From 1c08bab55ace2973f23f2bd7b307244ff305fcec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Fri, 9 Jan 2026 18:41:05 -0800 Subject: [PATCH] shaderc: Add WGSL support. (#3542) --- 3rdparty/dawn/LICENSE | 26 + 3rdparty/dawn/include/tint/tint.h | 85 + 3rdparty/dawn/include/webgpu/webgpu.h | 4887 ++++ .../dawn/src/tint/api/common/binding_point.h | 109 + 3rdparty/dawn/src/tint/api/common/bindings.h | 90 + .../dawn/src/tint/api/common/override_id.h | 84 + .../tint/api/common/resource_table_config.h | 98 + .../dawn/src/tint/api/common/resource_type.h | 71 + .../src/tint/api/common/subgroup_matrix.h | 113 + .../api/common/substitute_overrides_config.h | 53 + .../tint/api/common/vertex_pulling_config.cc | 44 + .../tint/api/common/vertex_pulling_config.h | 148 + .../src/tint/api/helpers/generate_bindings.cc | 174 + .../src/tint/api/helpers/generate_bindings.h | 54 + 3rdparty/dawn/src/tint/api/tint.cc | 116 + 3rdparty/dawn/src/tint/api/tint.h | 55 + 3rdparty/dawn/src/tint/lang/core/binary_op.cc | 74 + 3rdparty/dawn/src/tint/lang/core/binary_op.h | 72 + .../tint/lang/core/constant/clone_context.h | 51 + .../src/tint/lang/core/constant/composite.cc | 58 + .../src/tint/lang/core/constant/composite.h | 106 + .../dawn/src/tint/lang/core/constant/eval.cc | 3727 +++ .../dawn/src/tint/lang/core/constant/eval.h | 1349 + .../src/tint/lang/core/constant/invalid.cc | 45 + .../src/tint/lang/core/constant/invalid.h | 81 + .../src/tint/lang/core/constant/manager.cc | 197 + .../src/tint/lang/core/constant/manager.h | 181 + .../dawn/src/tint/lang/core/constant/node.cc | 40 + .../dawn/src/tint/lang/core/constant/node.h | 50 + .../src/tint/lang/core/constant/scalar.cc | 46 + .../dawn/src/tint/lang/core/constant/scalar.h | 125 + .../dawn/src/tint/lang/core/constant/splat.cc | 61 + .../dawn/src/tint/lang/core/constant/splat.h | 88 + .../src/tint/lang/core/constant/string.cc | 39 + .../dawn/src/tint/lang/core/constant/string.h | 89 + .../dawn/src/tint/lang/core/constant/value.cc | 114 + .../dawn/src/tint/lang/core/constant/value.h | 106 + 3rdparty/dawn/src/tint/lang/core/enums.cc | 2229 ++ 3rdparty/dawn/src/tint/lang/core/enums.h | 1389 + .../src/tint/lang/core/evaluation_stage.h | 75 + .../dawn/src/tint/lang/core/fluent_types.h | 294 + .../dawn/src/tint/lang/core/interpolation.h | 45 + .../src/tint/lang/core/intrinsic/ctor_conv.cc | 93 + .../src/tint/lang/core/intrinsic/ctor_conv.h | 133 + .../dawn/src/tint/lang/core/intrinsic/data.cc | 13850 +++++++++ .../src/tint/lang/core/intrinsic/dialect.h | 59 + .../src/tint/lang/core/intrinsic/table.cc | 895 + .../dawn/src/tint/lang/core/intrinsic/table.h | 401 + .../src/tint/lang/core/intrinsic/table_data.h | 678 + .../tint/lang/core/intrinsic/type_matchers.h | 824 + .../dawn/src/tint/lang/core/io_attributes.h | 104 + 3rdparty/dawn/src/tint/lang/core/ir/access.cc | 59 + 3rdparty/dawn/src/tint/lang/core/ir/access.h | 97 + .../core/ir/analysis/for_loop_analysis.cc | 124 + .../lang/core/ir/analysis/for_loop_analysis.h | 73 + .../ir/analysis/integer_range_analysis.cc | 1472 + .../core/ir/analysis/integer_range_analysis.h | 196 + .../lang/core/ir/analysis/loop_analysis.cc | 321 + .../lang/core/ir/analysis/loop_analysis.h | 73 + .../lang/core/ir/analysis/subgroup_matrix.cc | 169 + .../lang/core/ir/analysis/subgroup_matrix.h | 60 + 3rdparty/dawn/src/tint/lang/core/ir/binary.cc | 48 + 3rdparty/dawn/src/tint/lang/core/ir/binary.h | 101 + .../src/tint/lang/core/ir/binary/decode.cc | 2097 ++ .../src/tint/lang/core/ir/binary/decode.h | 53 + .../src/tint/lang/core/ir/binary/encode.cc | 1462 + .../src/tint/lang/core/ir/binary/encode.h | 55 + .../dawn/src/tint/lang/core/ir/bitcast.cc | 52 + 3rdparty/dawn/src/tint/lang/core/ir/bitcast.h | 80 + 3rdparty/dawn/src/tint/lang/core/ir/block.cc | 207 + 3rdparty/dawn/src/tint/lang/core/ir/block.h | 194 + .../dawn/src/tint/lang/core/ir/block_param.cc | 54 + .../dawn/src/tint/lang/core/ir/block_param.h | 69 + .../dawn/src/tint/lang/core/ir/break_if.cc | 90 + .../dawn/src/tint/lang/core/ir/break_if.h | 138 + .../dawn/src/tint/lang/core/ir/builder.cc | 154 + 3rdparty/dawn/src/tint/lang/core/ir/builder.h | 1978 ++ .../src/tint/lang/core/ir/builtin_call.cc | 48 + .../dawn/src/tint/lang/core/ir/builtin_call.h | 67 + 3rdparty/dawn/src/tint/lang/core/ir/call.cc | 38 + 3rdparty/dawn/src/tint/lang/core/ir/call.h | 84 + .../src/tint/lang/core/ir/clone_context.cc | 37 + .../src/tint/lang/core/ir/clone_context.h | 143 + .../lang/core/ir/const_param_validator.cc | 318 + .../tint/lang/core/ir/const_param_validator.h | 47 + .../dawn/src/tint/lang/core/ir/constant.cc | 46 + .../dawn/src/tint/lang/core/ir/constant.h | 56 + .../src/tint/lang/core/ir/constexpr_if.cc | 57 + .../dawn/src/tint/lang/core/ir/constexpr_if.h | 61 + .../dawn/src/tint/lang/core/ir/construct.cc | 54 + .../dawn/src/tint/lang/core/ir/construct.h | 71 + .../dawn/src/tint/lang/core/ir/continue.cc | 81 + .../dawn/src/tint/lang/core/ir/continue.h | 84 + .../tint/lang/core/ir/control_instruction.cc | 55 + .../tint/lang/core/ir/control_instruction.h | 83 + .../dawn/src/tint/lang/core/ir/convert.cc | 54 + 3rdparty/dawn/src/tint/lang/core/ir/convert.h | 72 + .../dawn/src/tint/lang/core/ir/core_binary.cc | 56 + .../dawn/src/tint/lang/core/ir/core_binary.h | 64 + .../tint/lang/core/ir/core_builtin_call.cc | 229 + .../src/tint/lang/core/ir/core_builtin_call.h | 89 + .../dawn/src/tint/lang/core/ir/core_unary.cc | 55 + .../dawn/src/tint/lang/core/ir/core_unary.h | 63 + .../src/tint/lang/core/ir/disassembler.cc | 1186 + .../dawn/src/tint/lang/core/ir/disassembler.h | 286 + .../dawn/src/tint/lang/core/ir/discard.cc | 47 + 3rdparty/dawn/src/tint/lang/core/ir/discard.h | 62 + .../dawn/src/tint/lang/core/ir/evaluator.cc | 382 + .../dawn/src/tint/lang/core/ir/evaluator.h | 99 + 3rdparty/dawn/src/tint/lang/core/ir/exit.cc | 58 + 3rdparty/dawn/src/tint/lang/core/ir/exit.h | 69 + .../dawn/src/tint/lang/core/ir/exit_if.cc | 68 + 3rdparty/dawn/src/tint/lang/core/ir/exit_if.h | 80 + .../dawn/src/tint/lang/core/ir/exit_loop.cc | 69 + .../dawn/src/tint/lang/core/ir/exit_loop.h | 80 + .../dawn/src/tint/lang/core/ir/exit_switch.cc | 69 + .../dawn/src/tint/lang/core/ir/exit_switch.h | 80 + .../dawn/src/tint/lang/core/ir/function.cc | 120 + .../dawn/src/tint/lang/core/ir/function.h | 276 + .../src/tint/lang/core/ir/function_param.cc | 54 + .../src/tint/lang/core/ir/function_param.h | 149 + 3rdparty/dawn/src/tint/lang/core/ir/if.cc | 111 + 3rdparty/dawn/src/tint/lang/core/ir/if.h | 120 + .../dawn/src/tint/lang/core/ir/instruction.cc | 83 + .../dawn/src/tint/lang/core/ir/instruction.h | 225 + .../tint/lang/core/ir/instruction_result.cc | 57 + .../tint/lang/core/ir/instruction_result.h | 70 + 3rdparty/dawn/src/tint/lang/core/ir/let.cc | 60 + 3rdparty/dawn/src/tint/lang/core/ir/let.h | 79 + 3rdparty/dawn/src/tint/lang/core/ir/load.cc | 66 + 3rdparty/dawn/src/tint/lang/core/ir/load.h | 80 + .../tint/lang/core/ir/load_vector_element.cc | 62 + .../tint/lang/core/ir/load_vector_element.h | 90 + 3rdparty/dawn/src/tint/lang/core/ir/loop.cc | 139 + 3rdparty/dawn/src/tint/lang/core/ir/loop.h | 141 + .../tint/lang/core/ir/member_builtin_call.cc | 58 + .../tint/lang/core/ir/member_builtin_call.h | 83 + 3rdparty/dawn/src/tint/lang/core/ir/module.cc | 186 + 3rdparty/dawn/src/tint/lang/core/ir/module.h | 225 + .../src/tint/lang/core/ir/multi_in_block.cc | 93 + .../src/tint/lang/core/ir/multi_in_block.h | 89 + .../src/tint/lang/core/ir/next_iteration.cc | 80 + .../src/tint/lang/core/ir/next_iteration.h | 85 + .../tint/lang/core/ir/operand_instruction.cc | 46 + .../tint/lang/core/ir/operand_instruction.h | 236 + .../dawn/src/tint/lang/core/ir/override.cc | 76 + .../dawn/src/tint/lang/core/ir/override.h | 85 + 3rdparty/dawn/src/tint/lang/core/ir/phony.cc | 48 + 3rdparty/dawn/src/tint/lang/core/ir/phony.h | 67 + .../tint/lang/core/ir/referenced_functions.h | 144 + .../lang/core/ir/referenced_module_decls.h | 258 + .../lang/core/ir/referenced_module_vars.h | 171 + .../dawn/src/tint/lang/core/ir/reflection.cc | 71 + .../dawn/src/tint/lang/core/ir/reflection.h | 55 + 3rdparty/dawn/src/tint/lang/core/ir/return.cc | 69 + 3rdparty/dawn/src/tint/lang/core/ir/return.h | 103 + 3rdparty/dawn/src/tint/lang/core/ir/store.cc | 56 + 3rdparty/dawn/src/tint/lang/core/ir/store.h | 95 + .../tint/lang/core/ir/store_vector_element.cc | 59 + .../tint/lang/core/ir/store_vector_element.h | 99 + 3rdparty/dawn/src/tint/lang/core/ir/switch.cc | 87 + 3rdparty/dawn/src/tint/lang/core/ir/switch.h | 145 + .../dawn/src/tint/lang/core/ir/swizzle.cc | 63 + 3rdparty/dawn/src/tint/lang/core/ir/swizzle.h | 98 + .../tint/lang/core/ir/terminate_invocation.cc | 45 + .../tint/lang/core/ir/terminate_invocation.h | 55 + .../dawn/src/tint/lang/core/ir/terminator.cc | 40 + .../dawn/src/tint/lang/core/ir/terminator.h | 65 + .../transform/array_length_from_immediate.cc | 365 + .../transform/array_length_from_immediate.h | 89 + .../ir/transform/array_length_from_uniform.cc | 375 + .../ir/transform/array_length_from_uniform.h | 77 + .../core/ir/transform/bgra8unorm_polyfill.cc | 250 + .../core/ir/transform/bgra8unorm_polyfill.h | 56 + .../lang/core/ir/transform/binary_polyfill.cc | 210 + .../lang/core/ir/transform/binary_polyfill.h | 69 + .../core/ir/transform/binding_remapper.cc | 83 + .../lang/core/ir/transform/binding_remapper.h | 63 + .../ir/transform/block_decorated_structs.cc | 129 + .../ir/transform/block_decorated_structs.h | 57 + .../core/ir/transform/builtin_polyfill.cc | 1231 + .../lang/core/ir/transform/builtin_polyfill.h | 142 + .../core/ir/transform/builtin_scalarize.cc | 145 + .../core/ir/transform/builtin_scalarize.h | 82 + .../transform/change_immediate_to_uniform.cc | 166 + .../transform/change_immediate_to_uniform.h | 61 + .../transform/combine_access_instructions.cc | 95 + .../transform/combine_access_instructions.h | 47 + .../core/ir/transform/conversion_polyfill.cc | 177 + .../core/ir/transform/conversion_polyfill.h | 67 + .../ir/transform/dead_code_elimination.cc | 116 + .../core/ir/transform/dead_code_elimination.h | 67 + .../ir/transform/decompose_uniform_access.cc | 624 + .../ir/transform/decompose_uniform_access.h | 49 + .../core/ir/transform/demote_to_helper.cc | 225 + .../lang/core/ir/transform/demote_to_helper.h | 62 + .../ir/transform/direct_variable_access.cc | 683 + .../ir/transform/direct_variable_access.h | 85 + .../transform/multiplanar_external_texture.cc | 612 + .../transform/multiplanar_external_texture.h | 61 + .../core/ir/transform/multiplanar_options.h | 58 + .../ir/transform/prepare_immediate_data.cc | 162 + .../ir/transform/prepare_immediate_data.h | 102 + .../core/ir/transform/preserve_padding.cc | 180 + .../lang/core/ir/transform/preserve_padding.h | 59 + .../ir/transform/prevent_infinite_loops.cc | 127 + .../ir/transform/prevent_infinite_loops.h | 57 + .../ir/transform/remove_continue_in_switch.cc | 138 + .../ir/transform/remove_continue_in_switch.h | 52 + .../ir/transform/remove_terminator_args.cc | 174 + .../ir/transform/remove_terminator_args.h | 68 + .../remove_uniform_vector_component_loads.cc | 93 + .../remove_uniform_vector_component_loads.h | 49 + .../core/ir/transform/rename_conflicts.cc | 311 + .../lang/core/ir/transform/rename_conflicts.h | 68 + .../lang/core/ir/transform/resource_table.cc | 212 + .../lang/core/ir/transform/resource_table.h | 73 + .../ir/transform/resource_table_helper.cc | 78 + .../core/ir/transform/resource_table_helper.h | 42 + .../tint/lang/core/ir/transform/robustness.cc | 578 + .../tint/lang/core/ir/transform/robustness.h | 96 + .../tint/lang/core/ir/transform/shader_io.cc | 266 + .../tint/lang/core/ir/transform/shader_io.h | 135 + .../ir/transform/signed_integer_polyfill.cc | 170 + .../ir/transform/signed_integer_polyfill.h | 65 + .../core/ir/transform/single_entry_point.cc | 114 + .../core/ir/transform/single_entry_point.h | 57 + .../src/tint/lang/core/ir/transform/std140.cc | 458 + .../src/tint/lang/core/ir/transform/std140.h | 61 + .../core/ir/transform/substitute_overrides.cc | 386 + .../core/ir/transform/substitute_overrides.h | 58 + .../lang/core/ir/transform/value_to_let.cc | 240 + .../lang/core/ir/transform/value_to_let.h | 83 + .../vectorize_scalar_matrix_constructors.cc | 105 + .../vectorize_scalar_matrix_constructors.h | 60 + .../lang/core/ir/transform/vertex_pulling.cc | 697 + .../lang/core/ir/transform/vertex_pulling.h | 64 + .../transform/zero_init_workgroup_memory.cc | 317 + .../ir/transform/zero_init_workgroup_memory.h | 56 + .../dawn/src/tint/lang/core/ir/traverse.h | 78 + .../src/tint/lang/core/ir/type/array_count.cc | 54 + .../src/tint/lang/core/ir/type/array_count.h | 67 + 3rdparty/dawn/src/tint/lang/core/ir/unary.cc | 46 + 3rdparty/dawn/src/tint/lang/core/ir/unary.h | 92 + .../dawn/src/tint/lang/core/ir/unreachable.cc | 45 + .../dawn/src/tint/lang/core/ir/unreachable.h | 60 + 3rdparty/dawn/src/tint/lang/core/ir/unused.cc | 45 + 3rdparty/dawn/src/tint/lang/core/ir/unused.h | 47 + .../dawn/src/tint/lang/core/ir/user_call.cc | 67 + .../dawn/src/tint/lang/core/ir/user_call.h | 95 + .../dawn/src/tint/lang/core/ir/validator.cc | 5244 ++++ .../dawn/src/tint/lang/core/ir/validator.h | 119 + 3rdparty/dawn/src/tint/lang/core/ir/value.cc | 84 + 3rdparty/dawn/src/tint/lang/core/ir/value.h | 170 + 3rdparty/dawn/src/tint/lang/core/ir/var.cc | 87 + 3rdparty/dawn/src/tint/lang/core/ir/var.h | 149 + 3rdparty/dawn/src/tint/lang/core/number.cc | 416 + 3rdparty/dawn/src/tint/lang/core/number.h | 787 + .../src/tint/lang/core/type/abstract_float.cc | 49 + .../src/tint/lang/core/type/abstract_float.h | 57 + .../src/tint/lang/core/type/abstract_int.cc | 49 + .../src/tint/lang/core/type/abstract_int.h | 57 + .../tint/lang/core/type/abstract_numeric.cc | 51 + .../tint/lang/core/type/abstract_numeric.h | 57 + .../dawn/src/tint/lang/core/type/array.cc | 135 + 3rdparty/dawn/src/tint/lang/core/type/array.h | 116 + .../src/tint/lang/core/type/array_count.cc | 76 + .../src/tint/lang/core/type/array_count.h | 111 + .../dawn/src/tint/lang/core/type/atomic.cc | 80 + .../dawn/src/tint/lang/core/type/atomic.h | 74 + .../src/tint/lang/core/type/binding_array.cc | 81 + .../src/tint/lang/core/type/binding_array.h | 84 + 3rdparty/dawn/src/tint/lang/core/type/bool.cc | 62 + 3rdparty/dawn/src/tint/lang/core/type/bool.h | 73 + .../dawn/src/tint/lang/core/type/buffer.cc | 70 + .../dawn/src/tint/lang/core/type/buffer.h | 81 + .../tint/lang/core/type/builtin_structs.cc | 198 + .../src/tint/lang/core/type/builtin_structs.h | 63 + .../src/tint/lang/core/type/clone_context.h | 60 + .../core/type/depth_multisampled_texture.cc | 68 + .../core/type/depth_multisampled_texture.h | 66 + .../src/tint/lang/core/type/depth_texture.cc | 70 + .../src/tint/lang/core/type/depth_texture.h | 66 + .../tint/lang/core/type/external_texture.cc | 55 + .../tint/lang/core/type/external_texture.h | 61 + 3rdparty/dawn/src/tint/lang/core/type/f16.cc | 63 + 3rdparty/dawn/src/tint/lang/core/type/f16.h | 63 + 3rdparty/dawn/src/tint/lang/core/type/f32.cc | 63 + 3rdparty/dawn/src/tint/lang/core/type/f32.h | 63 + .../dawn/src/tint/lang/core/type/function.cc | 53 + .../dawn/src/tint/lang/core/type/function.h | 61 + 3rdparty/dawn/src/tint/lang/core/type/i32.cc | 63 + 3rdparty/dawn/src/tint/lang/core/type/i32.h | 63 + 3rdparty/dawn/src/tint/lang/core/type/i8.cc | 50 + 3rdparty/dawn/src/tint/lang/core/type/i8.h | 62 + .../tint/lang/core/type/input_attachment.cc | 66 + .../tint/lang/core/type/input_attachment.h | 67 + .../dawn/src/tint/lang/core/type/invalid.cc | 61 + .../dawn/src/tint/lang/core/type/invalid.h | 67 + .../dawn/src/tint/lang/core/type/manager.cc | 421 + .../dawn/src/tint/lang/core/type/manager.h | 756 + .../dawn/src/tint/lang/core/type/matrix.cc | 100 + .../dawn/src/tint/lang/core/type/matrix.h | 101 + .../src/tint/lang/core/type/memory_view.cc | 50 + .../src/tint/lang/core/type/memory_view.h | 71 + .../lang/core/type/multisampled_texture.cc | 66 + .../lang/core/type/multisampled_texture.h | 70 + 3rdparty/dawn/src/tint/lang/core/type/node.cc | 40 + 3rdparty/dawn/src/tint/lang/core/type/node.h | 50 + .../src/tint/lang/core/type/numeric_scalar.cc | 38 + .../src/tint/lang/core/type/numeric_scalar.h | 51 + .../dawn/src/tint/lang/core/type/pointer.cc | 73 + .../dawn/src/tint/lang/core/type/pointer.h | 66 + .../dawn/src/tint/lang/core/type/reference.cc | 68 + .../dawn/src/tint/lang/core/type/reference.h | 64 + .../src/tint/lang/core/type/resource_type.cc | 183 + .../src/tint/lang/core/type/resource_type.h | 44 + .../tint/lang/core/type/sampled_texture.cc | 66 + .../src/tint/lang/core/type/sampled_texture.h | 70 + .../dawn/src/tint/lang/core/type/sampler.cc | 61 + .../dawn/src/tint/lang/core/type/sampler.h | 75 + .../src/tint/lang/core/type/sampler_kind.cc | 42 + .../src/tint/lang/core/type/sampler_kind.h | 59 + .../dawn/src/tint/lang/core/type/scalar.cc | 42 + .../dawn/src/tint/lang/core/type/scalar.h | 55 + .../tint/lang/core/type/storage_texture.cc | 70 + .../src/tint/lang/core/type/storage_texture.h | 89 + .../dawn/src/tint/lang/core/type/string.cc | 56 + .../dawn/src/tint/lang/core/type/string.h | 57 + .../dawn/src/tint/lang/core/type/struct.cc | 290 + .../dawn/src/tint/lang/core/type/struct.h | 295 + .../tint/lang/core/type/subgroup_matrix.cc | 95 + .../src/tint/lang/core/type/subgroup_matrix.h | 93 + .../src/tint/lang/core/type/texel_buffer.cc | 68 + .../src/tint/lang/core/type/texel_buffer.h | 84 + .../dawn/src/tint/lang/core/type/texture.cc | 74 + .../dawn/src/tint/lang/core/type/texture.h | 76 + .../tint/lang/core/type/texture_dimension.cc | 52 + .../tint/lang/core/type/texture_dimension.h | 69 + 3rdparty/dawn/src/tint/lang/core/type/type.cc | 299 + 3rdparty/dawn/src/tint/lang/core/type/type.h | 274 + 3rdparty/dawn/src/tint/lang/core/type/u32.cc | 63 + 3rdparty/dawn/src/tint/lang/core/type/u32.h | 63 + 3rdparty/dawn/src/tint/lang/core/type/u64.cc | 50 + 3rdparty/dawn/src/tint/lang/core/type/u64.h | 62 + 3rdparty/dawn/src/tint/lang/core/type/u8.cc | 50 + 3rdparty/dawn/src/tint/lang/core/type/u8.h | 62 + .../src/tint/lang/core/type/unique_node.cc | 36 + .../src/tint/lang/core/type/unique_node.h | 84 + .../dawn/src/tint/lang/core/type/vector.cc | 113 + .../dawn/src/tint/lang/core/type/vector.h | 99 + 3rdparty/dawn/src/tint/lang/core/type/void.cc | 52 + 3rdparty/dawn/src/tint/lang/core/type/void.h | 61 + 3rdparty/dawn/src/tint/lang/core/unary_op.cc | 47 + 3rdparty/dawn/src/tint/lang/core/unary_op.h | 60 + .../tint/lang/null/writer/common/options.cc | 40 + .../tint/lang/null/writer/common/options.h | 64 + .../tint/lang/null/writer/common/output.cc | 40 + .../src/tint/lang/null/writer/common/output.h | 70 + .../src/tint/lang/null/writer/raise/raise.cc | 43 + .../src/tint/lang/null/writer/raise/raise.h | 49 + .../dawn/src/tint/lang/null/writer/writer.cc | 54 + .../dawn/src/tint/lang/null/writer/writer.h | 51 + .../dawn/src/tint/lang/spirv/builtin_fn.cc | 397 + .../dawn/src/tint/lang/spirv/builtin_fn.h | 186 + .../src/tint/lang/spirv/intrinsic/data.cc | 12709 ++++++++ .../src/tint/lang/spirv/intrinsic/dialect.h | 51 + .../tint/lang/spirv/intrinsic/type_matchers.h | 136 + .../dawn/src/tint/lang/spirv/ir/binary.cc | 53 + 3rdparty/dawn/src/tint/lang/spirv/ir/binary.h | 66 + .../src/tint/lang/spirv/ir/builtin_call.cc | 69 + .../src/tint/lang/spirv/ir/builtin_call.h | 82 + .../src/tint/lang/spirv/ir/copy_logical.cc | 56 + .../src/tint/lang/spirv/ir/copy_logical.h | 73 + .../src/tint/lang/spirv/ir/literal_operand.cc | 38 + .../src/tint/lang/spirv/ir/literal_operand.h | 49 + .../tint/lang/spirv/reader/common/common.cc | 33 + .../tint/lang/spirv/reader/common/options.h | 56 + .../tint/lang/spirv/reader/lower/atomics.cc | 570 + .../tint/lang/spirv/reader/lower/atomics.h | 48 + .../tint/lang/spirv/reader/lower/builtins.cc | 1327 + .../tint/lang/spirv/reader/lower/builtins.h | 48 + .../reader/lower/decompose_strided_array.cc | 267 + .../reader/lower/decompose_strided_array.h | 48 + .../reader/lower/decompose_strided_matrix.cc | 380 + .../reader/lower/decompose_strided_matrix.h | 48 + .../src/tint/lang/spirv/reader/lower/lower.cc | 79 + .../src/tint/lang/spirv/reader/lower/lower.h | 43 + .../tint/lang/spirv/reader/lower/shader_io.cc | 759 + .../tint/lang/spirv/reader/lower/shader_io.h | 48 + .../tint/lang/spirv/reader/lower/texture.cc | 1046 + .../tint/lang/spirv/reader/lower/texture.h | 48 + .../spirv/reader/lower/transpose_row_major.cc | 773 + .../spirv/reader/lower/transpose_row_major.h | 49 + .../reader/lower/vector_element_pointer.cc | 176 + .../reader/lower/vector_element_pointer.h | 48 + .../tint/lang/spirv/reader/parser/parser.cc | 4657 +++ .../tint/lang/spirv/reader/parser/parser.h | 52 + .../dawn/src/tint/lang/spirv/reader/reader.cc | 54 + .../dawn/src/tint/lang/spirv/reader/reader.h | 52 + .../lang/spirv/type/explicit_layout_array.cc | 70 + .../lang/spirv/type/explicit_layout_array.h | 79 + .../dawn/src/tint/lang/spirv/type/image.cc | 169 + .../dawn/src/tint/lang/spirv/type/image.h | 127 + .../tint/lang/spirv/type/resource_table.cc | 71 + .../src/tint/lang/spirv/type/resource_table.h | 73 + .../src/tint/lang/spirv/type/sampled_image.cc | 59 + .../src/tint/lang/spirv/type/sampled_image.h | 66 + .../src/tint/lang/spirv/validate/validate.cc | 98 + .../src/tint/lang/spirv/validate/validate.h | 45 + .../lang/spirv/writer/common/binary_writer.cc | 93 + .../lang/spirv/writer/common/binary_writer.h | 74 + .../tint/lang/spirv/writer/common/function.cc | 174 + .../tint/lang/spirv/writer/common/function.h | 137 + .../lang/spirv/writer/common/instruction.cc | 51 + .../lang/spirv/writer/common/instruction.h | 73 + .../tint/lang/spirv/writer/common/module.cc | 123 + .../tint/lang/spirv/writer/common/module.h | 198 + .../tint/lang/spirv/writer/common/operand.cc | 42 + .../tint/lang/spirv/writer/common/operand.h | 59 + .../lang/spirv/writer/common/option_helper.cc | 234 + .../lang/spirv/writer/common/option_helpers.h | 58 + .../tint/lang/spirv/writer/common/options.h | 258 + .../tint/lang/spirv/writer/common/output.cc | 40 + .../tint/lang/spirv/writer/common/output.h | 84 + .../tint/lang/spirv/writer/printer/printer.cc | 3042 ++ .../tint/lang/spirv/writer/printer/printer.h | 59 + .../spirv/writer/raise/builtin_polyfill.cc | 1447 + .../spirv/writer/raise/builtin_polyfill.h | 59 + .../writer/raise/case_switch_to_if_else.cc | 164 + .../writer/raise/case_switch_to_if_else.h | 48 + .../writer/raise/expand_implicit_splats.cc | 146 + .../writer/raise/expand_implicit_splats.h | 59 + .../raise/fork_explicit_layout_types.cc | 381 + .../writer/raise/fork_explicit_layout_types.h | 63 + .../writer/raise/handle_matrix_arithmetic.cc | 174 + .../writer/raise/handle_matrix_arithmetic.h | 57 + .../raise/keep_binding_array_as_pointer.cc | 102 + .../raise/keep_binding_array_as_pointer.h | 64 + .../lang/spirv/writer/raise/merge_return.cc | 284 + .../lang/spirv/writer/raise/merge_return.h | 48 + .../writer/raise/pass_matrix_by_pointer.cc | 138 + .../writer/raise/pass_matrix_by_pointer.h | 49 + .../src/tint/lang/spirv/writer/raise/raise.cc | 247 + .../src/tint/lang/spirv/writer/raise/raise.h | 49 + .../remove_unreachable_in_loop_continuing.cc | 105 + .../remove_unreachable_in_loop_continuing.h | 57 + .../lang/spirv/writer/raise/resource_table.cc | 58 + .../lang/spirv/writer/raise/resource_table.h | 51 + .../tint/lang/spirv/writer/raise/shader_io.cc | 336 + .../tint/lang/spirv/writer/raise/shader_io.h | 76 + .../lang/spirv/writer/raise/unary_polyfill.cc | 121 + .../lang/spirv/writer/raise/unary_polyfill.h | 65 + .../writer/raise/var_for_dynamic_index.cc | 260 + .../writer/raise/var_for_dynamic_index.h | 61 + .../dawn/src/tint/lang/spirv/writer/writer.cc | 182 + .../dawn/src/tint/lang/spirv/writer/writer.h | 53 + .../src/tint/lang/wgsl/allowed_features.h | 70 + .../tint/lang/wgsl/ast/accessor_expression.cc | 43 + .../tint/lang/wgsl/ast/accessor_expression.h | 53 + 3rdparty/dawn/src/tint/lang/wgsl/ast/alias.cc | 43 + 3rdparty/dawn/src/tint/lang/wgsl/ast/alias.h | 57 + .../lang/wgsl/ast/assignment_statement.cc | 47 + .../tint/lang/wgsl/ast/assignment_statement.h | 61 + .../dawn/src/tint/lang/wgsl/ast/attribute.cc | 36 + .../dawn/src/tint/lang/wgsl/ast/attribute.h | 79 + .../tint/lang/wgsl/ast/binary_expression.cc | 48 + .../tint/lang/wgsl/ast/binary_expression.h | 291 + .../tint/lang/wgsl/ast/binding_attribute.cc | 47 + .../tint/lang/wgsl/ast/binding_attribute.h | 57 + .../tint/lang/wgsl/ast/blend_src_attribute.cc | 47 + .../tint/lang/wgsl/ast/blend_src_attribute.h | 57 + .../src/tint/lang/wgsl/ast/block_statement.cc | 51 + .../src/tint/lang/wgsl/ast/block_statement.h | 75 + .../lang/wgsl/ast/bool_literal_expression.cc | 41 + .../lang/wgsl/ast/bool_literal_expression.h | 53 + .../tint/lang/wgsl/ast/break_if_statement.cc | 43 + .../tint/lang/wgsl/ast/break_if_statement.h | 56 + .../src/tint/lang/wgsl/ast/break_statement.cc | 40 + .../src/tint/lang/wgsl/ast/break_statement.h | 49 + .../dawn/src/tint/lang/wgsl/ast/builder.cc | 100 + .../dawn/src/tint/lang/wgsl/ast/builder.h | 3621 +++ .../tint/lang/wgsl/ast/builtin_attribute.cc | 50 + .../tint/lang/wgsl/ast/builtin_attribute.h | 63 + .../src/tint/lang/wgsl/ast/call_expression.cc | 51 + .../src/tint/lang/wgsl/ast/call_expression.h | 70 + .../src/tint/lang/wgsl/ast/call_statement.cc | 43 + .../src/tint/lang/wgsl/ast/call_statement.h | 54 + .../src/tint/lang/wgsl/ast/case_selector.cc | 43 + .../src/tint/lang/wgsl/ast/case_selector.h | 59 + .../src/tint/lang/wgsl/ast/case_statement.cc | 61 + .../src/tint/lang/wgsl/ast/case_statement.h | 66 + .../src/tint/lang/wgsl/ast/color_attribute.cc | 49 + .../src/tint/lang/wgsl/ast/color_attribute.h | 61 + .../wgsl/ast/compound_assignment_statement.cc | 48 + .../wgsl/ast/compound_assignment_statement.h | 67 + 3rdparty/dawn/src/tint/lang/wgsl/ast/const.cc | 54 + 3rdparty/dawn/src/tint/lang/wgsl/ast/const.h | 70 + .../src/tint/lang/wgsl/ast/const_assert.cc | 43 + .../src/tint/lang/wgsl/ast/const_assert.h | 54 + .../tint/lang/wgsl/ast/continue_statement.cc | 40 + .../tint/lang/wgsl/ast/continue_statement.h | 49 + .../lang/wgsl/ast/diagnostic_attribute.cc | 48 + .../tint/lang/wgsl/ast/diagnostic_attribute.h | 57 + .../tint/lang/wgsl/ast/diagnostic_control.cc | 47 + .../tint/lang/wgsl/ast/diagnostic_control.h | 67 + .../lang/wgsl/ast/diagnostic_directive.cc | 41 + .../tint/lang/wgsl/ast/diagnostic_directive.h | 62 + .../lang/wgsl/ast/diagnostic_rule_name.cc | 73 + .../tint/lang/wgsl/ast/diagnostic_rule_name.h | 75 + .../tint/lang/wgsl/ast/discard_statement.cc | 40 + .../tint/lang/wgsl/ast/discard_statement.h | 49 + .../dawn/src/tint/lang/wgsl/ast/enable.cc | 50 + 3rdparty/dawn/src/tint/lang/wgsl/ast/enable.h | 65 + .../dawn/src/tint/lang/wgsl/ast/expression.cc | 38 + .../dawn/src/tint/lang/wgsl/ast/expression.h | 52 + .../dawn/src/tint/lang/wgsl/ast/extension.cc | 46 + .../dawn/src/tint/lang/wgsl/ast/extension.h | 57 + .../lang/wgsl/ast/float_literal_expression.cc | 57 + .../lang/wgsl/ast/float_literal_expression.h | 81 + .../tint/lang/wgsl/ast/for_loop_statement.cc | 60 + .../tint/lang/wgsl/ast/for_loop_statement.h | 77 + .../dawn/src/tint/lang/wgsl/ast/function.cc | 105 + .../dawn/src/tint/lang/wgsl/ast/function.h | 129 + .../src/tint/lang/wgsl/ast/group_attribute.cc | 47 + .../src/tint/lang/wgsl/ast/group_attribute.h | 57 + .../src/tint/lang/wgsl/ast/id_attribute.cc | 47 + .../src/tint/lang/wgsl/ast/id_attribute.h | 57 + .../dawn/src/tint/lang/wgsl/ast/identifier.cc | 42 + .../dawn/src/tint/lang/wgsl/ast/identifier.h | 54 + .../lang/wgsl/ast/identifier_expression.cc | 43 + .../lang/wgsl/ast/identifier_expression.h | 58 + .../src/tint/lang/wgsl/ast/if_statement.cc | 59 + .../src/tint/lang/wgsl/ast/if_statement.h | 73 + .../wgsl/ast/increment_decrement_statement.cc | 44 + .../wgsl/ast/increment_decrement_statement.h | 58 + .../wgsl/ast/index_accessor_expression.cc | 46 + .../lang/wgsl/ast/index_accessor_expression.h | 57 + .../ast/input_attachment_index_attribute.cc | 49 + .../ast/input_attachment_index_attribute.h | 62 + .../lang/wgsl/ast/int_literal_expression.cc | 52 + .../lang/wgsl/ast/int_literal_expression.h | 80 + .../lang/wgsl/ast/interpolate_attribute.cc | 50 + .../lang/wgsl/ast/interpolate_attribute.h | 57 + .../tint/lang/wgsl/ast/invariant_attribute.cc | 44 + .../tint/lang/wgsl/ast/invariant_attribute.h | 52 + 3rdparty/dawn/src/tint/lang/wgsl/ast/let.cc | 54 + 3rdparty/dawn/src/tint/lang/wgsl/ast/let.h | 68 + .../tint/lang/wgsl/ast/literal_expression.cc | 38 + .../tint/lang/wgsl/ast/literal_expression.h | 51 + .../tint/lang/wgsl/ast/location_attribute.cc | 47 + .../tint/lang/wgsl/ast/location_attribute.h | 57 + .../src/tint/lang/wgsl/ast/loop_statement.cc | 52 + .../src/tint/lang/wgsl/ast/loop_statement.h | 64 + .../wgsl/ast/member_accessor_expression.cc | 51 + .../wgsl/ast/member_accessor_expression.h | 59 + .../dawn/src/tint/lang/wgsl/ast/module.cc | 132 + 3rdparty/dawn/src/tint/lang/wgsl/ast/module.h | 173 + .../tint/lang/wgsl/ast/must_use_attribute.cc | 44 + .../tint/lang/wgsl/ast/must_use_attribute.h | 52 + 3rdparty/dawn/src/tint/lang/wgsl/ast/node.cc | 38 + 3rdparty/dawn/src/tint/lang/wgsl/ast/node.h | 68 + .../dawn/src/tint/lang/wgsl/ast/node_id.h | 55 + .../dawn/src/tint/lang/wgsl/ast/override.cc | 52 + .../dawn/src/tint/lang/wgsl/ast/override.h | 71 + .../dawn/src/tint/lang/wgsl/ast/parameter.cc | 51 + .../dawn/src/tint/lang/wgsl/ast/parameter.h | 70 + .../tint/lang/wgsl/ast/phony_expression.cc | 40 + .../src/tint/lang/wgsl/ast/phony_expression.h | 50 + .../src/tint/lang/wgsl/ast/pipeline_stage.cc | 46 + .../src/tint/lang/wgsl/ast/pipeline_stage.h | 54 + .../dawn/src/tint/lang/wgsl/ast/requires.cc | 41 + .../dawn/src/tint/lang/wgsl/ast/requires.h | 66 + .../tint/lang/wgsl/ast/return_statement.cc | 43 + .../src/tint/lang/wgsl/ast/return_statement.h | 59 + .../src/tint/lang/wgsl/ast/stage_attribute.cc | 57 + .../src/tint/lang/wgsl/ast/stage_attribute.h | 57 + .../dawn/src/tint/lang/wgsl/ast/statement.cc | 89 + .../dawn/src/tint/lang/wgsl/ast/statement.h | 54 + .../dawn/src/tint/lang/wgsl/ast/struct.cc | 54 + 3rdparty/dawn/src/tint/lang/wgsl/ast/struct.h | 68 + .../src/tint/lang/wgsl/ast/struct_member.cc | 55 + .../src/tint/lang/wgsl/ast/struct_member.h | 73 + .../wgsl/ast/struct_member_align_attribute.cc | 49 + .../wgsl/ast/struct_member_align_attribute.h | 58 + .../wgsl/ast/struct_member_size_attribute.cc | 49 + .../wgsl/ast/struct_member_size_attribute.h | 58 + .../lang/wgsl/ast/subgroup_size_attribute.cc | 49 + .../lang/wgsl/ast/subgroup_size_attribute.h | 65 + .../tint/lang/wgsl/ast/switch_statement.cc | 63 + .../src/tint/lang/wgsl/ast/switch_statement.h | 72 + .../lang/wgsl/ast/templated_identifier.cc | 51 + .../tint/lang/wgsl/ast/templated_identifier.h | 64 + .../tint/lang/wgsl/ast/traverse_expressions.h | 177 + 3rdparty/dawn/src/tint/lang/wgsl/ast/type.h | 55 + .../dawn/src/tint/lang/wgsl/ast/type_decl.cc | 45 + .../dawn/src/tint/lang/wgsl/ast/type_decl.h | 58 + .../tint/lang/wgsl/ast/unary_op_expression.cc | 46 + .../tint/lang/wgsl/ast/unary_op_expression.h | 58 + 3rdparty/dawn/src/tint/lang/wgsl/ast/var.cc | 54 + 3rdparty/dawn/src/tint/lang/wgsl/ast/var.h | 93 + .../dawn/src/tint/lang/wgsl/ast/variable.cc | 52 + .../dawn/src/tint/lang/wgsl/ast/variable.h | 108 + .../lang/wgsl/ast/variable_decl_statement.cc | 43 + .../lang/wgsl/ast/variable_decl_statement.h | 54 + .../src/tint/lang/wgsl/ast/while_statement.cc | 54 + .../src/tint/lang/wgsl/ast/while_statement.h | 67 + .../tint/lang/wgsl/ast/workgroup_attribute.cc | 51 + .../tint/lang/wgsl/ast/workgroup_attribute.h | 76 + 3rdparty/dawn/src/tint/lang/wgsl/enums.cc | 1255 + 3rdparty/dawn/src/tint/lang/wgsl/enums.h | 899 + .../dawn/src/tint/lang/wgsl/feature_status.cc | 85 + .../dawn/src/tint/lang/wgsl/feature_status.h | 63 + .../tint/lang/wgsl/inspector/entry_point.cc | 41 + .../tint/lang/wgsl/inspector/entry_point.h | 224 + .../src/tint/lang/wgsl/inspector/inspector.cc | 1100 + .../src/tint/lang/wgsl/inspector/inspector.h | 241 + .../lang/wgsl/inspector/resource_binding.cc | 175 + .../lang/wgsl/inspector/resource_binding.h | 176 + .../wgsl/inspector/resource_binding_info.h | 52 + .../src/tint/lang/wgsl/inspector/scalar.cc | 86 + .../src/tint/lang/wgsl/inspector/scalar.h | 91 + .../src/tint/lang/wgsl/intrinsic/ctor_conv.cc | 87 + .../src/tint/lang/wgsl/intrinsic/ctor_conv.h | 129 + .../dawn/src/tint/lang/wgsl/intrinsic/data.cc | 15327 ++++++++++ .../src/tint/lang/wgsl/intrinsic/dialect.h | 59 + .../tint/lang/wgsl/intrinsic/type_matchers.h | 46 + .../src/tint/lang/wgsl/ir/builtin_call.cc | 57 + .../dawn/src/tint/lang/wgsl/ir/builtin_call.h | 79 + 3rdparty/dawn/src/tint/lang/wgsl/ir/unary.cc | 55 + 3rdparty/dawn/src/tint/lang/wgsl/ir/unary.h | 63 + .../src/tint/lang/wgsl/program/program.cc | 126 + .../dawn/src/tint/lang/wgsl/program/program.h | 158 + .../tint/lang/wgsl/program/program_builder.cc | 82 + .../tint/lang/wgsl/program/program_builder.h | 203 + .../src/tint/lang/wgsl/reader/lower/lower.cc | 270 + .../src/tint/lang/wgsl/reader/lower/lower.h | 43 + .../dawn/src/tint/lang/wgsl/reader/options.h | 47 + .../reader/parser/classify_template_args.cc | 157 + .../reader/parser/classify_template_args.h | 41 + .../src/tint/lang/wgsl/reader/parser/detail.h | 77 + .../src/tint/lang/wgsl/reader/parser/lexer.cc | 1343 + .../src/tint/lang/wgsl/reader/parser/lexer.h | 134 + .../tint/lang/wgsl/reader/parser/parser.cc | 3542 +++ .../src/tint/lang/wgsl/reader/parser/parser.h | 927 + .../src/tint/lang/wgsl/reader/parser/token.cc | 290 + .../src/tint/lang/wgsl/reader/parser/token.h | 382 + .../reader/program_to_ir/program_to_ir.cc | 1408 + .../wgsl/reader/program_to_ir/program_to_ir.h | 52 + .../dawn/src/tint/lang/wgsl/reader/reader.cc | 80 + .../dawn/src/tint/lang/wgsl/reader/reader.h | 75 + .../dawn/src/tint/lang/wgsl/reserved_words.cc | 95 + .../dawn/src/tint/lang/wgsl/reserved_words.h | 52 + .../lang/wgsl/resolver/dependency_graph.cc | 856 + .../lang/wgsl/resolver/dependency_graph.h | 191 + .../lang/wgsl/resolver/incomplete_type.cc | 63 + .../tint/lang/wgsl/resolver/incomplete_type.h | 76 + .../src/tint/lang/wgsl/resolver/resolve.cc | 42 + .../src/tint/lang/wgsl/resolver/resolve.h | 49 + .../src/tint/lang/wgsl/resolver/resolver.cc | 5018 ++++ .../src/tint/lang/wgsl/resolver/resolver.h | 710 + .../src/tint/lang/wgsl/resolver/sem_helper.cc | 237 + .../src/tint/lang/wgsl/resolver/sem_helper.h | 265 + .../src/tint/lang/wgsl/resolver/uniformity.cc | 2341 ++ .../src/tint/lang/wgsl/resolver/uniformity.h | 55 + .../wgsl/resolver/unresolved_identifier.cc | 40 + .../wgsl/resolver/unresolved_identifier.h | 55 + .../src/tint/lang/wgsl/resolver/validator.cc | 3513 +++ .../src/tint/lang/wgsl/resolver/validator.h | 679 + .../tint/lang/wgsl/sem/accessor_expression.cc | 45 + .../tint/lang/wgsl/sem/accessor_expression.h | 69 + 3rdparty/dawn/src/tint/lang/wgsl/sem/array.cc | 48 + 3rdparty/dawn/src/tint/lang/wgsl/sem/array.h | 69 + .../src/tint/lang/wgsl/sem/array_count.cc | 76 + .../dawn/src/tint/lang/wgsl/sem/array_count.h | 110 + .../dawn/src/tint/lang/wgsl/sem/behavior.cc | 46 + .../dawn/src/tint/lang/wgsl/sem/behavior.h | 63 + .../src/tint/lang/wgsl/sem/block_statement.cc | 73 + .../src/tint/lang/wgsl/sem/block_statement.h | 113 + .../tint/lang/wgsl/sem/break_if_statement.cc | 47 + .../tint/lang/wgsl/sem/break_if_statement.h | 73 + .../lang/wgsl/sem/builtin_enum_expression.cc | 52 + .../lang/wgsl/sem/builtin_enum_expression.h | 80 + .../dawn/src/tint/lang/wgsl/sem/builtin_fn.cc | 119 + .../dawn/src/tint/lang/wgsl/sem/builtin_fn.h | 125 + 3rdparty/dawn/src/tint/lang/wgsl/sem/call.cc | 52 + 3rdparty/dawn/src/tint/lang/wgsl/sem/call.h | 79 + .../src/tint/lang/wgsl/sem/call_target.cc | 95 + .../dawn/src/tint/lang/wgsl/sem/call_target.h | 136 + .../dawn/src/tint/lang/wgsl/sem/expression.cc | 39 + .../dawn/src/tint/lang/wgsl/sem/expression.h | 68 + .../tint/lang/wgsl/sem/for_loop_statement.cc | 47 + .../tint/lang/wgsl/sem/for_loop_statement.h | 73 + .../dawn/src/tint/lang/wgsl/sem/function.cc | 68 + .../dawn/src/tint/lang/wgsl/sem/function.h | 254 + .../tint/lang/wgsl/sem/function_expression.cc | 42 + .../tint/lang/wgsl/sem/function_expression.h | 67 + .../src/tint/lang/wgsl/sem/if_statement.cc | 43 + .../src/tint/lang/wgsl/sem/if_statement.h | 70 + .../wgsl/sem/index_accessor_expression.cc | 48 + .../lang/wgsl/sem/index_accessor_expression.h | 69 + 3rdparty/dawn/src/tint/lang/wgsl/sem/info.cc | 101 + 3rdparty/dawn/src/tint/lang/wgsl/sem/info.h | 150 + 3rdparty/dawn/src/tint/lang/wgsl/sem/load.cc | 49 + 3rdparty/dawn/src/tint/lang/wgsl/sem/load.h | 58 + .../src/tint/lang/wgsl/sem/loop_statement.cc | 61 + .../src/tint/lang/wgsl/sem/loop_statement.h | 76 + .../src/tint/lang/wgsl/sem/materialize.cc | 48 + .../dawn/src/tint/lang/wgsl/sem/materialize.h | 65 + .../wgsl/sem/member_accessor_expression.cc | 62 + .../wgsl/sem/member_accessor_expression.h | 107 + .../dawn/src/tint/lang/wgsl/sem/module.cc | 45 + 3rdparty/dawn/src/tint/lang/wgsl/sem/module.h | 78 + 3rdparty/dawn/src/tint/lang/wgsl/sem/node.cc | 40 + 3rdparty/dawn/src/tint/lang/wgsl/sem/node.h | 50 + .../tint/lang/wgsl/sem/pipeline_stage_set.h | 41 + .../tint/lang/wgsl/sem/sampler_texture_pair.h | 102 + .../dawn/src/tint/lang/wgsl/sem/statement.cc | 67 + .../dawn/src/tint/lang/wgsl/sem/statement.h | 225 + .../dawn/src/tint/lang/wgsl/sem/struct.cc | 61 + 3rdparty/dawn/src/tint/lang/wgsl/sem/struct.h | 116 + .../tint/lang/wgsl/sem/switch_statement.cc | 71 + .../src/tint/lang/wgsl/sem/switch_statement.h | 138 + .../src/tint/lang/wgsl/sem/type_expression.cc | 41 + .../src/tint/lang/wgsl/sem/type_expression.h | 67 + .../src/tint/lang/wgsl/sem/type_mappings.h | 120 + .../tint/lang/wgsl/sem/value_constructor.cc | 43 + .../tint/lang/wgsl/sem/value_constructor.h | 53 + .../tint/lang/wgsl/sem/value_conversion.cc | 41 + .../src/tint/lang/wgsl/sem/value_conversion.h | 52 + .../tint/lang/wgsl/sem/value_expression.cc | 82 + .../src/tint/lang/wgsl/sem/value_expression.h | 101 + .../dawn/src/tint/lang/wgsl/sem/variable.cc | 95 + .../dawn/src/tint/lang/wgsl/sem/variable.h | 284 + .../src/tint/lang/wgsl/sem/while_statement.cc | 47 + .../src/tint/lang/wgsl/sem/while_statement.h | 73 + .../wgsl/writer/ast_printer/ast_printer.cc | 1085 + .../wgsl/writer/ast_printer/ast_printer.h | 263 + .../tint/lang/wgsl/writer/common/common.cc | 33 + .../tint/lang/wgsl/writer/common/options.h | 58 + .../writer/ir_to_program/ir_to_program.cc | 1428 + .../wgsl/writer/ir_to_program/ir_to_program.h | 49 + .../dawn/src/tint/lang/wgsl/writer/output.cc | 38 + .../dawn/src/tint/lang/wgsl/writer/output.h | 52 + .../tint/lang/wgsl/writer/raise/ptr_to_ref.cc | 156 + .../tint/lang/wgsl/writer/raise/ptr_to_ref.h | 48 + .../src/tint/lang/wgsl/writer/raise/raise.cc | 288 + .../src/tint/lang/wgsl/writer/raise/raise.h | 43 + .../lang/wgsl/writer/raise/value_to_let.cc | 214 + .../lang/wgsl/writer/raise/value_to_let.h | 54 + .../dawn/src/tint/lang/wgsl/writer/writer.cc | 69 + .../dawn/src/tint/lang/wgsl/writer/writer.h | 65 + 3rdparty/dawn/src/tint/tint.natvis | 272 + .../src/tint/utils/bytes/buffer_reader.cc | 53 + .../dawn/src/tint/utils/bytes/buffer_reader.h | 81 + 3rdparty/dawn/src/tint/utils/bytes/decoder.h | 273 + .../dawn/src/tint/utils/bytes/endianness.h | 52 + 3rdparty/dawn/src/tint/utils/bytes/reader.cc | 34 + 3rdparty/dawn/src/tint/utils/bytes/reader.h | 116 + 3rdparty/dawn/src/tint/utils/bytes/swap.h | 64 + .../dawn/src/tint/utils/containers/bitset.h | 134 + .../src/tint/utils/containers/containers.cc | 33 + .../dawn/src/tint/utils/containers/enum_set.h | 276 + .../tint/utils/containers/filtered_iterator.h | 135 + .../dawn/src/tint/utils/containers/hashmap.h | 365 + .../src/tint/utils/containers/hashmap_base.h | 693 + .../dawn/src/tint/utils/containers/hashset.h | 122 + 3rdparty/dawn/src/tint/utils/containers/map.h | 69 + .../src/tint/utils/containers/predicates.h | 91 + .../dawn/src/tint/utils/containers/reverse.h | 77 + .../src/tint/utils/containers/scope_stack.h | 113 + .../dawn/src/tint/utils/containers/slice.h | 311 + .../src/tint/utils/containers/transform.h | 191 + .../tint/utils/containers/unique_allocator.h | 138 + .../src/tint/utils/containers/unique_vector.h | 162 + .../dawn/src/tint/utils/containers/vector.h | 1331 + .../src/tint/utils/diagnostic/diagnostic.cc | 86 + .../src/tint/utils/diagnostic/diagnostic.h | 270 + .../src/tint/utils/diagnostic/formatter.cc | 208 + .../src/tint/utils/diagnostic/formatter.h | 84 + .../dawn/src/tint/utils/diagnostic/source.cc | 216 + .../dawn/src/tint/utils/diagnostic/source.h | 283 + 3rdparty/dawn/src/tint/utils/ice/debugger.cc | 75 + 3rdparty/dawn/src/tint/utils/ice/debugger.h | 40 + 3rdparty/dawn/src/tint/utils/ice/ice.cc | 81 + 3rdparty/dawn/src/tint/utils/ice/ice.h | 128 + .../dawn/src/tint/utils/internal_limits.h | 58 + .../dawn/src/tint/utils/macros/compiler.h | 307 + 3rdparty/dawn/src/tint/utils/macros/concat.h | 35 + 3rdparty/dawn/src/tint/utils/macros/defer.h | 73 + 3rdparty/dawn/src/tint/utils/macros/foreach.h | 521 + 3rdparty/dawn/src/tint/utils/macros/macros.cc | 33 + .../src/tint/utils/macros/scoped_assignment.h | 74 + .../dawn/src/tint/utils/macros/static_init.h | 44 + 3rdparty/dawn/src/tint/utils/math/crc32.h | 143 + 3rdparty/dawn/src/tint/utils/math/hash.h | 339 + 3rdparty/dawn/src/tint/utils/math/math.cc | 35 + 3rdparty/dawn/src/tint/utils/math/math.h | 116 + .../src/tint/utils/memory/aligned_storage.h | 58 + 3rdparty/dawn/src/tint/utils/memory/bitcast.h | 71 + .../src/tint/utils/memory/block_allocator.h | 330 + .../src/tint/utils/memory/bump_allocator.h | 158 + 3rdparty/dawn/src/tint/utils/memory/memory.cc | 33 + .../dawn/src/tint/utils/protos/ir/ir.pb.cc | 21506 ++++++++++++++ .../dawn/src/tint/utils/protos/ir/ir.pb.h | 23930 ++++++++++++++++ 3rdparty/dawn/src/tint/utils/reflection.cc | 65 + 3rdparty/dawn/src/tint/utils/reflection.h | 237 + 3rdparty/dawn/src/tint/utils/result.cc | 40 + 3rdparty/dawn/src/tint/utils/result.h | 261 + 3rdparty/dawn/src/tint/utils/rtti/castable.cc | 43 + 3rdparty/dawn/src/tint/utils/rtti/castable.h | 568 + 3rdparty/dawn/src/tint/utils/rtti/ignore.h | 61 + 3rdparty/dawn/src/tint/utils/rtti/switch.cc | 41 + 3rdparty/dawn/src/tint/utils/rtti/switch.h | 380 + 3rdparty/dawn/src/tint/utils/rtti/traits.h | 189 + .../src/tint/utils/strconv/float_to_string.cc | 193 + .../src/tint/utils/strconv/float_to_string.h | 63 + .../dawn/src/tint/utils/strconv/parse_num.cc | 115 + .../dawn/src/tint/utils/strconv/parse_num.h | 145 + .../src/tint/utils/symbol/generation_id.cc | 48 + .../src/tint/utils/symbol/generation_id.h | 65 + 3rdparty/dawn/src/tint/utils/symbol/symbol.cc | 102 + 3rdparty/dawn/src/tint/utils/symbol/symbol.h | 127 + .../src/tint/utils/symbol/symbol_table.cc | 108 + .../dawn/src/tint/utils/symbol/symbol_table.h | 118 + 3rdparty/dawn/src/tint/utils/system/env.h | 42 + .../src/tint/utils/system/executable_path.h | 43 + .../dawn/src/tint/utils/system/terminal.h | 49 + .../src/tint/utils/templates/enums.tmpl.inc | 236 + .../templates/intrinsic_table_data.tmpl.inc | 513 + 3rdparty/dawn/src/tint/utils/text/base64.cc | 71 + 3rdparty/dawn/src/tint/utils/text/base64.h | 68 + .../dawn/src/tint/utils/text/color_mode.cc | 65 + .../dawn/src/tint/utils/text/color_mode.h | 52 + 3rdparty/dawn/src/tint/utils/text/string.cc | 106 + 3rdparty/dawn/src/tint/utils/text/string.h | 169 + .../dawn/src/tint/utils/text/string_stream.cc | 80 + .../dawn/src/tint/utils/text/string_stream.h | 218 + .../dawn/src/tint/utils/text/styled_text.cc | 100 + .../dawn/src/tint/utils/text/styled_text.h | 154 + .../tint/utils/text/styled_text_printer.cc | 66 + .../src/tint/utils/text/styled_text_printer.h | 83 + .../utils/text/styled_text_printer_ansi.cc | 241 + .../src/tint/utils/text/styled_text_theme.cc | 370 + .../src/tint/utils/text/styled_text_theme.h | 119 + .../dawn/src/tint/utils/text/text_style.h | 219 + 3rdparty/dawn/src/tint/utils/text/unicode.cc | 539 + 3rdparty/dawn/src/tint/utils/text/unicode.h | 131 + .../utils/text_generator/text_generator.cc | 183 + .../utils/text_generator/text_generator.h | 206 + 3rdparty/dawn/src/utils/compiler.h | 127 + 3rdparty/dawn/src/utils/numeric.h | 56 + 3rdparty/dawn/third_party/abseil-cpp/LICENSE | 203 + .../abseil-cpp/absl/algorithm/algorithm.h | 64 + .../abseil-cpp/absl/algorithm/container.h | 1864 ++ .../abseil-cpp/absl/base/attributes.h | 1077 + .../abseil-cpp/absl/base/c_header_test.c | 30 + .../abseil-cpp/absl/base/call_once.h | 227 + .../third_party/abseil-cpp/absl/base/casts.h | 180 + .../third_party/abseil-cpp/absl/base/config.h | 877 + .../abseil-cpp/absl/base/const_init.h | 76 + .../absl/base/dynamic_annotations.h | 477 + .../abseil-cpp/absl/base/fast_type_id.h | 45 + .../absl/base/internal/atomic_hook.h | 200 + .../absl/base/internal/cycleclock.h | 144 + .../absl/base/internal/cycleclock_config.h | 55 + .../absl/base/internal/direct_mmap.h | 170 + .../abseil-cpp/absl/base/internal/endian.h | 279 + .../absl/base/internal/errno_saver.h | 43 + .../abseil-cpp/absl/base/internal/hide_ptr.h | 51 + .../abseil-cpp/absl/base/internal/identity.h | 39 + .../absl/base/internal/iterator_traits.h | 71 + .../absl/base/internal/low_level_alloc.h | 133 + .../absl/base/internal/low_level_scheduling.h | 134 + .../absl/base/internal/per_thread_tls.h | 52 + .../abseil-cpp/absl/base/internal/poison.h | 59 + .../absl/base/internal/pretty_function.h | 33 + .../absl/base/internal/raw_logging.h | 217 + .../absl/base/internal/scheduling_mode.h | 58 + .../absl/base/internal/scoped_set_env.h | 45 + .../abseil-cpp/absl/base/internal/spinlock.h | 305 + .../absl/base/internal/spinlock_akaros.inc | 35 + .../absl/base/internal/spinlock_linux.inc | 71 + .../absl/base/internal/spinlock_posix.inc | 46 + .../absl/base/internal/spinlock_wait.h | 95 + .../absl/base/internal/spinlock_win32.inc | 40 + .../abseil-cpp/absl/base/internal/strerror.h | 39 + .../abseil-cpp/absl/base/internal/sysinfo.h | 74 + .../absl/base/internal/thread_identity.h | 273 + .../absl/base/internal/throw_delegate.h | 75 + .../abseil-cpp/absl/base/internal/tracing.h | 81 + .../absl/base/internal/tsan_mutex_interface.h | 68 + .../absl/base/internal/unaligned_access.h | 89 + .../absl/base/internal/unscaledcycleclock.h | 113 + .../base/internal/unscaledcycleclock_config.h | 62 + .../abseil-cpp/absl/base/log_severity.h | 185 + .../third_party/abseil-cpp/absl/base/macros.h | 220 + .../abseil-cpp/absl/base/no_destructor.h | 191 + .../abseil-cpp/absl/base/nullability.h | 317 + .../abseil-cpp/absl/base/optimization.h | 310 + .../abseil-cpp/absl/base/options.h | 184 + .../abseil-cpp/absl/base/policy_checks.h | 115 + .../third_party/abseil-cpp/absl/base/port.h | 25 + .../abseil-cpp/absl/base/prefetch.h | 209 + .../abseil-cpp/absl/base/thread_annotations.h | 333 + .../abseil-cpp/absl/container/btree_map.h | 891 + .../abseil-cpp/absl/container/btree_set.h | 826 + .../abseil-cpp/absl/container/fixed_array.h | 549 + .../abseil-cpp/absl/container/flat_hash_map.h | 692 + .../abseil-cpp/absl/container/flat_hash_set.h | 580 + .../absl/container/hash_container_defaults.h | 45 + .../absl/container/inlined_vector.h | 1025 + .../absl/container/internal/btree.h | 3149 ++ .../absl/container/internal/btree_container.h | 867 + .../absl/container/internal/common.h | 250 + .../container/internal/common_policy_traits.h | 151 + .../container/internal/compressed_tuple.h | 275 + .../container/internal/container_memory.h | 555 + .../internal/hash_function_defaults.h | 281 + .../container/internal/hash_policy_traits.h | 195 + .../internal/hashtable_control_bytes.h | 516 + .../absl/container/internal/hashtable_debug.h | 102 + .../internal/hashtable_debug_hooks.h | 85 + .../container/internal/hashtablez_sampler.h | 294 + .../absl/container/internal/inlined_vector.h | 1102 + .../absl/container/internal/layout.h | 828 + .../container/internal/node_slot_policy.h | 95 + .../absl/container/internal/raw_hash_map.h | 357 + .../absl/container/internal/raw_hash_set.h | 3703 +++ .../internal/raw_hash_set_resize_impl.h | 79 + .../absl/container/internal/test_allocator.h | 387 + .../internal/test_instance_tracker.h | 274 + .../absl/container/internal/tracked.h | 83 + .../abseil-cpp/absl/container/node_hash_map.h | 687 + .../abseil-cpp/absl/container/node_hash_set.h | 578 + .../third_party/abseil-cpp/absl/crc/crc32c.h | 192 + .../abseil-cpp/absl/crc/internal/cpu_detect.h | 69 + .../abseil-cpp/absl/crc/internal/crc.h | 83 + .../internal/crc32_x86_arm_combined_simd.h | 278 + .../abseil-cpp/absl/crc/internal/crc32c.h | 39 + .../absl/crc/internal/crc32c_inline.h | 72 + .../absl/crc/internal/crc_cord_state.h | 159 + .../absl/crc/internal/crc_internal.h | 177 + .../abseil-cpp/absl/crc/internal/crc_memcpy.h | 122 + .../internal/non_temporal_arm_intrinsics.h | 79 + .../absl/crc/internal/non_temporal_memcpy.h | 195 + .../absl/debugging/failure_signal_handler.h | 121 + .../debugging/internal/address_is_readable.h | 32 + .../absl/debugging/internal/addresses.h | 57 + .../internal/bounded_utf8_length_sequence.h | 126 + .../debugging/internal/decode_rust_punycode.h | 55 + .../absl/debugging/internal/demangle.h | 76 + .../absl/debugging/internal/demangle_rust.h | 42 + .../absl/debugging/internal/elf_mem_image.h | 141 + .../absl/debugging/internal/examine_stack.h | 64 + .../debugging/internal/stack_consumption.h | 50 + .../internal/stacktrace_aarch64-inl.inc | 288 + .../debugging/internal/stacktrace_arm-inl.inc | 148 + .../debugging/internal/stacktrace_config.h | 96 + .../internal/stacktrace_emscripten-inl.inc | 119 + .../internal/stacktrace_generic-inl.inc | 103 + .../internal/stacktrace_powerpc-inl.inc | 269 + .../internal/stacktrace_riscv-inl.inc | 204 + .../internal/stacktrace_unimplemented-inl.inc | 25 + .../internal/stacktrace_win32-inl.inc | 81 + .../debugging/internal/stacktrace_x86-inl.inc | 405 + .../absl/debugging/internal/symbolize.h | 153 + .../debugging/internal/utf8_for_code_point.h | 47 + .../absl/debugging/internal/vdso_support.h | 158 + .../abseil-cpp/absl/debugging/leak_check.h | 150 + .../abseil-cpp/absl/debugging/stacktrace.h | 299 + .../abseil-cpp/absl/debugging/symbolize.h | 99 + .../absl/debugging/symbolize_darwin.inc | 102 + .../absl/debugging/symbolize_elf.inc | 1756 ++ .../absl/debugging/symbolize_emscripten.inc | 76 + .../debugging/symbolize_unimplemented.inc | 40 + .../absl/debugging/symbolize_win32.inc | 101 + .../absl/functional/any_invocable.h | 334 + .../abseil-cpp/absl/functional/bind_front.h | 194 + .../abseil-cpp/absl/functional/function_ref.h | 144 + .../absl/functional/internal/any_invocable.h | 776 + .../absl/functional/internal/front_binder.h | 93 + .../absl/functional/internal/function_ref.h | 113 + .../abseil-cpp/absl/functional/overload.h | 72 + .../third_party/abseil-cpp/absl/hash/hash.h | 466 + .../abseil-cpp/absl/hash/internal/city.h | 78 + .../abseil-cpp/absl/hash/internal/hash.h | 1454 + .../absl/hash/internal/weakly_mixed_integer.h | 38 + .../abseil-cpp/absl/log/absl_check.h | 117 + .../abseil-cpp/absl/log/absl_log.h | 115 + .../abseil-cpp/absl/log/absl_vlog_is_on.h | 95 + .../third_party/abseil-cpp/absl/log/check.h | 210 + .../abseil-cpp/absl/log/check_test_impl.inc | 979 + .../abseil-cpp/absl/log/die_if_null.h | 76 + .../third_party/abseil-cpp/absl/log/flags.h | 43 + .../third_party/abseil-cpp/absl/log/globals.h | 230 + .../abseil-cpp/absl/log/initialize.h | 45 + .../absl/log/internal/append_truncated.h | 75 + .../abseil-cpp/absl/log/internal/check_impl.h | 151 + .../abseil-cpp/absl/log/internal/check_op.h | 529 + .../abseil-cpp/absl/log/internal/conditions.h | 247 + .../abseil-cpp/absl/log/internal/config.h | 45 + .../abseil-cpp/absl/log/internal/flags.h | 59 + .../abseil-cpp/absl/log/internal/fnmatch.h | 35 + .../abseil-cpp/absl/log/internal/globals.h | 101 + .../abseil-cpp/absl/log/internal/log_format.h | 78 + .../abseil-cpp/absl/log/internal/log_impl.h | 282 + .../absl/log/internal/log_message.h | 451 + .../absl/log/internal/log_sink_set.h | 54 + .../abseil-cpp/absl/log/internal/nullguard.h | 88 + .../abseil-cpp/absl/log/internal/nullstream.h | 128 + .../abseil-cpp/absl/log/internal/proto.h | 298 + .../abseil-cpp/absl/log/internal/strip.h | 100 + .../abseil-cpp/absl/log/internal/structured.h | 160 + .../absl/log/internal/structured_proto.h | 107 + .../absl/log/internal/test_actions.h | 90 + .../absl/log/internal/test_helpers.h | 71 + .../absl/log/internal/test_matchers.h | 94 + .../absl/log/internal/vlog_config.h | 165 + .../abseil-cpp/absl/log/internal/voidify.h | 50 + .../third_party/abseil-cpp/absl/log/log.h | 378 + .../absl/log/log_basic_test_impl.inc | 654 + .../abseil-cpp/absl/log/log_entry.h | 223 + .../abseil-cpp/absl/log/log_sink.h | 71 + .../abseil-cpp/absl/log/log_sink_registry.h | 64 + .../abseil-cpp/absl/log/log_streamer.h | 181 + .../abseil-cpp/absl/log/scoped_mock_log.h | 203 + .../abseil-cpp/absl/log/structured.h | 75 + .../abseil-cpp/absl/log/vlog_is_on.h | 74 + .../abseil-cpp/absl/memory/memory.h | 278 + .../abseil-cpp/absl/meta/type_traits.h | 560 + .../abseil-cpp/absl/numeric/bits.h | 262 + .../abseil-cpp/absl/numeric/int128.h | 1220 + .../absl/numeric/int128_have_intrinsic.inc | 311 + .../absl/numeric/int128_no_intrinsic.inc | 349 + .../abseil-cpp/absl/numeric/internal/bits.h | 394 + .../absl/numeric/internal/representation.h | 55 + .../abseil-cpp/absl/profiling/hashtable.h | 40 + .../profiling/internal/exponential_biased.h | 130 + .../profiling/internal/periodic_sampler.h | 211 + .../absl/profiling/internal/profile_builder.h | 138 + .../absl/profiling/internal/sample_recorder.h | 253 + .../abseil-cpp/absl/strings/charconv.h | 123 + .../abseil-cpp/absl/strings/charset.h | 163 + .../abseil-cpp/absl/strings/cord.h | 1763 ++ .../abseil-cpp/absl/strings/cord_analysis.h | 63 + .../abseil-cpp/absl/strings/cord_buffer.h | 572 + .../abseil-cpp/absl/strings/escaping.h | 185 + .../absl/strings/has_absl_stringify.h | 64 + .../absl/strings/has_ostream_operator.h | 42 + .../absl/strings/internal/charconv_bigint.h | 433 + .../absl/strings/internal/charconv_parse.h | 99 + .../absl/strings/internal/cord_data_edge.h | 63 + .../absl/strings/internal/cord_internal.h | 940 + .../absl/strings/internal/cord_rep_btree.h | 944 + .../internal/cord_rep_btree_navigator.h | 267 + .../strings/internal/cord_rep_btree_reader.h | 212 + .../absl/strings/internal/cord_rep_consume.h | 47 + .../absl/strings/internal/cord_rep_crc.h | 103 + .../absl/strings/internal/cord_rep_flat.h | 195 + .../strings/internal/cord_rep_test_util.h | 205 + .../absl/strings/internal/cordz_functions.h | 87 + .../absl/strings/internal/cordz_handle.h | 98 + .../absl/strings/internal/cordz_info.h | 301 + .../strings/internal/cordz_sample_token.h | 97 + .../absl/strings/internal/cordz_statistics.h | 88 + .../strings/internal/cordz_update_scope.h | 71 + .../strings/internal/cordz_update_tracker.h | 123 + .../internal/damerau_levenshtein_distance.h | 34 + .../absl/strings/internal/escaping.h | 57 + .../strings/internal/escaping_test_common.h | 133 + .../absl/strings/internal/memutil.h | 40 + .../strings/internal/numbers_test_common.h | 184 + .../absl/strings/internal/ostringstream.h | 114 + .../absl/strings/internal/pow10_helper.h | 40 + .../strings/internal/resize_uninitialized.h | 119 + .../absl/strings/internal/stl_type_traits.h | 248 + .../absl/strings/internal/str_format/arg.h | 661 + .../absl/strings/internal/str_format/bind.h | 237 + .../strings/internal/str_format/checker.h | 98 + .../internal/str_format/constexpr_parser.h | 357 + .../strings/internal/str_format/extension.h | 456 + .../internal/str_format/float_conversion.h | 37 + .../absl/strings/internal/str_format/output.h | 97 + .../absl/strings/internal/str_format/parser.h | 271 + .../absl/strings/internal/str_join_internal.h | 338 + .../strings/internal/str_split_internal.h | 525 + .../absl/strings/internal/string_constant.h | 67 + .../absl/strings/internal/stringify_sink.h | 57 + .../abseil-cpp/absl/strings/internal/utf8.h | 64 + .../abseil-cpp/absl/strings/match.h | 129 + .../abseil-cpp/absl/strings/numbers.h | 346 + .../abseil-cpp/absl/strings/str_cat.h | 628 + .../abseil-cpp/absl/strings/str_format.h | 887 + .../abseil-cpp/absl/strings/str_join.h | 301 + .../abseil-cpp/absl/strings/str_replace.h | 222 + .../abseil-cpp/absl/strings/str_split.h | 582 + .../abseil-cpp/absl/strings/string_view.h | 782 + .../abseil-cpp/absl/synchronization/barrier.h | 79 + .../absl/synchronization/blocking_counter.h | 107 + .../internal/create_thread_identity.h | 56 + .../absl/synchronization/internal/futex.h | 177 + .../synchronization/internal/futex_waiter.h | 63 + .../synchronization/internal/graphcycles.h | 146 + .../synchronization/internal/kernel_timeout.h | 178 + .../synchronization/internal/per_thread_sem.h | 119 + .../synchronization/internal/pthread_waiter.h | 60 + .../synchronization/internal/sem_waiter.h | 65 + .../synchronization/internal/stdcpp_waiter.h | 56 + .../synchronization/internal/thread_pool.h | 96 + .../absl/synchronization/internal/waiter.h | 69 + .../synchronization/internal/waiter_base.h | 90 + .../synchronization/internal/win32_waiter.h | 72 + .../abseil-cpp/absl/synchronization/mutex.h | 1298 + .../absl/synchronization/notification.h | 133 + .../abseil-cpp/absl/time/civil_time.h | 589 + .../third_party/abseil-cpp/absl/time/clock.h | 78 + .../internal/cctz/include/cctz/civil_time.h | 332 + .../cctz/include/cctz/civil_time_detail.h | 644 + .../internal/cctz/include/cctz/time_zone.h | 460 + .../cctz/include/cctz/zone_info_source.h | 102 + .../internal/cctz/src/test_time_zone_names.h | 33 + .../time/internal/cctz/src/time_zone_fixed.h | 52 + .../time/internal/cctz/src/time_zone_if.h | 80 + .../time/internal/cctz/src/time_zone_impl.h | 97 + .../time/internal/cctz/src/time_zone_info.h | 128 + .../time/internal/cctz/src/time_zone_libc.h | 60 + .../time/internal/cctz/src/time_zone_posix.h | 132 + .../absl/time/internal/cctz/src/tzfile.h | 120 + .../time/internal/get_current_time_chrono.inc | 31 + .../time/internal/get_current_time_posix.inc | 24 + .../abseil-cpp/absl/time/internal/test_util.h | 33 + .../third_party/abseil-cpp/absl/time/time.h | 1926 ++ .../abseil-cpp/absl/types/compare.h | 505 + .../abseil-cpp/absl/types/internal/span.h | 140 + .../abseil-cpp/absl/types/optional.h | 41 + .../third_party/abseil-cpp/absl/types/span.h | 823 + .../abseil-cpp/absl/types/variant.h | 82 + .../abseil-cpp/absl/utility/utility.h | 55 + 3rdparty/dawn/third_party/protobuf/LICENSE | 32 + .../protobuf/src/google/protobuf/any.h | 146 + .../protobuf/src/google/protobuf/arena.h | 689 + .../src/google/protobuf/arena_align.h | 199 + .../google/protobuf/arena_allocation_policy.h | 102 + .../src/google/protobuf/arena_cleanup.h | 108 + .../src/google/protobuf/arenastring.h | 540 + .../src/google/protobuf/arenaz_sampler.h | 238 + .../protobuf/src/google/protobuf/descriptor.h | 3273 +++ .../src/google/protobuf/descriptor_lite.h | 98 + .../protobuf/src/google/protobuf/endian.h | 177 + .../google/protobuf/explicitly_constructed.h | 67 + .../src/google/protobuf/extension_set.h | 1811 ++ .../protobuf/generated_enum_reflection.h | 77 + .../src/google/protobuf/generated_enum_util.h | 114 + .../google/protobuf/generated_message_bases.h | 68 + .../protobuf/generated_message_reflection.h | 387 + .../protobuf/generated_message_tctable_decl.h | 613 + .../protobuf/generated_message_tctable_impl.h | 1181 + .../google/protobuf/generated_message_util.h | 401 + .../protobuf/src/google/protobuf/has_bits.h | 131 + .../google/protobuf/implicit_weak_message.h | 231 + .../google/protobuf/inlined_string_field.h | 545 + .../src/google/protobuf/internal_visibility.h | 44 + .../src/google/protobuf/io/coded_stream.h | 1853 ++ .../src/google/protobuf/io/zero_copy_stream.h | 260 + .../protobuf/io/zero_copy_stream_impl_lite.h | 515 + .../protobuf/src/google/protobuf/map.h | 1577 + .../protobuf/src/google/protobuf/message.h | 1827 ++ .../src/google/protobuf/message_lite.h | 1571 + .../src/google/protobuf/metadata_lite.h | 258 + .../src/google/protobuf/micro_string.h | 653 + .../src/google/protobuf/parse_context.h | 1511 + .../protobuf/src/google/protobuf/port.h | 814 + .../protobuf/src/google/protobuf/port_def.inc | 975 + .../src/google/protobuf/port_undef.inc | 181 + .../protobuf/src/google/protobuf/raw_ptr.h | 64 + .../protobuf/src/google/protobuf/reflection.h | 572 + .../src/google/protobuf/reflection_ops.h | 67 + .../src/google/protobuf/repeated_field.h | 1501 + .../src/google/protobuf/repeated_ptr_field.h | 2183 ++ .../src/google/protobuf/runtime_version.h | 27 + .../src/google/protobuf/serial_arena.h | 441 + .../src/google/protobuf/string_block.h | 181 + .../src/google/protobuf/stubs/common.h | 94 + .../google/protobuf/stubs/platform_macros.h | 115 + .../protobuf/src/google/protobuf/stubs/port.h | 251 + .../src/google/protobuf/text_format.h | 850 + .../src/google/protobuf/thread_safe_arena.h | 282 + .../src/google/protobuf/unknown_field_set.h | 456 + .../src/google/protobuf/wire_format.h | 378 + .../src/google/protobuf/wire_format_lite.h | 1690 ++ include/bgfx/embedded_shader.h | 60 +- scripts/shader-embeded.mk | 6 + scripts/shader.mk | 8 + scripts/shaderc.lua | 127 + src/bgfx_shader.sh | 35 +- tools/shaderc/shaderc.cpp | 32 + tools/shaderc/shaderc.h | 8 + tools/shaderc/shaderc_wgsl.cpp | 942 + 1199 files changed, 357030 insertions(+), 36 deletions(-) create mode 100644 3rdparty/dawn/LICENSE create mode 100644 3rdparty/dawn/include/tint/tint.h create mode 100644 3rdparty/dawn/include/webgpu/webgpu.h create mode 100644 3rdparty/dawn/src/tint/api/common/binding_point.h create mode 100644 3rdparty/dawn/src/tint/api/common/bindings.h create mode 100644 3rdparty/dawn/src/tint/api/common/override_id.h create mode 100644 3rdparty/dawn/src/tint/api/common/resource_table_config.h create mode 100644 3rdparty/dawn/src/tint/api/common/resource_type.h create mode 100644 3rdparty/dawn/src/tint/api/common/subgroup_matrix.h create mode 100644 3rdparty/dawn/src/tint/api/common/substitute_overrides_config.h create mode 100644 3rdparty/dawn/src/tint/api/common/vertex_pulling_config.cc create mode 100644 3rdparty/dawn/src/tint/api/common/vertex_pulling_config.h create mode 100644 3rdparty/dawn/src/tint/api/helpers/generate_bindings.cc create mode 100644 3rdparty/dawn/src/tint/api/helpers/generate_bindings.h create mode 100644 3rdparty/dawn/src/tint/api/tint.cc create mode 100644 3rdparty/dawn/src/tint/api/tint.h create mode 100644 3rdparty/dawn/src/tint/lang/core/binary_op.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/binary_op.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/clone_context.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/composite.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/composite.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/eval.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/eval.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/invalid.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/invalid.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/manager.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/manager.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/node.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/node.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/scalar.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/scalar.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/splat.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/splat.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/string.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/string.h create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/value.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/constant/value.h create mode 100644 3rdparty/dawn/src/tint/lang/core/enums.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/enums.h create mode 100644 3rdparty/dawn/src/tint/lang/core/evaluation_stage.h create mode 100644 3rdparty/dawn/src/tint/lang/core/fluent_types.h create mode 100644 3rdparty/dawn/src/tint/lang/core/interpolation.h create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.h create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/data.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/dialect.h create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/table.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/table.h create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/table_data.h create mode 100644 3rdparty/dawn/src/tint/lang/core/intrinsic/type_matchers.h create mode 100644 3rdparty/dawn/src/tint/lang/core/io_attributes.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/access.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/access.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/binary.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/binary.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/binary/decode.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/binary/decode.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/binary/encode.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/binary/encode.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/bitcast.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/bitcast.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/block.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/block.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/block_param.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/block_param.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/break_if.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/break_if.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/builder.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/builder.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/builtin_call.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/builtin_call.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/call.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/call.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/clone_context.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/clone_context.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/constant.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/constant.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/construct.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/construct.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/continue.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/continue.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/control_instruction.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/control_instruction.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/convert.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/convert.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/core_binary.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/core_binary.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/core_unary.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/core_unary.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/disassembler.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/disassembler.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/discard.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/discard.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/evaluator.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/evaluator.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit_if.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit_if.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit_loop.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit_loop.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit_switch.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/exit_switch.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/function.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/function.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/function_param.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/function_param.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/if.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/if.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/instruction.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/instruction.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/instruction_result.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/instruction_result.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/let.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/let.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/load.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/load.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/loop.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/loop.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/module.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/module.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/next_iteration.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/next_iteration.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/override.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/override.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/phony.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/phony.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/referenced_functions.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/referenced_module_decls.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/referenced_module_vars.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/reflection.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/reflection.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/return.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/return.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/store.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/store.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/switch.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/switch.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/swizzle.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/swizzle.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/terminator.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/terminator.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_options.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/std140.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/std140.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/traverse.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/type/array_count.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/type/array_count.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/unary.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/unary.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/unreachable.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/unreachable.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/unused.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/unused.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/user_call.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/user_call.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/validator.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/validator.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/value.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/value.h create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/var.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/ir/var.h create mode 100644 3rdparty/dawn/src/tint/lang/core/number.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/number.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/abstract_float.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/abstract_float.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/abstract_int.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/abstract_int.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/array.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/array.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/array_count.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/array_count.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/atomic.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/atomic.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/binding_array.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/binding_array.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/bool.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/bool.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/buffer.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/buffer.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/builtin_structs.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/builtin_structs.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/clone_context.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/depth_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/depth_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/external_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/external_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/f16.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/f16.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/f32.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/f32.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/function.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/function.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/i32.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/i32.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/i8.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/i8.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/input_attachment.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/input_attachment.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/invalid.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/invalid.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/manager.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/manager.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/matrix.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/matrix.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/memory_view.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/memory_view.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/node.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/node.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/pointer.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/pointer.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/reference.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/reference.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/resource_type.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/resource_type.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/sampled_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/sampled_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/sampler.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/sampler.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/sampler_kind.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/sampler_kind.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/scalar.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/scalar.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/storage_texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/storage_texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/string.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/string.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/struct.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/struct.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/texel_buffer.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/texel_buffer.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/texture.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/texture_dimension.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/texture_dimension.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/type.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/type.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/u32.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/u32.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/u64.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/u64.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/u8.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/u8.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/unique_node.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/unique_node.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/vector.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/vector.h create mode 100644 3rdparty/dawn/src/tint/lang/core/type/void.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/type/void.h create mode 100644 3rdparty/dawn/src/tint/lang/core/unary_op.cc create mode 100644 3rdparty/dawn/src/tint/lang/core/unary_op.h create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/common/options.cc create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/common/options.h create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/common/output.cc create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/common/output.h create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/raise/raise.cc create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/raise/raise.h create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/writer.cc create mode 100644 3rdparty/dawn/src/tint/lang/null/writer/writer.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/builtin_fn.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/builtin_fn.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/intrinsic/data.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/intrinsic/dialect.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/intrinsic/type_matchers.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/binary.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/binary.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/common/common.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/common/options.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/reader.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/reader/reader.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/image.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/image.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/resource_table.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/resource_table.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/validate/validate.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/validate/validate.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/function.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/function.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/module.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/module.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helper.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helpers.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/options.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/output.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/common/output.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/writer.cc create mode 100644 3rdparty/dawn/src/tint/lang/spirv/writer/writer.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/allowed_features.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/alias.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/alias.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/builder.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/builder.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/const.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/const.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/enable.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/enable.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/extension.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/extension.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/function.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/function.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/let.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/let.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/module.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/module.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/node.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/node.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/node_id.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/override.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/override.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/requires.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/requires.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/traverse_expressions.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/type.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/var.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/var.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/variable.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/variable.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/enums.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/enums.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/feature_status.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/feature_status.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding_info.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/intrinsic/data.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/intrinsic/dialect.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/intrinsic/type_matchers.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ir/unary.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/ir/unary.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/program/program.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/program/program.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/options.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/detail.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/reader.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reader/reader.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reserved_words.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/reserved_words.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/array.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/array.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/call.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/call.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/function.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/function.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/info.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/info.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/load.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/load.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/module.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/module.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/node.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/node.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/pipeline_stage_set.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/sampler_texture_pair.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/struct.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/struct.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/type_mappings.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/variable.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/variable.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/common/common.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/common/options.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/output.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/output.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.h create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/writer.cc create mode 100644 3rdparty/dawn/src/tint/lang/wgsl/writer/writer.h create mode 100644 3rdparty/dawn/src/tint/tint.natvis create mode 100644 3rdparty/dawn/src/tint/utils/bytes/buffer_reader.cc create mode 100644 3rdparty/dawn/src/tint/utils/bytes/buffer_reader.h create mode 100644 3rdparty/dawn/src/tint/utils/bytes/decoder.h create mode 100644 3rdparty/dawn/src/tint/utils/bytes/endianness.h create mode 100644 3rdparty/dawn/src/tint/utils/bytes/reader.cc create mode 100644 3rdparty/dawn/src/tint/utils/bytes/reader.h create mode 100644 3rdparty/dawn/src/tint/utils/bytes/swap.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/bitset.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/containers.cc create mode 100644 3rdparty/dawn/src/tint/utils/containers/enum_set.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/filtered_iterator.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/hashmap.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/hashmap_base.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/hashset.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/map.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/predicates.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/reverse.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/scope_stack.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/slice.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/transform.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/unique_allocator.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/unique_vector.h create mode 100644 3rdparty/dawn/src/tint/utils/containers/vector.h create mode 100644 3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.cc create mode 100644 3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.h create mode 100644 3rdparty/dawn/src/tint/utils/diagnostic/formatter.cc create mode 100644 3rdparty/dawn/src/tint/utils/diagnostic/formatter.h create mode 100644 3rdparty/dawn/src/tint/utils/diagnostic/source.cc create mode 100644 3rdparty/dawn/src/tint/utils/diagnostic/source.h create mode 100644 3rdparty/dawn/src/tint/utils/ice/debugger.cc create mode 100644 3rdparty/dawn/src/tint/utils/ice/debugger.h create mode 100644 3rdparty/dawn/src/tint/utils/ice/ice.cc create mode 100644 3rdparty/dawn/src/tint/utils/ice/ice.h create mode 100644 3rdparty/dawn/src/tint/utils/internal_limits.h create mode 100644 3rdparty/dawn/src/tint/utils/macros/compiler.h create mode 100644 3rdparty/dawn/src/tint/utils/macros/concat.h create mode 100644 3rdparty/dawn/src/tint/utils/macros/defer.h create mode 100644 3rdparty/dawn/src/tint/utils/macros/foreach.h create mode 100644 3rdparty/dawn/src/tint/utils/macros/macros.cc create mode 100644 3rdparty/dawn/src/tint/utils/macros/scoped_assignment.h create mode 100644 3rdparty/dawn/src/tint/utils/macros/static_init.h create mode 100644 3rdparty/dawn/src/tint/utils/math/crc32.h create mode 100644 3rdparty/dawn/src/tint/utils/math/hash.h create mode 100644 3rdparty/dawn/src/tint/utils/math/math.cc create mode 100644 3rdparty/dawn/src/tint/utils/math/math.h create mode 100644 3rdparty/dawn/src/tint/utils/memory/aligned_storage.h create mode 100644 3rdparty/dawn/src/tint/utils/memory/bitcast.h create mode 100644 3rdparty/dawn/src/tint/utils/memory/block_allocator.h create mode 100644 3rdparty/dawn/src/tint/utils/memory/bump_allocator.h create mode 100644 3rdparty/dawn/src/tint/utils/memory/memory.cc create mode 100644 3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.cc create mode 100644 3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.h create mode 100644 3rdparty/dawn/src/tint/utils/reflection.cc create mode 100644 3rdparty/dawn/src/tint/utils/reflection.h create mode 100644 3rdparty/dawn/src/tint/utils/result.cc create mode 100644 3rdparty/dawn/src/tint/utils/result.h create mode 100644 3rdparty/dawn/src/tint/utils/rtti/castable.cc create mode 100644 3rdparty/dawn/src/tint/utils/rtti/castable.h create mode 100644 3rdparty/dawn/src/tint/utils/rtti/ignore.h create mode 100644 3rdparty/dawn/src/tint/utils/rtti/switch.cc create mode 100644 3rdparty/dawn/src/tint/utils/rtti/switch.h create mode 100644 3rdparty/dawn/src/tint/utils/rtti/traits.h create mode 100644 3rdparty/dawn/src/tint/utils/strconv/float_to_string.cc create mode 100644 3rdparty/dawn/src/tint/utils/strconv/float_to_string.h create mode 100644 3rdparty/dawn/src/tint/utils/strconv/parse_num.cc create mode 100644 3rdparty/dawn/src/tint/utils/strconv/parse_num.h create mode 100644 3rdparty/dawn/src/tint/utils/symbol/generation_id.cc create mode 100644 3rdparty/dawn/src/tint/utils/symbol/generation_id.h create mode 100644 3rdparty/dawn/src/tint/utils/symbol/symbol.cc create mode 100644 3rdparty/dawn/src/tint/utils/symbol/symbol.h create mode 100644 3rdparty/dawn/src/tint/utils/symbol/symbol_table.cc create mode 100644 3rdparty/dawn/src/tint/utils/symbol/symbol_table.h create mode 100644 3rdparty/dawn/src/tint/utils/system/env.h create mode 100644 3rdparty/dawn/src/tint/utils/system/executable_path.h create mode 100644 3rdparty/dawn/src/tint/utils/system/terminal.h create mode 100644 3rdparty/dawn/src/tint/utils/templates/enums.tmpl.inc create mode 100644 3rdparty/dawn/src/tint/utils/templates/intrinsic_table_data.tmpl.inc create mode 100644 3rdparty/dawn/src/tint/utils/text/base64.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/base64.h create mode 100644 3rdparty/dawn/src/tint/utils/text/color_mode.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/color_mode.h create mode 100644 3rdparty/dawn/src/tint/utils/text/string.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/string.h create mode 100644 3rdparty/dawn/src/tint/utils/text/string_stream.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/string_stream.h create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text.h create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text_printer.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text_printer.h create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text_printer_ansi.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text_theme.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/styled_text_theme.h create mode 100644 3rdparty/dawn/src/tint/utils/text/text_style.h create mode 100644 3rdparty/dawn/src/tint/utils/text/unicode.cc create mode 100644 3rdparty/dawn/src/tint/utils/text/unicode.h create mode 100644 3rdparty/dawn/src/tint/utils/text_generator/text_generator.cc create mode 100644 3rdparty/dawn/src/tint/utils/text_generator/text_generator.h create mode 100644 3rdparty/dawn/src/utils/compiler.h create mode 100644 3rdparty/dawn/src/utils/numeric.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/LICENSE create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/algorithm.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/container.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/attributes.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/c_header_test.c create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/call_once.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/casts.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/config.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/const_init.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/dynamic_annotations.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/fast_type_id.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/atomic_hook.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/cycleclock.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/cycleclock_config.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/direct_mmap.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/endian.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/errno_saver.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/hide_ptr.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/identity.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/iterator_traits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/low_level_alloc.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/per_thread_tls.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/poison.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/pretty_function.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/raw_logging.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/scheduling_mode.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/scoped_set_env.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/spinlock.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/strerror.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/sysinfo.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/thread_identity.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/throw_delegate.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/tracing.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/unaligned_access.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/log_severity.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/macros.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/no_destructor.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/nullability.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/optimization.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/options.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/policy_checks.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/port.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/prefetch.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/base/thread_annotations.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/btree_map.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/btree_set.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/fixed_array.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/flat_hash_map.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/flat_hash_set.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/hash_container_defaults.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/inlined_vector.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/btree.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/btree_container.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/common.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/common_policy_traits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/container_memory.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/hashtable_control_bytes.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/hashtable_debug.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/inlined_vector.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/layout.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/node_slot_policy.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/raw_hash_map.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/test_allocator.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/test_instance_tracker.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/internal/tracked.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/node_hash_map.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/container/node_hash_set.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/crc32c.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/cpu_detect.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc32c.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc32c_inline.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc_cord_state.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc_internal.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/crc_memcpy.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/non_temporal_arm_intrinsics.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/failure_signal_handler.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/addresses.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/bounded_utf8_length_sequence.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/demangle.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/examine_stack.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/symbolize.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/internal/vdso_support.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/leak_check.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/stacktrace.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/symbolize.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/symbolize_darwin.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/symbolize_emscripten.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/debugging/symbolize_win32.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/any_invocable.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/bind_front.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/function_ref.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/internal/any_invocable.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/internal/front_binder.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/internal/function_ref.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/functional/overload.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/hash/hash.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/hash/internal/city.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/hash/internal/hash.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/hash/internal/weakly_mixed_integer.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/absl_check.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/absl_log.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/absl_vlog_is_on.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/check.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/check_test_impl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/die_if_null.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/flags.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/globals.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/initialize.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/append_truncated.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/check_impl.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/check_op.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/conditions.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/config.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/flags.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/fnmatch.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/globals.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/log_format.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/log_impl.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/log_message.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/log_sink_set.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/nullguard.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/nullstream.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/proto.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/strip.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/structured.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/structured_proto.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/test_actions.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/test_helpers.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/test_matchers.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/vlog_config.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/internal/voidify.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/log.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/log_basic_test_impl.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/log_entry.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/log_sink.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/log_sink_registry.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/log_streamer.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/scoped_mock_log.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/structured.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/log/vlog_is_on.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/memory/memory.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/meta/type_traits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/numeric/bits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/numeric/int128.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/numeric/internal/bits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/numeric/internal/representation.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/profiling/hashtable.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/profiling/internal/exponential_biased.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/profiling/internal/profile_builder.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/charconv.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/charset.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/cord.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/cord_analysis.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/cord_buffer.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/escaping.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/has_absl_stringify.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/has_ostream_operator.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/charconv_parse.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_data_edge.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_internal.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_crc.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cord_rep_test_util.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_functions.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_handle.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_info.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_statistics.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/escaping.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/escaping_test_common.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/memutil.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/numbers_test_common.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/ostringstream.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/pow10_helper.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/stl_type_traits.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/output.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_join_internal.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/string_constant.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/stringify_sink.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/internal/utf8.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/match.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/numbers.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/str_cat.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/str_format.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/str_join.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/str_replace.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/str_split.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/strings/string_view.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/barrier.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/blocking_counter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/futex.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/futex_waiter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/pthread_waiter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/sem_waiter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/stdcpp_waiter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/thread_pool.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/waiter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/waiter_base.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/internal/win32_waiter.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/mutex.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/synchronization/notification.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/civil_time.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/clock.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/test_time_zone_names.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/get_current_time_chrono.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/get_current_time_posix.inc create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/internal/test_util.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/time/time.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/types/compare.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/types/internal/span.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/types/optional.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/types/span.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/types/variant.h create mode 100644 3rdparty/dawn/third_party/abseil-cpp/absl/utility/utility.h create mode 100644 3rdparty/dawn/third_party/protobuf/LICENSE create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/any.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/arena.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/arena_align.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/arena_allocation_policy.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/arena_cleanup.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/arenastring.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/arenaz_sampler.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/descriptor.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/descriptor_lite.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/endian.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/explicitly_constructed.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/extension_set.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_enum_util.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_message_bases.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_message_reflection.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_message_tctable_decl.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_message_tctable_impl.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/generated_message_util.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/has_bits.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/implicit_weak_message.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/inlined_string_field.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/internal_visibility.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/io/coded_stream.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/map.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/message.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/message_lite.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/metadata_lite.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/micro_string.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/parse_context.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/port.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/port_def.inc create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/port_undef.inc create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/raw_ptr.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/reflection.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/reflection_ops.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/repeated_field.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/repeated_ptr_field.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/runtime_version.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/serial_arena.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/string_block.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/stubs/common.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/stubs/platform_macros.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/stubs/port.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/text_format.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/thread_safe_arena.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/unknown_field_set.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/wire_format.h create mode 100644 3rdparty/dawn/third_party/protobuf/src/google/protobuf/wire_format_lite.h create mode 100644 tools/shaderc/shaderc_wgsl.cpp diff --git a/3rdparty/dawn/LICENSE b/3rdparty/dawn/LICENSE new file mode 100644 index 000000000..5b716b6a0 --- /dev/null +++ b/3rdparty/dawn/LICENSE @@ -0,0 +1,26 @@ +// Copyright 2017-2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/3rdparty/dawn/include/tint/tint.h b/3rdparty/dawn/include/tint/tint.h new file mode 100644 index 000000000..61fad6373 --- /dev/null +++ b/3rdparty/dawn/include/tint/tint.h @@ -0,0 +1,85 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef INCLUDE_TINT_TINT_H_ +#define INCLUDE_TINT_TINT_H_ + +// Guard for accidental includes to private headers +#define CURRENTLY_IN_TINT_PUBLIC_HEADER + +// TODO(tint:88): When implementing support for an install target, all of these +// headers will need to be moved to include/tint/. + +#include "src/tint/api/common/subgroup_matrix.h" +#include "src/tint/api/common/substitute_overrides_config.h" +#include "src/tint/api/common/vertex_pulling_config.h" +#include "src/tint/api/tint.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/wgsl/inspector/inspector.h" +#include "src/tint/utils/diagnostic/formatter.h" +#include "src/tint/utils/text/styled_text.h" + +/////////////// +// NOTE if adding a new guard include here, it must also appear in src/tint/api/tint.cc for the +// build to work correctly. +/////////////// + +#if TINT_BUILD_SPV_READER +#include "src/tint/lang/spirv/reader/reader.h" +#endif // TINT_BUILD_SPV_READER + +#if TINT_BUILD_WGSL_READER +#include "src/tint/lang/wgsl/reader/reader.h" +#endif // TINT_BUILD_WGSL_READER + +#if TINT_BUILD_SPV_WRITER +#include "src/tint/lang/spirv/writer/writer.h" +#endif // TINT_BUILD_SPV_WRITER + +#if TINT_BUILD_WGSL_WRITER +#include "src/tint/lang/wgsl/writer/writer.h" +#endif // TINT_BUILD_WGSL_WRITER + +#if TINT_BUILD_MSL_WRITER +#include "src/tint/lang/msl/writer/writer.h" +#endif // TINT_BUILD_MSL_WRITER + +#if TINT_BUILD_HLSL_WRITER +#include "src/tint/lang/hlsl/writer/writer.h" +#endif // TINT_BUILD_HLSL_WRITER + +#if TINT_BUILD_GLSL_WRITER +#include "src/tint/lang/glsl/writer/writer.h" +#endif // TINT_BUILD_GLSL_WRITER + +#if TINT_BUILD_NULL_WRITER +#include "src/tint/lang/null/writer/writer.h" +#endif // TINT_BUILD_NULL_WRITER + +#undef CURRENTLY_IN_TINT_PUBLIC_HEADER + +#endif // INCLUDE_TINT_TINT_H_ diff --git a/3rdparty/dawn/include/webgpu/webgpu.h b/3rdparty/dawn/include/webgpu/webgpu.h new file mode 100644 index 000000000..6c57aafda --- /dev/null +++ b/3rdparty/dawn/include/webgpu/webgpu.h @@ -0,0 +1,4887 @@ +// BSD 3-Clause License +// +// Copyright (c) 2019, "WebGPU native" developers +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifdef __EMSCRIPTEN__ +#error "Do not include this header. Emscripten already provides headers needed for WebGPU." +#endif + +#ifndef WEBGPU_H_ +#define WEBGPU_H_ + +#if defined(WGPU_SHARED_LIBRARY) +# if defined(_WIN32) +# if defined(WGPU_IMPLEMENTATION) +# define WGPU_EXPORT __declspec(dllexport) +# else +# define WGPU_EXPORT __declspec(dllimport) +# endif +# else // defined(_WIN32) +# if defined(WGPU_IMPLEMENTATION) +# define WGPU_EXPORT __attribute__((visibility("default"))) +# else +# define WGPU_EXPORT +# endif +# endif // defined(_WIN32) +#else // defined(WGPU_SHARED_LIBRARY) +# define WGPU_EXPORT +#endif // defined(WGPU_SHARED_LIBRARY) + +#if !defined(WGPU_OBJECT_ATTRIBUTE) +#define WGPU_OBJECT_ATTRIBUTE +#endif +#if !defined(WGPU_ENUM_ATTRIBUTE) +#define WGPU_ENUM_ATTRIBUTE +#endif +#if !defined(WGPU_STRUCTURE_ATTRIBUTE) +#define WGPU_STRUCTURE_ATTRIBUTE +#endif +#if !defined(WGPU_FUNCTION_ATTRIBUTE) +#define WGPU_FUNCTION_ATTRIBUTE +#endif +#if !defined(WGPU_NULLABLE) +#define WGPU_NULLABLE +#endif + +#include +#include +#include + +#define _wgpu_COMMA , +#if defined(__cplusplus) +# define _wgpu_ENUM_ZERO_INIT(type) type(0) +# define _wgpu_STRUCT_ZERO_INIT {} +# if __cplusplus >= 201103L +# define _wgpu_MAKE_INIT_STRUCT(type, value) (type value) +# else +# define _wgpu_MAKE_INIT_STRUCT(type, value) value +# endif +#else +# define _wgpu_ENUM_ZERO_INIT(type) (type)0 +# define _wgpu_STRUCT_ZERO_INIT {0} +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define _wgpu_MAKE_INIT_STRUCT(type, value) ((type) value) +# else +# define _wgpu_MAKE_INIT_STRUCT(type, value) value +# endif +#endif + +#define WGPU_TRUE (UINT32_C(1)) +#define WGPU_FALSE (UINT32_C(0)) +#define WGPU_ARRAY_LAYER_COUNT_UNDEFINED (UINT32_MAX) +#define WGPU_COPY_STRIDE_UNDEFINED (UINT32_MAX) +#define WGPU_DEPTH_CLEAR_VALUE_UNDEFINED (NAN) +#define WGPU_DEPTH_SLICE_UNDEFINED (UINT32_MAX) +#define WGPU_INVALID_BINDING (UINT32_MAX) +#define WGPU_LIMIT_U32_UNDEFINED (UINT32_MAX) +#define WGPU_LIMIT_U64_UNDEFINED (UINT64_MAX) +#define WGPU_MIP_LEVEL_COUNT_UNDEFINED (UINT32_MAX) +#define WGPU_QUERY_SET_INDEX_UNDEFINED (UINT32_MAX) +#define WGPU_STRLEN (SIZE_MAX) +#define WGPU_WHOLE_MAP_SIZE (SIZE_MAX) +#define WGPU_WHOLE_SIZE (UINT64_MAX) + +typedef struct WGPUStringView { + WGPU_NULLABLE char const * data; + size_t length; +} WGPUStringView WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_STRING_VIEW_INIT _wgpu_MAKE_INIT_STRUCT(WGPUStringView, { \ + /*.data=*/NULL _wgpu_COMMA \ + /*.length=*/WGPU_STRLEN _wgpu_COMMA \ +}) + +typedef uint64_t WGPUFlags; +typedef uint32_t WGPUBool; + +typedef struct WGPUAdapterImpl* WGPUAdapter WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUBindGroupImpl* WGPUBindGroup WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUBindGroupLayoutImpl* WGPUBindGroupLayout WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUBufferImpl* WGPUBuffer WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUCommandBufferImpl* WGPUCommandBuffer WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUComputePipelineImpl* WGPUComputePipeline WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUDeviceImpl* WGPUDevice WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUExternalTextureImpl* WGPUExternalTexture WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUInstanceImpl* WGPUInstance WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUPipelineLayoutImpl* WGPUPipelineLayout WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUQuerySetImpl* WGPUQuerySet WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUQueueImpl* WGPUQueue WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPURenderBundleImpl* WGPURenderBundle WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPURenderPipelineImpl* WGPURenderPipeline WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUResourceTableImpl* WGPUResourceTable WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUSamplerImpl* WGPUSampler WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUShaderModuleImpl* WGPUShaderModule WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUSharedBufferMemoryImpl* WGPUSharedBufferMemory WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUSharedFenceImpl* WGPUSharedFence WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUSharedTextureMemoryImpl* WGPUSharedTextureMemory WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUSurfaceImpl* WGPUSurface WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUTexelBufferViewImpl* WGPUTexelBufferView WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUTextureImpl* WGPUTexture WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUTextureViewImpl* WGPUTextureView WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUCommandEncoderImpl* WGPUCommandEncoder WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPUComputePassEncoderImpl* WGPUComputePassEncoder WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPURenderBundleEncoderImpl* WGPURenderBundleEncoder WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPURenderPassEncoderImpl* WGPURenderPassEncoder WGPU_OBJECT_ATTRIBUTE; + +// Structure forward declarations +struct WGPUAdapterPropertiesD3D; +struct WGPUAdapterPropertiesVk; +struct WGPUAdapterPropertiesWGPU; +struct WGPUBindingResource; +struct WGPUBlendComponent; +struct WGPUBufferBindingLayout; +struct WGPUBufferHostMappedPointer; +struct WGPUColor; +struct WGPUColorTargetStateExpandResolveTextureDawn; +struct WGPUCommandBufferDescriptor; +struct WGPUCompatibilityModeLimits; +struct WGPUConstantEntry; +struct WGPUCopyTextureForBrowserOptions; +struct WGPUDawnAdapterPropertiesPowerPreference; +struct WGPUDawnBufferDescriptorErrorInfoFromWireClient; +struct WGPUDawnCacheDeviceDescriptor; +struct WGPUDawnCompilationMessageUtf16; +struct WGPUDawnConsumeAdapterDescriptor; +struct WGPUDawnDeviceAllocatorControl; +struct WGPUDawnDrmFormatProperties; +struct WGPUDawnEncoderInternalUsageDescriptor; +struct WGPUDawnFakeBufferOOMForTesting; +struct WGPUDawnFakeDeviceInitializeErrorForTesting; +struct WGPUDawnHostMappedPointerLimits; +struct WGPUDawnInjectedInvalidSType; +struct WGPUDawnRenderPassColorAttachmentRenderToSingleSampled; +struct WGPUDawnShaderModuleSPIRVOptionsDescriptor; +struct WGPUDawnTexelCopyBufferRowAlignmentLimits; +struct WGPUDawnTextureInternalUsageDescriptor; +struct WGPUDawnTogglesDescriptor; +struct WGPUDawnWGSLBlocklist; +struct WGPUDawnWireWGSLControl; +struct WGPUEmscriptenSurfaceSourceCanvasHTMLSelector; +struct WGPUExtent2D; +struct WGPUExtent3D; +struct WGPUExternalTextureBindingEntry; +struct WGPUExternalTextureBindingLayout; +struct WGPUFuture; +struct WGPUInstanceLimits; +struct WGPUINTERNAL_HAVE_EMDAWNWEBGPU_HEADER; +struct WGPUMemoryHeapInfo; +struct WGPUMultisampleState; +struct WGPUOrigin2D; +struct WGPUOrigin3D; +struct WGPUPassTimestampWrites; +struct WGPUPipelineLayoutResourceTable; +struct WGPUPipelineLayoutStorageAttachment; +struct WGPUPrimitiveState; +struct WGPUQuerySetDescriptor; +struct WGPUQueueDescriptor; +struct WGPURenderBundleDescriptor; +struct WGPURenderBundleEncoderDescriptor; +struct WGPURenderPassDepthStencilAttachment; +struct WGPURenderPassDescriptorExpandResolveRect; +struct WGPURenderPassDescriptorResolveRect; +struct WGPURenderPassMaxDrawCount; +struct WGPURequestAdapterWebGPUBackendOptions; +struct WGPURequestAdapterWebXROptions; +struct WGPUResourceTableDescriptor; +struct WGPUResourceTableLimits; +struct WGPUSamplerBindingLayout; +struct WGPUShaderModuleCompilationOptions; +struct WGPUShaderSourceSPIRV; +struct WGPUShaderSourceWGSL; +struct WGPUSharedBufferMemoryBeginAccessDescriptor; +struct WGPUSharedBufferMemoryDescriptor; +struct WGPUSharedBufferMemoryEndAccessState; +struct WGPUSharedBufferMemoryProperties; +struct WGPUSharedFenceDXGISharedHandleDescriptor; +struct WGPUSharedFenceDXGISharedHandleExportInfo; +struct WGPUSharedFenceEGLSyncDescriptor; +struct WGPUSharedFenceEGLSyncExportInfo; +struct WGPUSharedFenceMTLSharedEventDescriptor; +struct WGPUSharedFenceMTLSharedEventExportInfo; +struct WGPUSharedFenceSyncFDDescriptor; +struct WGPUSharedFenceSyncFDExportInfo; +struct WGPUSharedFenceVkSemaphoreOpaqueFDDescriptor; +struct WGPUSharedFenceVkSemaphoreOpaqueFDExportInfo; +struct WGPUSharedFenceVkSemaphoreZirconHandleDescriptor; +struct WGPUSharedFenceVkSemaphoreZirconHandleExportInfo; +struct WGPUSharedTextureMemoryAHardwareBufferDescriptor; +struct WGPUSharedTextureMemoryD3D11BeginState; +struct WGPUSharedTextureMemoryD3DSwapchainBeginState; +struct WGPUSharedTextureMemoryDmaBufPlane; +struct WGPUSharedTextureMemoryDXGISharedHandleDescriptor; +struct WGPUSharedTextureMemoryEGLImageDescriptor; +struct WGPUSharedTextureMemoryIOSurfaceDescriptor; +struct WGPUSharedTextureMemoryOpaqueFDDescriptor; +struct WGPUSharedTextureMemoryVkDedicatedAllocationDescriptor; +struct WGPUSharedTextureMemoryVkImageLayoutBeginState; +struct WGPUSharedTextureMemoryVkImageLayoutEndState; +struct WGPUSharedTextureMemoryZirconHandleDescriptor; +struct WGPUStaticSamplerBindingLayout; +struct WGPUStencilFaceState; +struct WGPUStorageTextureBindingLayout; +struct WGPUSubgroupMatrixConfig; +struct WGPUSupportedFeatures; +struct WGPUSupportedInstanceFeatures; +struct WGPUSupportedWGSLLanguageFeatures; +struct WGPUSurfaceCapabilities; +struct WGPUSurfaceColorManagement; +struct WGPUSurfaceConfiguration; +struct WGPUSurfaceDescriptorFromWindowsCoreWindow; +struct WGPUSurfaceDescriptorFromWindowsUWPSwapChainPanel; +struct WGPUSurfaceDescriptorFromWindowsWinUISwapChainPanel; +struct WGPUSurfaceSourceAndroidNativeWindow; +struct WGPUSurfaceSourceMetalLayer; +struct WGPUSurfaceSourceWaylandSurface; +struct WGPUSurfaceSourceWindowsHWND; +struct WGPUSurfaceSourceXCBWindow; +struct WGPUSurfaceSourceXlibWindow; +struct WGPUSurfaceTexture; +struct WGPUTexelBufferBindingEntry; +struct WGPUTexelBufferBindingLayout; +struct WGPUTexelBufferViewDescriptor; +struct WGPUTexelCopyBufferLayout; +struct WGPUTextureBindingLayout; +struct WGPUTextureBindingViewDimensionDescriptor; +struct WGPUTextureComponentSwizzle; +struct WGPUVertexAttribute; +struct WGPUYCbCrVkDescriptor; +struct WGPUAdapterPropertiesMemoryHeaps; +struct WGPUAdapterPropertiesSubgroupMatrixConfigs; +struct WGPUAHardwareBufferProperties; +struct WGPUBindGroupEntry; +struct WGPUBindGroupLayoutEntry; +struct WGPUBlendState; +struct WGPUBufferDescriptor; +struct WGPUCommandEncoderDescriptor; +struct WGPUCompilationMessage; +struct WGPUComputePassDescriptor; +struct WGPUComputeState; +struct WGPUDawnDrmFormatCapabilities; +struct WGPUDepthStencilState; +struct WGPUExternalTextureDescriptor; +struct WGPUFutureWaitInfo; +struct WGPUImageCopyExternalTexture; +struct WGPUInstanceDescriptor; +struct WGPULimits; +struct WGPUPipelineLayoutPixelLocalStorage; +struct WGPURenderPassColorAttachment; +struct WGPURenderPassStorageAttachment; +struct WGPURequestAdapterOptions; +struct WGPUSamplerDescriptor; +struct WGPUShaderModuleDescriptor; +struct WGPUSharedFenceDescriptor; +struct WGPUSharedFenceExportInfo; +struct WGPUSharedTextureMemoryAHardwareBufferProperties; +struct WGPUSharedTextureMemoryBeginAccessDescriptor; +struct WGPUSharedTextureMemoryDmaBufDescriptor; +struct WGPUSharedTextureMemoryMetalEndAccessState; +struct WGPUSurfaceDescriptor; +struct WGPUTexelCopyBufferInfo; +struct WGPUTexelCopyTextureInfo; +struct WGPUTextureComponentSwizzleDescriptor; +struct WGPUTextureDescriptor; +struct WGPUVertexBufferLayout; +struct WGPUAdapterInfo; +struct WGPUBindGroupDescriptor; +struct WGPUBindGroupLayoutDescriptor; +struct WGPUColorTargetState; +struct WGPUCompilationInfo; +struct WGPUComputePipelineDescriptor; +struct WGPUDawnFormatCapabilities; +struct WGPUDeviceDescriptor; +struct WGPUPipelineLayoutDescriptor; +struct WGPURenderPassPixelLocalStorage; +struct WGPUSharedTextureMemoryDescriptor; +struct WGPUSharedTextureMemoryEndAccessState; +struct WGPUSharedTextureMemoryProperties; +struct WGPUTextureViewDescriptor; +struct WGPUVertexState; +struct WGPUFragmentState; +struct WGPURenderPassDescriptor; +struct WGPURenderPipelineDescriptor; + +// Callback info structure forward declarations. +struct WGPUBufferMapCallbackInfo; +struct WGPUCompilationInfoCallbackInfo; +struct WGPUCreateComputePipelineAsyncCallbackInfo; +struct WGPUCreateRenderPipelineAsyncCallbackInfo; +struct WGPUDeviceLostCallbackInfo; +struct WGPULoggingCallbackInfo; +struct WGPUPopErrorScopeCallbackInfo; +struct WGPUQueueWorkDoneCallbackInfo; +struct WGPURequestAdapterCallbackInfo; +struct WGPURequestDeviceCallbackInfo; +struct WGPUUncapturedErrorCallbackInfo; + +typedef enum WGPUAdapterType { + WGPUAdapterType_DiscreteGPU = 0x00000001, + WGPUAdapterType_IntegratedGPU = 0x00000002, + WGPUAdapterType_CPU = 0x00000003, + WGPUAdapterType_Unknown = 0x00000004, + WGPUAdapterType_Force32 = 0x7FFFFFFF +} WGPUAdapterType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUAddressMode { + WGPUAddressMode_Undefined = 0x00000000, + WGPUAddressMode_ClampToEdge = 0x00000001, + WGPUAddressMode_Repeat = 0x00000002, + WGPUAddressMode_MirrorRepeat = 0x00000003, + WGPUAddressMode_Force32 = 0x7FFFFFFF +} WGPUAddressMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUAlphaMode { + WGPUAlphaMode_Opaque = 0x00000001, + WGPUAlphaMode_Premultiplied = 0x00000002, + WGPUAlphaMode_Unpremultiplied = 0x00000003, + WGPUAlphaMode_Force32 = 0x7FFFFFFF +} WGPUAlphaMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUBackendType { + WGPUBackendType_Undefined = 0x00000000, + WGPUBackendType_Null = 0x00000001, + WGPUBackendType_WebGPU = 0x00000002, + WGPUBackendType_D3D11 = 0x00000003, + WGPUBackendType_D3D12 = 0x00000004, + WGPUBackendType_Metal = 0x00000005, + WGPUBackendType_Vulkan = 0x00000006, + WGPUBackendType_OpenGL = 0x00000007, + WGPUBackendType_OpenGLES = 0x00000008, + WGPUBackendType_Force32 = 0x7FFFFFFF +} WGPUBackendType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUBlendFactor { + WGPUBlendFactor_Undefined = 0x00000000, + WGPUBlendFactor_Zero = 0x00000001, + WGPUBlendFactor_One = 0x00000002, + WGPUBlendFactor_Src = 0x00000003, + WGPUBlendFactor_OneMinusSrc = 0x00000004, + WGPUBlendFactor_SrcAlpha = 0x00000005, + WGPUBlendFactor_OneMinusSrcAlpha = 0x00000006, + WGPUBlendFactor_Dst = 0x00000007, + WGPUBlendFactor_OneMinusDst = 0x00000008, + WGPUBlendFactor_DstAlpha = 0x00000009, + WGPUBlendFactor_OneMinusDstAlpha = 0x0000000A, + WGPUBlendFactor_SrcAlphaSaturated = 0x0000000B, + WGPUBlendFactor_Constant = 0x0000000C, + WGPUBlendFactor_OneMinusConstant = 0x0000000D, + WGPUBlendFactor_Src1 = 0x0000000E, + WGPUBlendFactor_OneMinusSrc1 = 0x0000000F, + WGPUBlendFactor_Src1Alpha = 0x00000010, + WGPUBlendFactor_OneMinusSrc1Alpha = 0x00000011, + WGPUBlendFactor_Force32 = 0x7FFFFFFF +} WGPUBlendFactor WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUBlendOperation { + WGPUBlendOperation_Undefined = 0x00000000, + WGPUBlendOperation_Add = 0x00000001, + WGPUBlendOperation_Subtract = 0x00000002, + WGPUBlendOperation_ReverseSubtract = 0x00000003, + WGPUBlendOperation_Min = 0x00000004, + WGPUBlendOperation_Max = 0x00000005, + WGPUBlendOperation_Force32 = 0x7FFFFFFF +} WGPUBlendOperation WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUBufferBindingType { + WGPUBufferBindingType_BindingNotUsed = 0x00000000, + WGPUBufferBindingType_Undefined = 0x00000001, + WGPUBufferBindingType_Uniform = 0x00000002, + WGPUBufferBindingType_Storage = 0x00000003, + WGPUBufferBindingType_ReadOnlyStorage = 0x00000004, + WGPUBufferBindingType_Force32 = 0x7FFFFFFF +} WGPUBufferBindingType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUBufferMapState { + WGPUBufferMapState_Unmapped = 0x00000001, + WGPUBufferMapState_Pending = 0x00000002, + WGPUBufferMapState_Mapped = 0x00000003, + WGPUBufferMapState_Force32 = 0x7FFFFFFF +} WGPUBufferMapState WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCallbackMode { + WGPUCallbackMode_WaitAnyOnly = 0x00000001, + WGPUCallbackMode_AllowProcessEvents = 0x00000002, + WGPUCallbackMode_AllowSpontaneous = 0x00000003, + WGPUCallbackMode_Force32 = 0x7FFFFFFF +} WGPUCallbackMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCompareFunction { + WGPUCompareFunction_Undefined = 0x00000000, + WGPUCompareFunction_Never = 0x00000001, + WGPUCompareFunction_Less = 0x00000002, + WGPUCompareFunction_Equal = 0x00000003, + WGPUCompareFunction_LessEqual = 0x00000004, + WGPUCompareFunction_Greater = 0x00000005, + WGPUCompareFunction_NotEqual = 0x00000006, + WGPUCompareFunction_GreaterEqual = 0x00000007, + WGPUCompareFunction_Always = 0x00000008, + WGPUCompareFunction_Force32 = 0x7FFFFFFF +} WGPUCompareFunction WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCompilationInfoRequestStatus { + WGPUCompilationInfoRequestStatus_Success = 0x00000001, + WGPUCompilationInfoRequestStatus_CallbackCancelled = 0x00000002, + WGPUCompilationInfoRequestStatus_Force32 = 0x7FFFFFFF +} WGPUCompilationInfoRequestStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCompilationMessageType { + WGPUCompilationMessageType_Error = 0x00000001, + WGPUCompilationMessageType_Warning = 0x00000002, + WGPUCompilationMessageType_Info = 0x00000003, + WGPUCompilationMessageType_Force32 = 0x7FFFFFFF +} WGPUCompilationMessageType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUComponentSwizzle { + WGPUComponentSwizzle_Undefined = 0x00000000, + WGPUComponentSwizzle_Zero = 0x00000001, + WGPUComponentSwizzle_One = 0x00000002, + WGPUComponentSwizzle_R = 0x00000003, + WGPUComponentSwizzle_G = 0x00000004, + WGPUComponentSwizzle_B = 0x00000005, + WGPUComponentSwizzle_A = 0x00000006, + WGPUComponentSwizzle_Force32 = 0x7FFFFFFF +} WGPUComponentSwizzle WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCompositeAlphaMode { + WGPUCompositeAlphaMode_Auto = 0x00000000, + WGPUCompositeAlphaMode_Opaque = 0x00000001, + WGPUCompositeAlphaMode_Premultiplied = 0x00000002, + WGPUCompositeAlphaMode_Unpremultiplied = 0x00000003, + WGPUCompositeAlphaMode_Inherit = 0x00000004, + WGPUCompositeAlphaMode_Force32 = 0x7FFFFFFF +} WGPUCompositeAlphaMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCreatePipelineAsyncStatus { + WGPUCreatePipelineAsyncStatus_Success = 0x00000001, + WGPUCreatePipelineAsyncStatus_CallbackCancelled = 0x00000002, + WGPUCreatePipelineAsyncStatus_ValidationError = 0x00000003, + WGPUCreatePipelineAsyncStatus_InternalError = 0x00000004, + WGPUCreatePipelineAsyncStatus_Force32 = 0x7FFFFFFF +} WGPUCreatePipelineAsyncStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUCullMode { + WGPUCullMode_Undefined = 0x00000000, + WGPUCullMode_None = 0x00000001, + WGPUCullMode_Front = 0x00000002, + WGPUCullMode_Back = 0x00000003, + WGPUCullMode_Force32 = 0x7FFFFFFF +} WGPUCullMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUDeviceLostReason { + WGPUDeviceLostReason_Unknown = 0x00000001, + WGPUDeviceLostReason_Destroyed = 0x00000002, + WGPUDeviceLostReason_CallbackCancelled = 0x00000003, + WGPUDeviceLostReason_FailedCreation = 0x00000004, + WGPUDeviceLostReason_Force32 = 0x7FFFFFFF +} WGPUDeviceLostReason WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUErrorFilter { + WGPUErrorFilter_Validation = 0x00000001, + WGPUErrorFilter_OutOfMemory = 0x00000002, + WGPUErrorFilter_Internal = 0x00000003, + WGPUErrorFilter_Force32 = 0x7FFFFFFF +} WGPUErrorFilter WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUErrorType { + WGPUErrorType_NoError = 0x00000001, + WGPUErrorType_Validation = 0x00000002, + WGPUErrorType_OutOfMemory = 0x00000003, + WGPUErrorType_Internal = 0x00000004, + WGPUErrorType_Unknown = 0x00000005, + WGPUErrorType_Force32 = 0x7FFFFFFF +} WGPUErrorType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUExternalTextureRotation { + WGPUExternalTextureRotation_Rotate0Degrees = 0x00000001, + WGPUExternalTextureRotation_Rotate90Degrees = 0x00000002, + WGPUExternalTextureRotation_Rotate180Degrees = 0x00000003, + WGPUExternalTextureRotation_Rotate270Degrees = 0x00000004, + WGPUExternalTextureRotation_Force32 = 0x7FFFFFFF +} WGPUExternalTextureRotation WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUFeatureLevel { + WGPUFeatureLevel_Undefined = 0x00000000, + WGPUFeatureLevel_Compatibility = 0x00000001, + WGPUFeatureLevel_Core = 0x00000002, + WGPUFeatureLevel_Force32 = 0x7FFFFFFF +} WGPUFeatureLevel WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUFeatureName { + WGPUFeatureName_CoreFeaturesAndLimits = 0x00000001, + WGPUFeatureName_DepthClipControl = 0x00000002, + WGPUFeatureName_Depth32FloatStencil8 = 0x00000003, + WGPUFeatureName_TextureCompressionBC = 0x00000004, + WGPUFeatureName_TextureCompressionBCSliced3D = 0x00000005, + WGPUFeatureName_TextureCompressionETC2 = 0x00000006, + WGPUFeatureName_TextureCompressionASTC = 0x00000007, + WGPUFeatureName_TextureCompressionASTCSliced3D = 0x00000008, + WGPUFeatureName_TimestampQuery = 0x00000009, + WGPUFeatureName_IndirectFirstInstance = 0x0000000A, + WGPUFeatureName_ShaderF16 = 0x0000000B, + WGPUFeatureName_RG11B10UfloatRenderable = 0x0000000C, + WGPUFeatureName_BGRA8UnormStorage = 0x0000000D, + WGPUFeatureName_Float32Filterable = 0x0000000E, + WGPUFeatureName_Float32Blendable = 0x0000000F, + WGPUFeatureName_ClipDistances = 0x00000010, + WGPUFeatureName_DualSourceBlending = 0x00000011, + WGPUFeatureName_Subgroups = 0x00000012, + WGPUFeatureName_TextureFormatsTier1 = 0x00000013, + WGPUFeatureName_TextureFormatsTier2 = 0x00000014, + WGPUFeatureName_PrimitiveIndex = 0x00000015, + WGPUFeatureName_TextureComponentSwizzle = 0x00000016, + WGPUFeatureName_DawnInternalUsages = 0x00050000, + WGPUFeatureName_DawnMultiPlanarFormats = 0x00050001, + WGPUFeatureName_DawnNative = 0x00050002, + WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses = 0x00050003, + WGPUFeatureName_ImplicitDeviceSynchronization = 0x00050004, + WGPUFeatureName_TransientAttachments = 0x00050006, + WGPUFeatureName_MSAARenderToSingleSampled = 0x00050007, + WGPUFeatureName_D3D11MultithreadProtected = 0x00050008, + WGPUFeatureName_ANGLETextureSharing = 0x00050009, + WGPUFeatureName_PixelLocalStorageCoherent = 0x0005000A, + WGPUFeatureName_PixelLocalStorageNonCoherent = 0x0005000B, + WGPUFeatureName_Unorm16TextureFormats = 0x0005000C, + WGPUFeatureName_MultiPlanarFormatExtendedUsages = 0x0005000D, + WGPUFeatureName_MultiPlanarFormatP010 = 0x0005000E, + WGPUFeatureName_HostMappedPointer = 0x0005000F, + WGPUFeatureName_MultiPlanarRenderTargets = 0x00050010, + WGPUFeatureName_MultiPlanarFormatNv12a = 0x00050011, + WGPUFeatureName_FramebufferFetch = 0x00050012, + WGPUFeatureName_BufferMapExtendedUsages = 0x00050013, + WGPUFeatureName_AdapterPropertiesMemoryHeaps = 0x00050014, + WGPUFeatureName_AdapterPropertiesD3D = 0x00050015, + WGPUFeatureName_AdapterPropertiesVk = 0x00050016, + WGPUFeatureName_DawnFormatCapabilities = 0x00050017, + WGPUFeatureName_DawnDrmFormatCapabilities = 0x00050018, + WGPUFeatureName_MultiPlanarFormatNv16 = 0x00050019, + WGPUFeatureName_MultiPlanarFormatNv24 = 0x0005001A, + WGPUFeatureName_MultiPlanarFormatP210 = 0x0005001B, + WGPUFeatureName_MultiPlanarFormatP410 = 0x0005001C, + WGPUFeatureName_SharedTextureMemoryVkDedicatedAllocation = 0x0005001D, + WGPUFeatureName_SharedTextureMemoryAHardwareBuffer = 0x0005001E, + WGPUFeatureName_SharedTextureMemoryDmaBuf = 0x0005001F, + WGPUFeatureName_SharedTextureMemoryOpaqueFD = 0x00050020, + WGPUFeatureName_SharedTextureMemoryZirconHandle = 0x00050021, + WGPUFeatureName_SharedTextureMemoryDXGISharedHandle = 0x00050022, + WGPUFeatureName_SharedTextureMemoryD3D11Texture2D = 0x00050023, + WGPUFeatureName_SharedTextureMemoryIOSurface = 0x00050024, + WGPUFeatureName_SharedTextureMemoryEGLImage = 0x00050025, + WGPUFeatureName_SharedFenceVkSemaphoreOpaqueFD = 0x00050026, + WGPUFeatureName_SharedFenceSyncFD = 0x00050027, + WGPUFeatureName_SharedFenceVkSemaphoreZirconHandle = 0x00050028, + WGPUFeatureName_SharedFenceDXGISharedHandle = 0x00050029, + WGPUFeatureName_SharedFenceMTLSharedEvent = 0x0005002A, + WGPUFeatureName_SharedBufferMemoryD3D12Resource = 0x0005002B, + WGPUFeatureName_StaticSamplers = 0x0005002C, + WGPUFeatureName_YCbCrVulkanSamplers = 0x0005002D, + WGPUFeatureName_ShaderModuleCompilationOptions = 0x0005002E, + WGPUFeatureName_DawnLoadResolveTexture = 0x0005002F, + WGPUFeatureName_DawnPartialLoadResolveTexture = 0x00050030, + WGPUFeatureName_MultiDrawIndirect = 0x00050031, + WGPUFeatureName_DawnTexelCopyBufferRowAlignment = 0x00050032, + WGPUFeatureName_FlexibleTextureViews = 0x00050033, + WGPUFeatureName_ChromiumExperimentalSubgroupMatrix = 0x00050034, + WGPUFeatureName_SharedFenceEGLSync = 0x00050035, + WGPUFeatureName_DawnDeviceAllocatorControl = 0x00050036, + WGPUFeatureName_AdapterPropertiesWGPU = 0x00050037, + WGPUFeatureName_SharedBufferMemoryD3D12SharedMemoryFileMappingHandle = 0x00050038, + WGPUFeatureName_SharedTextureMemoryD3D12Resource = 0x00050039, + WGPUFeatureName_ChromiumExperimentalSamplingResourceTable = 0x0005003A, + WGPUFeatureName_Force32 = 0x7FFFFFFF +} WGPUFeatureName WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUFilterMode { + WGPUFilterMode_Undefined = 0x00000000, + WGPUFilterMode_Nearest = 0x00000001, + WGPUFilterMode_Linear = 0x00000002, + WGPUFilterMode_Force32 = 0x7FFFFFFF +} WGPUFilterMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUFrontFace { + WGPUFrontFace_Undefined = 0x00000000, + WGPUFrontFace_CCW = 0x00000001, + WGPUFrontFace_CW = 0x00000002, + WGPUFrontFace_Force32 = 0x7FFFFFFF +} WGPUFrontFace WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUIndexFormat { + WGPUIndexFormat_Undefined = 0x00000000, + WGPUIndexFormat_Uint16 = 0x00000001, + WGPUIndexFormat_Uint32 = 0x00000002, + WGPUIndexFormat_Force32 = 0x7FFFFFFF +} WGPUIndexFormat WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUInstanceFeatureName { + WGPUInstanceFeatureName_TimedWaitAny = 0x00000001, + WGPUInstanceFeatureName_ShaderSourceSPIRV = 0x00000002, + WGPUInstanceFeatureName_MultipleDevicesPerAdapter = 0x00000003, + WGPUInstanceFeatureName_Force32 = 0x7FFFFFFF +} WGPUInstanceFeatureName WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPULoadOp { + WGPULoadOp_Undefined = 0x00000000, + WGPULoadOp_Load = 0x00000001, + WGPULoadOp_Clear = 0x00000002, + WGPULoadOp_ExpandResolveTexture = 0x00050003, + WGPULoadOp_Force32 = 0x7FFFFFFF +} WGPULoadOp WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPULoggingType { + WGPULoggingType_Verbose = 0x00000001, + WGPULoggingType_Info = 0x00000002, + WGPULoggingType_Warning = 0x00000003, + WGPULoggingType_Error = 0x00000004, + WGPULoggingType_Force32 = 0x7FFFFFFF +} WGPULoggingType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUMapAsyncStatus { + WGPUMapAsyncStatus_Success = 0x00000001, + WGPUMapAsyncStatus_CallbackCancelled = 0x00000002, + WGPUMapAsyncStatus_Error = 0x00000003, + WGPUMapAsyncStatus_Aborted = 0x00000004, + WGPUMapAsyncStatus_Force32 = 0x7FFFFFFF +} WGPUMapAsyncStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUMipmapFilterMode { + WGPUMipmapFilterMode_Undefined = 0x00000000, + WGPUMipmapFilterMode_Nearest = 0x00000001, + WGPUMipmapFilterMode_Linear = 0x00000002, + WGPUMipmapFilterMode_Force32 = 0x7FFFFFFF +} WGPUMipmapFilterMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUOptionalBool { + WGPUOptionalBool_False = 0x00000000, + WGPUOptionalBool_True = 0x00000001, + WGPUOptionalBool_Undefined = 0x00000002, + WGPUOptionalBool_Force32 = 0x7FFFFFFF +} WGPUOptionalBool WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUPopErrorScopeStatus { + WGPUPopErrorScopeStatus_Success = 0x00000001, + WGPUPopErrorScopeStatus_CallbackCancelled = 0x00000002, + WGPUPopErrorScopeStatus_Error = 0x00000003, + WGPUPopErrorScopeStatus_Force32 = 0x7FFFFFFF +} WGPUPopErrorScopeStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUPowerPreference { + WGPUPowerPreference_Undefined = 0x00000000, + WGPUPowerPreference_LowPower = 0x00000001, + WGPUPowerPreference_HighPerformance = 0x00000002, + WGPUPowerPreference_Force32 = 0x7FFFFFFF +} WGPUPowerPreference WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUPredefinedColorSpace { + WGPUPredefinedColorSpace_SRGB = 0x00000001, + WGPUPredefinedColorSpace_DisplayP3 = 0x00000002, + WGPUPredefinedColorSpace_Force32 = 0x7FFFFFFF +} WGPUPredefinedColorSpace WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUPresentMode { + WGPUPresentMode_Undefined = 0x00000000, + WGPUPresentMode_Fifo = 0x00000001, + WGPUPresentMode_FifoRelaxed = 0x00000002, + WGPUPresentMode_Immediate = 0x00000003, + WGPUPresentMode_Mailbox = 0x00000004, + WGPUPresentMode_Force32 = 0x7FFFFFFF +} WGPUPresentMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUPrimitiveTopology { + WGPUPrimitiveTopology_Undefined = 0x00000000, + WGPUPrimitiveTopology_PointList = 0x00000001, + WGPUPrimitiveTopology_LineList = 0x00000002, + WGPUPrimitiveTopology_LineStrip = 0x00000003, + WGPUPrimitiveTopology_TriangleList = 0x00000004, + WGPUPrimitiveTopology_TriangleStrip = 0x00000005, + WGPUPrimitiveTopology_Force32 = 0x7FFFFFFF +} WGPUPrimitiveTopology WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUQueryType { + WGPUQueryType_Occlusion = 0x00000001, + WGPUQueryType_Timestamp = 0x00000002, + WGPUQueryType_Force32 = 0x7FFFFFFF +} WGPUQueryType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUQueueWorkDoneStatus { + WGPUQueueWorkDoneStatus_Success = 0x00000001, + WGPUQueueWorkDoneStatus_CallbackCancelled = 0x00000002, + WGPUQueueWorkDoneStatus_Error = 0x00000003, + WGPUQueueWorkDoneStatus_Force32 = 0x7FFFFFFF +} WGPUQueueWorkDoneStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPURequestAdapterStatus { + WGPURequestAdapterStatus_Success = 0x00000001, + WGPURequestAdapterStatus_CallbackCancelled = 0x00000002, + WGPURequestAdapterStatus_Unavailable = 0x00000003, + WGPURequestAdapterStatus_Error = 0x00000004, + WGPURequestAdapterStatus_Force32 = 0x7FFFFFFF +} WGPURequestAdapterStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPURequestDeviceStatus { + WGPURequestDeviceStatus_Success = 0x00000001, + WGPURequestDeviceStatus_CallbackCancelled = 0x00000002, + WGPURequestDeviceStatus_Error = 0x00000003, + WGPURequestDeviceStatus_Force32 = 0x7FFFFFFF +} WGPURequestDeviceStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUSamplerBindingType { + WGPUSamplerBindingType_BindingNotUsed = 0x00000000, + WGPUSamplerBindingType_Undefined = 0x00000001, + WGPUSamplerBindingType_Filtering = 0x00000002, + WGPUSamplerBindingType_NonFiltering = 0x00000003, + WGPUSamplerBindingType_Comparison = 0x00000004, + WGPUSamplerBindingType_Force32 = 0x7FFFFFFF +} WGPUSamplerBindingType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUSharedFenceType { + WGPUSharedFenceType_VkSemaphoreOpaqueFD = 0x00000001, + WGPUSharedFenceType_SyncFD = 0x00000002, + WGPUSharedFenceType_VkSemaphoreZirconHandle = 0x00000003, + WGPUSharedFenceType_DXGISharedHandle = 0x00000004, + WGPUSharedFenceType_MTLSharedEvent = 0x00000005, + WGPUSharedFenceType_EGLSync = 0x00000006, + WGPUSharedFenceType_Force32 = 0x7FFFFFFF +} WGPUSharedFenceType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUStatus { + WGPUStatus_Success = 0x00000001, + WGPUStatus_Error = 0x00000002, + WGPUStatus_Force32 = 0x7FFFFFFF +} WGPUStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUStencilOperation { + WGPUStencilOperation_Undefined = 0x00000000, + WGPUStencilOperation_Keep = 0x00000001, + WGPUStencilOperation_Zero = 0x00000002, + WGPUStencilOperation_Replace = 0x00000003, + WGPUStencilOperation_Invert = 0x00000004, + WGPUStencilOperation_IncrementClamp = 0x00000005, + WGPUStencilOperation_DecrementClamp = 0x00000006, + WGPUStencilOperation_IncrementWrap = 0x00000007, + WGPUStencilOperation_DecrementWrap = 0x00000008, + WGPUStencilOperation_Force32 = 0x7FFFFFFF +} WGPUStencilOperation WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUStorageTextureAccess { + WGPUStorageTextureAccess_BindingNotUsed = 0x00000000, + WGPUStorageTextureAccess_Undefined = 0x00000001, + WGPUStorageTextureAccess_WriteOnly = 0x00000002, + WGPUStorageTextureAccess_ReadOnly = 0x00000003, + WGPUStorageTextureAccess_ReadWrite = 0x00000004, + WGPUStorageTextureAccess_Force32 = 0x7FFFFFFF +} WGPUStorageTextureAccess WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUStoreOp { + WGPUStoreOp_Undefined = 0x00000000, + WGPUStoreOp_Store = 0x00000001, + WGPUStoreOp_Discard = 0x00000002, + WGPUStoreOp_Force32 = 0x7FFFFFFF +} WGPUStoreOp WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUSType { + WGPUSType_ShaderSourceSPIRV = 0x00000001, + WGPUSType_ShaderSourceWGSL = 0x00000002, + WGPUSType_RenderPassMaxDrawCount = 0x00000003, + WGPUSType_SurfaceSourceMetalLayer = 0x00000004, + WGPUSType_SurfaceSourceWindowsHWND = 0x00000005, + WGPUSType_SurfaceSourceXlibWindow = 0x00000006, + WGPUSType_SurfaceSourceWaylandSurface = 0x00000007, + WGPUSType_SurfaceSourceAndroidNativeWindow = 0x00000008, + WGPUSType_SurfaceSourceXCBWindow = 0x00000009, + WGPUSType_SurfaceColorManagement = 0x0000000A, + WGPUSType_RequestAdapterWebXROptions = 0x0000000B, + WGPUSType_TextureComponentSwizzleDescriptor = 0x0000000C, + WGPUSType_CompatibilityModeLimits = 0x00020000, + WGPUSType_TextureBindingViewDimensionDescriptor = 0x00020001, + WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector = 0x00040000, + WGPUSType_SurfaceDescriptorFromWindowsCoreWindow = 0x00050000, + WGPUSType_ExternalTextureBindingEntry = 0x00050001, + WGPUSType_ExternalTextureBindingLayout = 0x00050002, + WGPUSType_SurfaceDescriptorFromWindowsUWPSwapChainPanel = 0x00050003, + WGPUSType_DawnTextureInternalUsageDescriptor = 0x00050004, + WGPUSType_DawnEncoderInternalUsageDescriptor = 0x00050005, + WGPUSType_DawnInstanceDescriptor = 0x00050006, + WGPUSType_DawnCacheDeviceDescriptor = 0x00050007, + WGPUSType_DawnAdapterPropertiesPowerPreference = 0x00050008, + WGPUSType_DawnBufferDescriptorErrorInfoFromWireClient = 0x00050009, + WGPUSType_DawnTogglesDescriptor = 0x0005000A, + WGPUSType_DawnShaderModuleSPIRVOptionsDescriptor = 0x0005000B, + WGPUSType_RequestAdapterOptionsLUID = 0x0005000C, + WGPUSType_RequestAdapterOptionsGetGLProc = 0x0005000D, + WGPUSType_RequestAdapterOptionsD3D11Device = 0x0005000E, + WGPUSType_DawnRenderPassColorAttachmentRenderToSingleSampled = 0x0005000F, + WGPUSType_RenderPassPixelLocalStorage = 0x00050010, + WGPUSType_PipelineLayoutPixelLocalStorage = 0x00050011, + WGPUSType_BufferHostMappedPointer = 0x00050012, + WGPUSType_AdapterPropertiesMemoryHeaps = 0x00050013, + WGPUSType_AdapterPropertiesD3D = 0x00050014, + WGPUSType_AdapterPropertiesVk = 0x00050015, + WGPUSType_DawnWireWGSLControl = 0x00050016, + WGPUSType_DawnWGSLBlocklist = 0x00050017, + WGPUSType_DawnDrmFormatCapabilities = 0x00050018, + WGPUSType_ShaderModuleCompilationOptions = 0x00050019, + WGPUSType_ColorTargetStateExpandResolveTextureDawn = 0x0005001A, + WGPUSType_RenderPassDescriptorExpandResolveRect = 0x0005001B, + WGPUSType_SharedTextureMemoryVkDedicatedAllocationDescriptor = 0x0005001C, + WGPUSType_SharedTextureMemoryAHardwareBufferDescriptor = 0x0005001D, + WGPUSType_SharedTextureMemoryDmaBufDescriptor = 0x0005001E, + WGPUSType_SharedTextureMemoryOpaqueFDDescriptor = 0x0005001F, + WGPUSType_SharedTextureMemoryZirconHandleDescriptor = 0x00050020, + WGPUSType_SharedTextureMemoryDXGISharedHandleDescriptor = 0x00050021, + WGPUSType_SharedTextureMemoryD3D11Texture2DDescriptor = 0x00050022, + WGPUSType_SharedTextureMemoryIOSurfaceDescriptor = 0x00050023, + WGPUSType_SharedTextureMemoryEGLImageDescriptor = 0x00050024, + WGPUSType_SharedTextureMemoryInitializedBeginState = 0x00050025, + WGPUSType_SharedTextureMemoryInitializedEndState = 0x00050026, + WGPUSType_SharedTextureMemoryVkImageLayoutBeginState = 0x00050027, + WGPUSType_SharedTextureMemoryVkImageLayoutEndState = 0x00050028, + WGPUSType_SharedTextureMemoryD3DSwapchainBeginState = 0x00050029, + WGPUSType_SharedFenceVkSemaphoreOpaqueFDDescriptor = 0x0005002A, + WGPUSType_SharedFenceVkSemaphoreOpaqueFDExportInfo = 0x0005002B, + WGPUSType_SharedFenceSyncFDDescriptor = 0x0005002C, + WGPUSType_SharedFenceSyncFDExportInfo = 0x0005002D, + WGPUSType_SharedFenceVkSemaphoreZirconHandleDescriptor = 0x0005002E, + WGPUSType_SharedFenceVkSemaphoreZirconHandleExportInfo = 0x0005002F, + WGPUSType_SharedFenceDXGISharedHandleDescriptor = 0x00050030, + WGPUSType_SharedFenceDXGISharedHandleExportInfo = 0x00050031, + WGPUSType_SharedFenceMTLSharedEventDescriptor = 0x00050032, + WGPUSType_SharedFenceMTLSharedEventExportInfo = 0x00050033, + WGPUSType_SharedBufferMemoryD3D12ResourceDescriptor = 0x00050034, + WGPUSType_StaticSamplerBindingLayout = 0x00050035, + WGPUSType_YCbCrVkDescriptor = 0x00050036, + WGPUSType_SharedTextureMemoryAHardwareBufferProperties = 0x00050037, + WGPUSType_AHardwareBufferProperties = 0x00050038, + WGPUSType_DawnTexelCopyBufferRowAlignmentLimits = 0x0005003A, + WGPUSType_AdapterPropertiesSubgroupMatrixConfigs = 0x0005003B, + WGPUSType_SharedFenceEGLSyncDescriptor = 0x0005003C, + WGPUSType_SharedFenceEGLSyncExportInfo = 0x0005003D, + WGPUSType_DawnInjectedInvalidSType = 0x0005003E, + WGPUSType_DawnCompilationMessageUtf16 = 0x0005003F, + WGPUSType_DawnFakeBufferOOMForTesting = 0x00050040, + WGPUSType_SurfaceDescriptorFromWindowsWinUISwapChainPanel = 0x00050041, + WGPUSType_DawnDeviceAllocatorControl = 0x00050042, + WGPUSType_DawnHostMappedPointerLimits = 0x00050043, + WGPUSType_RenderPassDescriptorResolveRect = 0x00050044, + WGPUSType_RequestAdapterWebGPUBackendOptions = 0x00050045, + WGPUSType_DawnFakeDeviceInitializeErrorForTesting = 0x00050046, + WGPUSType_SharedTextureMemoryD3D11BeginState = 0x00050047, + WGPUSType_DawnConsumeAdapterDescriptor = 0x00050048, + WGPUSType_TexelBufferBindingEntry = 0x00050049, + WGPUSType_TexelBufferBindingLayout = 0x0005004A, + WGPUSType_SharedTextureMemoryMetalEndAccessState = 0x0005004B, + WGPUSType_AdapterPropertiesWGPU = 0x0005004C, + WGPUSType_SharedBufferMemoryD3D12SharedMemoryFileMappingHandleDescriptor = 0x0005004D, + WGPUSType_SharedTextureMemoryD3D12ResourceDescriptor = 0x0005004E, + WGPUSType_RequestAdapterOptionsAngleVirtualizationGroup = 0x0005004F, + WGPUSType_ResourceTableLimits = 0x00050050, + WGPUSType_PipelineLayoutResourceTable = 0x00050051, + WGPUSType_Force32 = 0x7FFFFFFF +} WGPUSType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUSubgroupMatrixComponentType { + WGPUSubgroupMatrixComponentType_F32 = 0x00000001, + WGPUSubgroupMatrixComponentType_F16 = 0x00000002, + WGPUSubgroupMatrixComponentType_U32 = 0x00000003, + WGPUSubgroupMatrixComponentType_I32 = 0x00000004, + WGPUSubgroupMatrixComponentType_U8 = 0x00000005, + WGPUSubgroupMatrixComponentType_I8 = 0x00000006, + WGPUSubgroupMatrixComponentType_Force32 = 0x7FFFFFFF +} WGPUSubgroupMatrixComponentType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUSurfaceGetCurrentTextureStatus { + WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal = 0x00000001, + WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal = 0x00000002, + WGPUSurfaceGetCurrentTextureStatus_Timeout = 0x00000003, + WGPUSurfaceGetCurrentTextureStatus_Outdated = 0x00000004, + WGPUSurfaceGetCurrentTextureStatus_Lost = 0x00000005, + WGPUSurfaceGetCurrentTextureStatus_Error = 0x00000006, + WGPUSurfaceGetCurrentTextureStatus_Force32 = 0x7FFFFFFF +} WGPUSurfaceGetCurrentTextureStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUTexelBufferAccess { + WGPUTexelBufferAccess_Undefined = 0x00000000, + WGPUTexelBufferAccess_ReadOnly = 0x00000001, + WGPUTexelBufferAccess_ReadWrite = 0x00000002, + WGPUTexelBufferAccess_Force32 = 0x7FFFFFFF +} WGPUTexelBufferAccess WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUTextureAspect { + WGPUTextureAspect_Undefined = 0x00000000, + WGPUTextureAspect_All = 0x00000001, + WGPUTextureAspect_StencilOnly = 0x00000002, + WGPUTextureAspect_DepthOnly = 0x00000003, + WGPUTextureAspect_Plane0Only = 0x00050000, + WGPUTextureAspect_Plane1Only = 0x00050001, + WGPUTextureAspect_Plane2Only = 0x00050002, + WGPUTextureAspect_Force32 = 0x7FFFFFFF +} WGPUTextureAspect WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUTextureDimension { + WGPUTextureDimension_Undefined = 0x00000000, + WGPUTextureDimension_1D = 0x00000001, + WGPUTextureDimension_2D = 0x00000002, + WGPUTextureDimension_3D = 0x00000003, + WGPUTextureDimension_Force32 = 0x7FFFFFFF +} WGPUTextureDimension WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUTextureFormat { + WGPUTextureFormat_Undefined = 0x00000000, + WGPUTextureFormat_R8Unorm = 0x00000001, + WGPUTextureFormat_R8Snorm = 0x00000002, + WGPUTextureFormat_R8Uint = 0x00000003, + WGPUTextureFormat_R8Sint = 0x00000004, + WGPUTextureFormat_R16Unorm = 0x00000005, + WGPUTextureFormat_R16Snorm = 0x00000006, + WGPUTextureFormat_R16Uint = 0x00000007, + WGPUTextureFormat_R16Sint = 0x00000008, + WGPUTextureFormat_R16Float = 0x00000009, + WGPUTextureFormat_RG8Unorm = 0x0000000A, + WGPUTextureFormat_RG8Snorm = 0x0000000B, + WGPUTextureFormat_RG8Uint = 0x0000000C, + WGPUTextureFormat_RG8Sint = 0x0000000D, + WGPUTextureFormat_R32Float = 0x0000000E, + WGPUTextureFormat_R32Uint = 0x0000000F, + WGPUTextureFormat_R32Sint = 0x00000010, + WGPUTextureFormat_RG16Unorm = 0x00000011, + WGPUTextureFormat_RG16Snorm = 0x00000012, + WGPUTextureFormat_RG16Uint = 0x00000013, + WGPUTextureFormat_RG16Sint = 0x00000014, + WGPUTextureFormat_RG16Float = 0x00000015, + WGPUTextureFormat_RGBA8Unorm = 0x00000016, + WGPUTextureFormat_RGBA8UnormSrgb = 0x00000017, + WGPUTextureFormat_RGBA8Snorm = 0x00000018, + WGPUTextureFormat_RGBA8Uint = 0x00000019, + WGPUTextureFormat_RGBA8Sint = 0x0000001A, + WGPUTextureFormat_BGRA8Unorm = 0x0000001B, + WGPUTextureFormat_BGRA8UnormSrgb = 0x0000001C, + WGPUTextureFormat_RGB10A2Uint = 0x0000001D, + WGPUTextureFormat_RGB10A2Unorm = 0x0000001E, + WGPUTextureFormat_RG11B10Ufloat = 0x0000001F, + WGPUTextureFormat_RGB9E5Ufloat = 0x00000020, + WGPUTextureFormat_RG32Float = 0x00000021, + WGPUTextureFormat_RG32Uint = 0x00000022, + WGPUTextureFormat_RG32Sint = 0x00000023, + WGPUTextureFormat_RGBA16Unorm = 0x00000024, + WGPUTextureFormat_RGBA16Snorm = 0x00000025, + WGPUTextureFormat_RGBA16Uint = 0x00000026, + WGPUTextureFormat_RGBA16Sint = 0x00000027, + WGPUTextureFormat_RGBA16Float = 0x00000028, + WGPUTextureFormat_RGBA32Float = 0x00000029, + WGPUTextureFormat_RGBA32Uint = 0x0000002A, + WGPUTextureFormat_RGBA32Sint = 0x0000002B, + WGPUTextureFormat_Stencil8 = 0x0000002C, + WGPUTextureFormat_Depth16Unorm = 0x0000002D, + WGPUTextureFormat_Depth24Plus = 0x0000002E, + WGPUTextureFormat_Depth24PlusStencil8 = 0x0000002F, + WGPUTextureFormat_Depth32Float = 0x00000030, + WGPUTextureFormat_Depth32FloatStencil8 = 0x00000031, + WGPUTextureFormat_BC1RGBAUnorm = 0x00000032, + WGPUTextureFormat_BC1RGBAUnormSrgb = 0x00000033, + WGPUTextureFormat_BC2RGBAUnorm = 0x00000034, + WGPUTextureFormat_BC2RGBAUnormSrgb = 0x00000035, + WGPUTextureFormat_BC3RGBAUnorm = 0x00000036, + WGPUTextureFormat_BC3RGBAUnormSrgb = 0x00000037, + WGPUTextureFormat_BC4RUnorm = 0x00000038, + WGPUTextureFormat_BC4RSnorm = 0x00000039, + WGPUTextureFormat_BC5RGUnorm = 0x0000003A, + WGPUTextureFormat_BC5RGSnorm = 0x0000003B, + WGPUTextureFormat_BC6HRGBUfloat = 0x0000003C, + WGPUTextureFormat_BC6HRGBFloat = 0x0000003D, + WGPUTextureFormat_BC7RGBAUnorm = 0x0000003E, + WGPUTextureFormat_BC7RGBAUnormSrgb = 0x0000003F, + WGPUTextureFormat_ETC2RGB8Unorm = 0x00000040, + WGPUTextureFormat_ETC2RGB8UnormSrgb = 0x00000041, + WGPUTextureFormat_ETC2RGB8A1Unorm = 0x00000042, + WGPUTextureFormat_ETC2RGB8A1UnormSrgb = 0x00000043, + WGPUTextureFormat_ETC2RGBA8Unorm = 0x00000044, + WGPUTextureFormat_ETC2RGBA8UnormSrgb = 0x00000045, + WGPUTextureFormat_EACR11Unorm = 0x00000046, + WGPUTextureFormat_EACR11Snorm = 0x00000047, + WGPUTextureFormat_EACRG11Unorm = 0x00000048, + WGPUTextureFormat_EACRG11Snorm = 0x00000049, + WGPUTextureFormat_ASTC4x4Unorm = 0x0000004A, + WGPUTextureFormat_ASTC4x4UnormSrgb = 0x0000004B, + WGPUTextureFormat_ASTC5x4Unorm = 0x0000004C, + WGPUTextureFormat_ASTC5x4UnormSrgb = 0x0000004D, + WGPUTextureFormat_ASTC5x5Unorm = 0x0000004E, + WGPUTextureFormat_ASTC5x5UnormSrgb = 0x0000004F, + WGPUTextureFormat_ASTC6x5Unorm = 0x00000050, + WGPUTextureFormat_ASTC6x5UnormSrgb = 0x00000051, + WGPUTextureFormat_ASTC6x6Unorm = 0x00000052, + WGPUTextureFormat_ASTC6x6UnormSrgb = 0x00000053, + WGPUTextureFormat_ASTC8x5Unorm = 0x00000054, + WGPUTextureFormat_ASTC8x5UnormSrgb = 0x00000055, + WGPUTextureFormat_ASTC8x6Unorm = 0x00000056, + WGPUTextureFormat_ASTC8x6UnormSrgb = 0x00000057, + WGPUTextureFormat_ASTC8x8Unorm = 0x00000058, + WGPUTextureFormat_ASTC8x8UnormSrgb = 0x00000059, + WGPUTextureFormat_ASTC10x5Unorm = 0x0000005A, + WGPUTextureFormat_ASTC10x5UnormSrgb = 0x0000005B, + WGPUTextureFormat_ASTC10x6Unorm = 0x0000005C, + WGPUTextureFormat_ASTC10x6UnormSrgb = 0x0000005D, + WGPUTextureFormat_ASTC10x8Unorm = 0x0000005E, + WGPUTextureFormat_ASTC10x8UnormSrgb = 0x0000005F, + WGPUTextureFormat_ASTC10x10Unorm = 0x00000060, + WGPUTextureFormat_ASTC10x10UnormSrgb = 0x00000061, + WGPUTextureFormat_ASTC12x10Unorm = 0x00000062, + WGPUTextureFormat_ASTC12x10UnormSrgb = 0x00000063, + WGPUTextureFormat_ASTC12x12Unorm = 0x00000064, + WGPUTextureFormat_ASTC12x12UnormSrgb = 0x00000065, + WGPUTextureFormat_R8BG8Biplanar420Unorm = 0x00050006, + WGPUTextureFormat_R10X6BG10X6Biplanar420Unorm = 0x00050007, + WGPUTextureFormat_R8BG8A8Triplanar420Unorm = 0x00050008, + WGPUTextureFormat_R8BG8Biplanar422Unorm = 0x00050009, + WGPUTextureFormat_R8BG8Biplanar444Unorm = 0x0005000A, + WGPUTextureFormat_R10X6BG10X6Biplanar422Unorm = 0x0005000B, + WGPUTextureFormat_R10X6BG10X6Biplanar444Unorm = 0x0005000C, + WGPUTextureFormat_External = 0x0005000D, + WGPUTextureFormat_Force32 = 0x7FFFFFFF +} WGPUTextureFormat WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUTextureSampleType { + WGPUTextureSampleType_BindingNotUsed = 0x00000000, + WGPUTextureSampleType_Undefined = 0x00000001, + WGPUTextureSampleType_Float = 0x00000002, + WGPUTextureSampleType_UnfilterableFloat = 0x00000003, + WGPUTextureSampleType_Depth = 0x00000004, + WGPUTextureSampleType_Sint = 0x00000005, + WGPUTextureSampleType_Uint = 0x00000006, + WGPUTextureSampleType_Force32 = 0x7FFFFFFF +} WGPUTextureSampleType WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUTextureViewDimension { + WGPUTextureViewDimension_Undefined = 0x00000000, + WGPUTextureViewDimension_1D = 0x00000001, + WGPUTextureViewDimension_2D = 0x00000002, + WGPUTextureViewDimension_2DArray = 0x00000003, + WGPUTextureViewDimension_Cube = 0x00000004, + WGPUTextureViewDimension_CubeArray = 0x00000005, + WGPUTextureViewDimension_3D = 0x00000006, + WGPUTextureViewDimension_Force32 = 0x7FFFFFFF +} WGPUTextureViewDimension WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUToneMappingMode { + WGPUToneMappingMode_Standard = 0x00000001, + WGPUToneMappingMode_Extended = 0x00000002, + WGPUToneMappingMode_Force32 = 0x7FFFFFFF +} WGPUToneMappingMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUVertexFormat { + WGPUVertexFormat_Uint8 = 0x00000001, + WGPUVertexFormat_Uint8x2 = 0x00000002, + WGPUVertexFormat_Uint8x4 = 0x00000003, + WGPUVertexFormat_Sint8 = 0x00000004, + WGPUVertexFormat_Sint8x2 = 0x00000005, + WGPUVertexFormat_Sint8x4 = 0x00000006, + WGPUVertexFormat_Unorm8 = 0x00000007, + WGPUVertexFormat_Unorm8x2 = 0x00000008, + WGPUVertexFormat_Unorm8x4 = 0x00000009, + WGPUVertexFormat_Snorm8 = 0x0000000A, + WGPUVertexFormat_Snorm8x2 = 0x0000000B, + WGPUVertexFormat_Snorm8x4 = 0x0000000C, + WGPUVertexFormat_Uint16 = 0x0000000D, + WGPUVertexFormat_Uint16x2 = 0x0000000E, + WGPUVertexFormat_Uint16x4 = 0x0000000F, + WGPUVertexFormat_Sint16 = 0x00000010, + WGPUVertexFormat_Sint16x2 = 0x00000011, + WGPUVertexFormat_Sint16x4 = 0x00000012, + WGPUVertexFormat_Unorm16 = 0x00000013, + WGPUVertexFormat_Unorm16x2 = 0x00000014, + WGPUVertexFormat_Unorm16x4 = 0x00000015, + WGPUVertexFormat_Snorm16 = 0x00000016, + WGPUVertexFormat_Snorm16x2 = 0x00000017, + WGPUVertexFormat_Snorm16x4 = 0x00000018, + WGPUVertexFormat_Float16 = 0x00000019, + WGPUVertexFormat_Float16x2 = 0x0000001A, + WGPUVertexFormat_Float16x4 = 0x0000001B, + WGPUVertexFormat_Float32 = 0x0000001C, + WGPUVertexFormat_Float32x2 = 0x0000001D, + WGPUVertexFormat_Float32x3 = 0x0000001E, + WGPUVertexFormat_Float32x4 = 0x0000001F, + WGPUVertexFormat_Uint32 = 0x00000020, + WGPUVertexFormat_Uint32x2 = 0x00000021, + WGPUVertexFormat_Uint32x3 = 0x00000022, + WGPUVertexFormat_Uint32x4 = 0x00000023, + WGPUVertexFormat_Sint32 = 0x00000024, + WGPUVertexFormat_Sint32x2 = 0x00000025, + WGPUVertexFormat_Sint32x3 = 0x00000026, + WGPUVertexFormat_Sint32x4 = 0x00000027, + WGPUVertexFormat_Unorm10_10_10_2 = 0x00000028, + WGPUVertexFormat_Unorm8x4BGRA = 0x00000029, + WGPUVertexFormat_Force32 = 0x7FFFFFFF +} WGPUVertexFormat WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUVertexStepMode { + WGPUVertexStepMode_Undefined = 0x00000000, + WGPUVertexStepMode_Vertex = 0x00000001, + WGPUVertexStepMode_Instance = 0x00000002, + WGPUVertexStepMode_Force32 = 0x7FFFFFFF +} WGPUVertexStepMode WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUWaitStatus { + WGPUWaitStatus_Success = 0x00000001, + WGPUWaitStatus_TimedOut = 0x00000002, + WGPUWaitStatus_Error = 0x00000003, + WGPUWaitStatus_Force32 = 0x7FFFFFFF +} WGPUWaitStatus WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUWGSLLanguageFeatureName { + WGPUWGSLLanguageFeatureName_ReadonlyAndReadwriteStorageTextures = 0x00000001, + WGPUWGSLLanguageFeatureName_Packed4x8IntegerDotProduct = 0x00000002, + WGPUWGSLLanguageFeatureName_UnrestrictedPointerParameters = 0x00000003, + WGPUWGSLLanguageFeatureName_PointerCompositeAccess = 0x00000004, + WGPUWGSLLanguageFeatureName_UniformBufferStandardLayout = 0x00000005, + WGPUWGSLLanguageFeatureName_SubgroupId = 0x00000006, + WGPUWGSLLanguageFeatureName_SizedBindingArray = 0x00050007, + WGPUWGSLLanguageFeatureName_TexelBuffers = 0x00050008, + WGPUWGSLLanguageFeatureName_ChromiumPrint = 0x00050009, + WGPUWGSLLanguageFeatureName_FragmentDepth = 0x0005000A, + WGPUWGSLLanguageFeatureName_ImmediateAddressSpace = 0x0005000B, + WGPUWGSLLanguageFeatureName_SubgroupUniformity = 0x0005000C, + WGPUWGSLLanguageFeatureName_TextureAndSamplerLet = 0x0005000D, + WGPUWGSLLanguageFeatureName_BufferView = 0x0005000E, + WGPUWGSLLanguageFeatureName_ChromiumTestingUnimplemented = 0x00050000, + WGPUWGSLLanguageFeatureName_ChromiumTestingUnsafeExperimental = 0x00050001, + WGPUWGSLLanguageFeatureName_ChromiumTestingExperimental = 0x00050002, + WGPUWGSLLanguageFeatureName_ChromiumTestingShippedWithKillswitch = 0x00050003, + WGPUWGSLLanguageFeatureName_ChromiumTestingShipped = 0x00050004, + WGPUWGSLLanguageFeatureName_Force32 = 0x7FFFFFFF +} WGPUWGSLLanguageFeatureName WGPU_ENUM_ATTRIBUTE; + +typedef WGPUFlags WGPUBufferUsage; +static const WGPUBufferUsage WGPUBufferUsage_None = 0x0000000000000000; +static const WGPUBufferUsage WGPUBufferUsage_MapRead = 0x0000000000000001; +static const WGPUBufferUsage WGPUBufferUsage_MapWrite = 0x0000000000000002; +static const WGPUBufferUsage WGPUBufferUsage_CopySrc = 0x0000000000000004; +static const WGPUBufferUsage WGPUBufferUsage_CopyDst = 0x0000000000000008; +static const WGPUBufferUsage WGPUBufferUsage_Index = 0x0000000000000010; +static const WGPUBufferUsage WGPUBufferUsage_Vertex = 0x0000000000000020; +static const WGPUBufferUsage WGPUBufferUsage_Uniform = 0x0000000000000040; +static const WGPUBufferUsage WGPUBufferUsage_Storage = 0x0000000000000080; +static const WGPUBufferUsage WGPUBufferUsage_Indirect = 0x0000000000000100; +static const WGPUBufferUsage WGPUBufferUsage_QueryResolve = 0x0000000000000200; +static const WGPUBufferUsage WGPUBufferUsage_TexelBuffer = 0x0000000000000400; + +typedef WGPUFlags WGPUColorWriteMask; +static const WGPUColorWriteMask WGPUColorWriteMask_None = 0x0000000000000000; +static const WGPUColorWriteMask WGPUColorWriteMask_Red = 0x0000000000000001; +static const WGPUColorWriteMask WGPUColorWriteMask_Green = 0x0000000000000002; +static const WGPUColorWriteMask WGPUColorWriteMask_Blue = 0x0000000000000004; +static const WGPUColorWriteMask WGPUColorWriteMask_Alpha = 0x0000000000000008; +static const WGPUColorWriteMask WGPUColorWriteMask_All = 0x000000000000000F; + +typedef WGPUFlags WGPUHeapProperty; +static const WGPUHeapProperty WGPUHeapProperty_None = 0x0000000000000000; +static const WGPUHeapProperty WGPUHeapProperty_DeviceLocal = 0x0000000000000001; +static const WGPUHeapProperty WGPUHeapProperty_HostVisible = 0x0000000000000002; +static const WGPUHeapProperty WGPUHeapProperty_HostCoherent = 0x0000000000000004; +static const WGPUHeapProperty WGPUHeapProperty_HostUncached = 0x0000000000000008; +static const WGPUHeapProperty WGPUHeapProperty_HostCached = 0x0000000000000010; + +typedef WGPUFlags WGPUMapMode; +static const WGPUMapMode WGPUMapMode_None = 0x0000000000000000; +static const WGPUMapMode WGPUMapMode_Read = 0x0000000000000001; +static const WGPUMapMode WGPUMapMode_Write = 0x0000000000000002; + +typedef WGPUFlags WGPUShaderStage; +static const WGPUShaderStage WGPUShaderStage_None = 0x0000000000000000; +static const WGPUShaderStage WGPUShaderStage_Vertex = 0x0000000000000001; +static const WGPUShaderStage WGPUShaderStage_Fragment = 0x0000000000000002; +static const WGPUShaderStage WGPUShaderStage_Compute = 0x0000000000000004; + +typedef WGPUFlags WGPUTextureUsage; +static const WGPUTextureUsage WGPUTextureUsage_None = 0x0000000000000000; +static const WGPUTextureUsage WGPUTextureUsage_CopySrc = 0x0000000000000001; +static const WGPUTextureUsage WGPUTextureUsage_CopyDst = 0x0000000000000002; +static const WGPUTextureUsage WGPUTextureUsage_TextureBinding = 0x0000000000000004; +static const WGPUTextureUsage WGPUTextureUsage_StorageBinding = 0x0000000000000008; +static const WGPUTextureUsage WGPUTextureUsage_RenderAttachment = 0x0000000000000010; +static const WGPUTextureUsage WGPUTextureUsage_TransientAttachment = 0x0000000000000020; +static const WGPUTextureUsage WGPUTextureUsage_StorageAttachment = 0x0000000000000040; + +typedef void (*WGPUCallback)(void * userdata) WGPU_FUNCTION_ATTRIBUTE; +typedef size_t (*WGPUDawnLoadCacheDataFunction)(void const * key, size_t keySize, void * value, size_t valueSize, void * userdata) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUDawnStoreCacheDataFunction)(void const * key, size_t keySize, void const * value, size_t valueSize, void * userdata) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProc)(void) WGPU_FUNCTION_ATTRIBUTE; + +// Callback function pointers +typedef void (*WGPUBufferMapCallback)(WGPUMapAsyncStatus status, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUCompilationInfoCallback)(WGPUCompilationInfoRequestStatus status, struct WGPUCompilationInfo const * compilationInfo, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUCreateComputePipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUCreateRenderPipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUDeviceLostCallback)(WGPUDevice const * device, WGPUDeviceLostReason reason, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPULoggingCallback)(WGPULoggingType type, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUPopErrorScopeCallback)(WGPUPopErrorScopeStatus status, WGPUErrorType type, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUQueueWorkDoneCallback)(WGPUQueueWorkDoneStatus status, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPURequestAdapterCallback)(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPURequestDeviceCallback)(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef void (*WGPUUncapturedErrorCallback)(WGPUDevice const * device, WGPUErrorType type, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; + +typedef struct WGPUChainedStruct { + struct WGPUChainedStruct * next; + WGPUSType sType; +} WGPUChainedStruct WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUBufferMapCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUBufferMapCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUBufferMapCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BUFFER_MAP_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBufferMapCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUCompilationInfoCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUCompilationInfoCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUCompilationInfoCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPILATION_INFO_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCompilationInfoCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUCreateComputePipelineAsyncCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUCreateComputePipelineAsyncCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUCreateComputePipelineAsyncCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_CREATE_COMPUTE_PIPELINE_ASYNC_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCreateComputePipelineAsyncCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUCreateRenderPipelineAsyncCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUCreateRenderPipelineAsyncCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUCreateRenderPipelineAsyncCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_CREATE_RENDER_PIPELINE_ASYNC_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCreateRenderPipelineAsyncCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUDeviceLostCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUDeviceLostCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUDeviceLostCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DEVICE_LOST_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDeviceLostCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPULoggingCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPULoggingCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPULoggingCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_LOGGING_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPULoggingCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUPopErrorScopeCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUPopErrorScopeCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUPopErrorScopeCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPopErrorScopeCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUQueueWorkDoneCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPUQueueWorkDoneCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUQueueWorkDoneCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_QUEUE_WORK_DONE_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUQueueWorkDoneCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPURequestAdapterCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPURequestAdapterCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPURequestAdapterCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_REQUEST_ADAPTER_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPURequestAdapterCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPURequestDeviceCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUCallbackMode mode; + WGPURequestDeviceCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPURequestDeviceCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_REQUEST_DEVICE_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPURequestDeviceCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.mode=*/_wgpu_ENUM_ZERO_INIT(WGPUCallbackMode) _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUUncapturedErrorCallbackInfo { + WGPUChainedStruct * nextInChain; + WGPUUncapturedErrorCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUUncapturedErrorCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_UNCAPTURED_ERROR_CALLBACK_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUUncapturedErrorCallbackInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.callback=*/NULL _wgpu_COMMA \ + /*.userdata1=*/NULL _wgpu_COMMA \ + /*.userdata2=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUAdapterInfo +typedef struct WGPUAdapterPropertiesD3D { + WGPUChainedStruct chain; + uint32_t shaderModel; +} WGPUAdapterPropertiesD3D WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ADAPTER_PROPERTIES_D3D_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAdapterPropertiesD3D, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_AdapterPropertiesD3D _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.shaderModel=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUAdapterInfo +typedef struct WGPUAdapterPropertiesVk { + WGPUChainedStruct chain; + uint32_t driverVersion; +} WGPUAdapterPropertiesVk WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ADAPTER_PROPERTIES_VK_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAdapterPropertiesVk, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_AdapterPropertiesVk _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.driverVersion=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUAdapterInfo +typedef struct WGPUAdapterPropertiesWGPU { + WGPUChainedStruct chain; + WGPUBackendType backendType; +} WGPUAdapterPropertiesWGPU WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ADAPTER_PROPERTIES_WGPU_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAdapterPropertiesWGPU, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_AdapterPropertiesWGPU _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.backendType=*/WGPUBackendType_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUBindingResource { + WGPUChainedStruct * nextInChain; + WGPU_NULLABLE WGPUBuffer buffer; + uint64_t offset; + uint64_t size; + WGPU_NULLABLE WGPUSampler sampler; + WGPU_NULLABLE WGPUTextureView textureView; +} WGPUBindingResource WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BINDING_RESOURCE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBindingResource, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.buffer=*/NULL _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.size=*/WGPU_WHOLE_SIZE _wgpu_COMMA \ + /*.sampler=*/NULL _wgpu_COMMA \ + /*.textureView=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUBlendComponent { + WGPUBlendOperation operation; + WGPUBlendFactor srcFactor; + WGPUBlendFactor dstFactor; +} WGPUBlendComponent WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BLEND_COMPONENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBlendComponent, { \ + /*.operation=*/WGPUBlendOperation_Undefined _wgpu_COMMA \ + /*.srcFactor=*/WGPUBlendFactor_Undefined _wgpu_COMMA \ + /*.dstFactor=*/WGPUBlendFactor_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUBufferBindingLayout { + WGPUChainedStruct * nextInChain; + WGPUBufferBindingType type; + WGPUBool hasDynamicOffset; + uint64_t minBindingSize; +} WGPUBufferBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BUFFER_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBufferBindingLayout, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.type=*/WGPUBufferBindingType_Undefined _wgpu_COMMA \ + /*.hasDynamicOffset=*/WGPU_FALSE _wgpu_COMMA \ + /*.minBindingSize=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUBufferDescriptor +typedef struct WGPUBufferHostMappedPointer { + WGPUChainedStruct chain; + void * pointer; + WGPUCallback disposeCallback; + void * userdata; +} WGPUBufferHostMappedPointer WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BUFFER_HOST_MAPPED_POINTER_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBufferHostMappedPointer, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_BufferHostMappedPointer _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.pointer=*/NULL _wgpu_COMMA \ + /*.disposeCallback=*/NULL _wgpu_COMMA \ + /*.userdata=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUColor { + double r; + double g; + double b; + double a; +} WGPUColor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COLOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUColor, { \ + /*.r=*/0. _wgpu_COMMA \ + /*.g=*/0. _wgpu_COMMA \ + /*.b=*/0. _wgpu_COMMA \ + /*.a=*/0. _wgpu_COMMA \ +}) + +// Can be chained in WGPUColorTargetState +typedef struct WGPUColorTargetStateExpandResolveTextureDawn { + WGPUChainedStruct chain; + WGPUBool enabled; +} WGPUColorTargetStateExpandResolveTextureDawn WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COLOR_TARGET_STATE_EXPAND_RESOLVE_TEXTURE_DAWN_INIT _wgpu_MAKE_INIT_STRUCT(WGPUColorTargetStateExpandResolveTextureDawn, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ColorTargetStateExpandResolveTextureDawn _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.enabled=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUCommandBufferDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUCommandBufferDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMMAND_BUFFER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCommandBufferDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +// Can be chained in WGPULimits +typedef struct WGPUCompatibilityModeLimits { + WGPUChainedStruct chain; + uint32_t maxStorageBuffersInVertexStage; + uint32_t maxStorageTexturesInVertexStage; + uint32_t maxStorageBuffersInFragmentStage; + uint32_t maxStorageTexturesInFragmentStage; +} WGPUCompatibilityModeLimits WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPATIBILITY_MODE_LIMITS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCompatibilityModeLimits, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_CompatibilityModeLimits _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.maxStorageBuffersInVertexStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxStorageTexturesInVertexStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxStorageBuffersInFragmentStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxStorageTexturesInFragmentStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ +}) + +typedef struct WGPUConstantEntry { + WGPUChainedStruct * nextInChain; + WGPUStringView key; + double value; +} WGPUConstantEntry WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_CONSTANT_ENTRY_INIT _wgpu_MAKE_INIT_STRUCT(WGPUConstantEntry, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.key=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.value=*/0. _wgpu_COMMA \ +}) + +typedef struct WGPUCopyTextureForBrowserOptions { + WGPUChainedStruct * nextInChain; + WGPUBool flipY; + WGPUBool needsColorSpaceConversion; + WGPUAlphaMode srcAlphaMode; + WGPU_NULLABLE float const * srcTransferFunctionParameters; + WGPU_NULLABLE float const * conversionMatrix; + WGPU_NULLABLE float const * dstTransferFunctionParameters; + WGPUAlphaMode dstAlphaMode; + WGPUBool internalUsage; +} WGPUCopyTextureForBrowserOptions WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COPY_TEXTURE_FOR_BROWSER_OPTIONS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCopyTextureForBrowserOptions, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.flipY=*/WGPU_FALSE _wgpu_COMMA \ + /*.needsColorSpaceConversion=*/WGPU_FALSE _wgpu_COMMA \ + /*.srcAlphaMode=*/WGPUAlphaMode_Unpremultiplied _wgpu_COMMA \ + /*.srcTransferFunctionParameters=*/NULL _wgpu_COMMA \ + /*.conversionMatrix=*/NULL _wgpu_COMMA \ + /*.dstTransferFunctionParameters=*/NULL _wgpu_COMMA \ + /*.dstAlphaMode=*/WGPUAlphaMode_Unpremultiplied _wgpu_COMMA \ + /*.internalUsage=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUAdapterInfo +typedef struct WGPUDawnAdapterPropertiesPowerPreference { + WGPUChainedStruct chain; + WGPUPowerPreference powerPreference; +} WGPUDawnAdapterPropertiesPowerPreference WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_ADAPTER_PROPERTIES_POWER_PREFERENCE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnAdapterPropertiesPowerPreference, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnAdapterPropertiesPowerPreference _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.powerPreference=*/WGPUPowerPreference_Undefined _wgpu_COMMA \ +}) + +// Can be chained in WGPUBufferDescriptor +typedef struct WGPUDawnBufferDescriptorErrorInfoFromWireClient { + WGPUChainedStruct chain; + WGPUBool outOfMemory; +} WGPUDawnBufferDescriptorErrorInfoFromWireClient WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_BUFFER_DESCRIPTOR_ERROR_INFO_FROM_WIRE_CLIENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnBufferDescriptorErrorInfoFromWireClient, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnBufferDescriptorErrorInfoFromWireClient _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.outOfMemory=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUDeviceDescriptor +typedef struct WGPUDawnCacheDeviceDescriptor { + WGPUChainedStruct chain; + WGPUStringView isolationKey; + WGPUDawnLoadCacheDataFunction loadDataFunction; + WGPUDawnStoreCacheDataFunction storeDataFunction; + void * functionUserdata; +} WGPUDawnCacheDeviceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_CACHE_DEVICE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnCacheDeviceDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnCacheDeviceDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.isolationKey=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.loadDataFunction=*/NULL _wgpu_COMMA \ + /*.storeDataFunction=*/NULL _wgpu_COMMA \ + /*.functionUserdata=*/nullptr _wgpu_COMMA \ +}) + +// Can be chained in WGPUCompilationMessage +typedef struct WGPUDawnCompilationMessageUtf16 { + WGPUChainedStruct chain; + uint64_t linePos; + uint64_t offset; + uint64_t length; +} WGPUDawnCompilationMessageUtf16 WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_COMPILATION_MESSAGE_UTF16_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnCompilationMessageUtf16, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnCompilationMessageUtf16 _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.linePos=*/0 _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.length=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUDeviceDescriptor +typedef struct WGPUDawnConsumeAdapterDescriptor { + WGPUChainedStruct chain; + WGPUBool consumeAdapter; +} WGPUDawnConsumeAdapterDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_CONSUME_ADAPTER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnConsumeAdapterDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnConsumeAdapterDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.consumeAdapter=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUDeviceDescriptor +typedef struct WGPUDawnDeviceAllocatorControl { + WGPUChainedStruct chain; + size_t allocatorHeapBlockSize; +} WGPUDawnDeviceAllocatorControl WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_DEVICE_ALLOCATOR_CONTROL_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnDeviceAllocatorControl, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnDeviceAllocatorControl _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.allocatorHeapBlockSize=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUDawnDrmFormatProperties { + uint64_t modifier; + uint32_t modifierPlaneCount; +} WGPUDawnDrmFormatProperties WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_DRM_FORMAT_PROPERTIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnDrmFormatProperties, { \ + /*.modifier=*/0 _wgpu_COMMA \ + /*.modifierPlaneCount=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUCommandEncoderDescriptor +typedef struct WGPUDawnEncoderInternalUsageDescriptor { + WGPUChainedStruct chain; + WGPUBool useInternalUsages; +} WGPUDawnEncoderInternalUsageDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_ENCODER_INTERNAL_USAGE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnEncoderInternalUsageDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnEncoderInternalUsageDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.useInternalUsages=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUBufferDescriptor +typedef struct WGPUDawnFakeBufferOOMForTesting { + WGPUChainedStruct chain; + WGPUBool fakeOOMAtWireClientMap; + WGPUBool fakeOOMAtNativeMap; + WGPUBool fakeOOMAtDevice; +} WGPUDawnFakeBufferOOMForTesting WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_FAKE_BUFFER_OOM_FOR_TESTING_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnFakeBufferOOMForTesting, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnFakeBufferOOMForTesting _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.fakeOOMAtWireClientMap=*/WGPU_FALSE _wgpu_COMMA \ + /*.fakeOOMAtNativeMap=*/WGPU_FALSE _wgpu_COMMA \ + /*.fakeOOMAtDevice=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUDeviceDescriptor +typedef struct WGPUDawnFakeDeviceInitializeErrorForTesting { + WGPUChainedStruct chain; +} WGPUDawnFakeDeviceInitializeErrorForTesting WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_FAKE_DEVICE_INITIALIZE_ERROR_FOR_TESTING_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnFakeDeviceInitializeErrorForTesting, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnFakeDeviceInitializeErrorForTesting _wgpu_COMMA \ + }) _wgpu_COMMA \ +}) + +// Can be chained in WGPULimits +typedef struct WGPUDawnHostMappedPointerLimits { + WGPUChainedStruct chain; + uint32_t hostMappedPointerAlignment; +} WGPUDawnHostMappedPointerLimits WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_HOST_MAPPED_POINTER_LIMITS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnHostMappedPointerLimits, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnHostMappedPointerLimits _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.hostMappedPointerAlignment=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ +}) + +typedef struct WGPUDawnInjectedInvalidSType { + WGPUChainedStruct chain; + WGPUSType invalidSType; +} WGPUDawnInjectedInvalidSType WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_INJECTED_INVALID_S_TYPE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnInjectedInvalidSType, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnInjectedInvalidSType _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.invalidSType=*/_wgpu_ENUM_ZERO_INIT(WGPUSType) _wgpu_COMMA \ +}) + +// Can be chained in WGPURenderPassColorAttachment +typedef struct WGPUDawnRenderPassColorAttachmentRenderToSingleSampled { + WGPUChainedStruct chain; + uint32_t implicitSampleCount; +} WGPUDawnRenderPassColorAttachmentRenderToSingleSampled WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_RENDER_PASS_COLOR_ATTACHMENT_RENDER_TO_SINGLE_SAMPLED_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnRenderPassColorAttachmentRenderToSingleSampled, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnRenderPassColorAttachmentRenderToSingleSampled _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.implicitSampleCount=*/1 _wgpu_COMMA \ +}) + +// Can be chained in WGPUShaderModuleDescriptor +typedef struct WGPUDawnShaderModuleSPIRVOptionsDescriptor { + WGPUChainedStruct chain; + WGPUBool allowNonUniformDerivatives; +} WGPUDawnShaderModuleSPIRVOptionsDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_SHADER_MODULE_SPIRV_OPTIONS_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnShaderModuleSPIRVOptionsDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnShaderModuleSPIRVOptionsDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.allowNonUniformDerivatives=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPULimits +typedef struct WGPUDawnTexelCopyBufferRowAlignmentLimits { + WGPUChainedStruct chain; + uint32_t minTexelCopyBufferRowAlignment; +} WGPUDawnTexelCopyBufferRowAlignmentLimits WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_TEXEL_COPY_BUFFER_ROW_ALIGNMENT_LIMITS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnTexelCopyBufferRowAlignmentLimits, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnTexelCopyBufferRowAlignmentLimits _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.minTexelCopyBufferRowAlignment=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ +}) + +// Can be chained in WGPUTextureDescriptor +typedef struct WGPUDawnTextureInternalUsageDescriptor { + WGPUChainedStruct chain; + WGPUTextureUsage internalUsage; +} WGPUDawnTextureInternalUsageDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_TEXTURE_INTERNAL_USAGE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnTextureInternalUsageDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnTextureInternalUsageDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.internalUsage=*/WGPUTextureUsage_None _wgpu_COMMA \ +}) + +// Can be chained in WGPUInstanceDescriptor +// Can be chained in WGPURequestAdapterOptions +// Can be chained in WGPUDeviceDescriptor +typedef struct WGPUDawnTogglesDescriptor { + WGPUChainedStruct chain; + size_t enabledToggleCount; + const char* const * enabledToggles; + size_t disabledToggleCount; + const char* const * disabledToggles; +} WGPUDawnTogglesDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_TOGGLES_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnTogglesDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnTogglesDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.enabledToggleCount=*/0 _wgpu_COMMA \ + /*.enabledToggles=*/NULL _wgpu_COMMA \ + /*.disabledToggleCount=*/0 _wgpu_COMMA \ + /*.disabledToggles=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUInstanceDescriptor +typedef struct WGPUDawnWGSLBlocklist { + WGPUChainedStruct chain; + size_t blocklistedFeatureCount; + const char* const * blocklistedFeatures; +} WGPUDawnWGSLBlocklist WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_WGSL_BLOCKLIST_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnWGSLBlocklist, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnWGSLBlocklist _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.blocklistedFeatureCount=*/0 _wgpu_COMMA \ + /*.blocklistedFeatures=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUInstanceDescriptor +typedef struct WGPUDawnWireWGSLControl { + WGPUChainedStruct chain; + WGPUBool enableExperimental; + WGPUBool enableUnsafe; + WGPUBool enableTesting; +} WGPUDawnWireWGSLControl WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_WIRE_WGSL_CONTROL_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnWireWGSLControl, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnWireWGSLControl _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.enableExperimental=*/WGPU_FALSE _wgpu_COMMA \ + /*.enableUnsafe=*/WGPU_FALSE _wgpu_COMMA \ + /*.enableTesting=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUEmscriptenSurfaceSourceCanvasHTMLSelector { + WGPUChainedStruct chain; + WGPUStringView selector; +} WGPUEmscriptenSurfaceSourceCanvasHTMLSelector WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_EMSCRIPTEN_SURFACE_SOURCE_CANVAS_HTML_SELECTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUEmscriptenSurfaceSourceCanvasHTMLSelector, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.selector=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUExtent2D { + uint32_t width; + uint32_t height; +} WGPUExtent2D WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_EXTENT_2D_INIT _wgpu_MAKE_INIT_STRUCT(WGPUExtent2D, { \ + /*.width=*/0 _wgpu_COMMA \ + /*.height=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUExtent3D { + uint32_t width; + uint32_t height; + uint32_t depthOrArrayLayers; +} WGPUExtent3D WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_EXTENT_3D_INIT _wgpu_MAKE_INIT_STRUCT(WGPUExtent3D, { \ + /*.width=*/0 _wgpu_COMMA \ + /*.height=*/1 _wgpu_COMMA \ + /*.depthOrArrayLayers=*/1 _wgpu_COMMA \ +}) + +// Can be chained in WGPUBindGroupEntry +typedef struct WGPUExternalTextureBindingEntry { + WGPUChainedStruct chain; + WGPUExternalTexture externalTexture; +} WGPUExternalTextureBindingEntry WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_EXTERNAL_TEXTURE_BINDING_ENTRY_INIT _wgpu_MAKE_INIT_STRUCT(WGPUExternalTextureBindingEntry, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ExternalTextureBindingEntry _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.externalTexture=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUBindGroupLayoutEntry +typedef struct WGPUExternalTextureBindingLayout { + WGPUChainedStruct chain; +} WGPUExternalTextureBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_EXTERNAL_TEXTURE_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUExternalTextureBindingLayout, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ExternalTextureBindingLayout _wgpu_COMMA \ + }) _wgpu_COMMA \ +}) + +typedef struct WGPUFuture { + uint64_t id; +} WGPUFuture WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_FUTURE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUFuture, { \ + /*.id=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUInstanceLimits { + WGPUChainedStruct * nextInChain; + size_t timedWaitAnyMaxCount; +} WGPUInstanceLimits WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_INSTANCE_LIMITS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUInstanceLimits, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.timedWaitAnyMaxCount=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUINTERNAL_HAVE_EMDAWNWEBGPU_HEADER { + WGPUBool unused; +} WGPUINTERNAL_HAVE_EMDAWNWEBGPU_HEADER WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_INTERNAL_HAVE_EMDAWNWEBGPU_HEADER_INIT _wgpu_MAKE_INIT_STRUCT(WGPUINTERNAL_HAVE_EMDAWNWEBGPU_HEADER, { \ + /*.unused=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUMemoryHeapInfo { + WGPUHeapProperty properties; + uint64_t size; +} WGPUMemoryHeapInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_MEMORY_HEAP_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUMemoryHeapInfo, { \ + /*.properties=*/WGPUHeapProperty_None _wgpu_COMMA \ + /*.size=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUMultisampleState { + WGPUChainedStruct * nextInChain; + uint32_t count; + uint32_t mask; + WGPUBool alphaToCoverageEnabled; +} WGPUMultisampleState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_MULTISAMPLE_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUMultisampleState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.count=*/1 _wgpu_COMMA \ + /*.mask=*/0xFFFFFFFF _wgpu_COMMA \ + /*.alphaToCoverageEnabled=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUOrigin2D { + uint32_t x; + uint32_t y; +} WGPUOrigin2D WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ORIGIN_2D_INIT _wgpu_MAKE_INIT_STRUCT(WGPUOrigin2D, { \ + /*.x=*/0 _wgpu_COMMA \ + /*.y=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUOrigin3D { + uint32_t x; + uint32_t y; + uint32_t z; +} WGPUOrigin3D WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ORIGIN_3D_INIT _wgpu_MAKE_INIT_STRUCT(WGPUOrigin3D, { \ + /*.x=*/0 _wgpu_COMMA \ + /*.y=*/0 _wgpu_COMMA \ + /*.z=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUPassTimestampWrites { + WGPUChainedStruct * nextInChain; + WGPUQuerySet querySet; + uint32_t beginningOfPassWriteIndex; + uint32_t endOfPassWriteIndex; +} WGPUPassTimestampWrites WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_PASS_TIMESTAMP_WRITES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPassTimestampWrites, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.querySet=*/NULL _wgpu_COMMA \ + /*.beginningOfPassWriteIndex=*/WGPU_QUERY_SET_INDEX_UNDEFINED _wgpu_COMMA \ + /*.endOfPassWriteIndex=*/WGPU_QUERY_SET_INDEX_UNDEFINED _wgpu_COMMA \ +}) + +// Can be chained in WGPUPipelineLayoutDescriptor +typedef struct WGPUPipelineLayoutResourceTable { + WGPUChainedStruct chain; + WGPUBool usesResourceTable; +} WGPUPipelineLayoutResourceTable WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_PIPELINE_LAYOUT_RESOURCE_TABLE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPipelineLayoutResourceTable, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_PipelineLayoutResourceTable _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.usesResourceTable=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUPipelineLayoutStorageAttachment { + WGPUChainedStruct * nextInChain; + uint64_t offset; + WGPUTextureFormat format; +} WGPUPipelineLayoutStorageAttachment WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_PIPELINE_LAYOUT_STORAGE_ATTACHMENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPipelineLayoutStorageAttachment, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUPrimitiveState { + WGPUChainedStruct * nextInChain; + WGPUPrimitiveTopology topology; + WGPUIndexFormat stripIndexFormat; + WGPUFrontFace frontFace; + WGPUCullMode cullMode; + WGPUBool unclippedDepth; +} WGPUPrimitiveState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_PRIMITIVE_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPrimitiveState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.topology=*/WGPUPrimitiveTopology_Undefined _wgpu_COMMA \ + /*.stripIndexFormat=*/WGPUIndexFormat_Undefined _wgpu_COMMA \ + /*.frontFace=*/WGPUFrontFace_Undefined _wgpu_COMMA \ + /*.cullMode=*/WGPUCullMode_Undefined _wgpu_COMMA \ + /*.unclippedDepth=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUQuerySetDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUQueryType type; + uint32_t count; +} WGPUQuerySetDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_QUERY_SET_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUQuerySetDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.type=*/_wgpu_ENUM_ZERO_INIT(WGPUQueryType) _wgpu_COMMA \ + /*.count=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUQueueDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUQueueDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_QUEUE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUQueueDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPURenderBundleDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPURenderBundleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_BUNDLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderBundleDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPURenderBundleEncoderDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + size_t colorFormatCount; + WGPUTextureFormat const * colorFormats; + WGPUTextureFormat depthStencilFormat; + uint32_t sampleCount; + WGPUBool depthReadOnly; + WGPUBool stencilReadOnly; +} WGPURenderBundleEncoderDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_BUNDLE_ENCODER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderBundleEncoderDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.colorFormatCount=*/0 _wgpu_COMMA \ + /*.colorFormats=*/NULL _wgpu_COMMA \ + /*.depthStencilFormat=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.sampleCount=*/1 _wgpu_COMMA \ + /*.depthReadOnly=*/WGPU_FALSE _wgpu_COMMA \ + /*.stencilReadOnly=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPURenderPassDepthStencilAttachment { + WGPUChainedStruct * nextInChain; + WGPUTextureView view; + WGPULoadOp depthLoadOp; + WGPUStoreOp depthStoreOp; + float depthClearValue; + WGPUBool depthReadOnly; + WGPULoadOp stencilLoadOp; + WGPUStoreOp stencilStoreOp; + uint32_t stencilClearValue; + WGPUBool stencilReadOnly; +} WGPURenderPassDepthStencilAttachment WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_DEPTH_STENCIL_ATTACHMENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassDepthStencilAttachment, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.view=*/NULL _wgpu_COMMA \ + /*.depthLoadOp=*/WGPULoadOp_Undefined _wgpu_COMMA \ + /*.depthStoreOp=*/WGPUStoreOp_Undefined _wgpu_COMMA \ + /*.depthClearValue=*/WGPU_DEPTH_CLEAR_VALUE_UNDEFINED _wgpu_COMMA \ + /*.depthReadOnly=*/WGPU_FALSE _wgpu_COMMA \ + /*.stencilLoadOp=*/WGPULoadOp_Undefined _wgpu_COMMA \ + /*.stencilStoreOp=*/WGPUStoreOp_Undefined _wgpu_COMMA \ + /*.stencilClearValue=*/0 _wgpu_COMMA \ + /*.stencilReadOnly=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPURenderPassDescriptor +typedef struct WGPURenderPassDescriptorExpandResolveRect { + WGPUChainedStruct chain; + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; +} WGPURenderPassDescriptorExpandResolveRect WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_DESCRIPTOR_EXPAND_RESOLVE_RECT_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassDescriptorExpandResolveRect, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_RenderPassDescriptorExpandResolveRect _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.x=*/0 _wgpu_COMMA \ + /*.y=*/0 _wgpu_COMMA \ + /*.width=*/0 _wgpu_COMMA \ + /*.height=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPURenderPassDescriptor +typedef struct WGPURenderPassDescriptorResolveRect { + WGPUChainedStruct chain; + uint32_t colorOffsetX; + uint32_t colorOffsetY; + uint32_t resolveOffsetX; + uint32_t resolveOffsetY; + uint32_t width; + uint32_t height; +} WGPURenderPassDescriptorResolveRect WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_DESCRIPTOR_RESOLVE_RECT_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassDescriptorResolveRect, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_RenderPassDescriptorResolveRect _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.colorOffsetX=*/0 _wgpu_COMMA \ + /*.colorOffsetY=*/0 _wgpu_COMMA \ + /*.resolveOffsetX=*/0 _wgpu_COMMA \ + /*.resolveOffsetY=*/0 _wgpu_COMMA \ + /*.width=*/0 _wgpu_COMMA \ + /*.height=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPURenderPassDescriptor +typedef struct WGPURenderPassMaxDrawCount { + WGPUChainedStruct chain; + uint64_t maxDrawCount; +} WGPURenderPassMaxDrawCount WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_MAX_DRAW_COUNT_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassMaxDrawCount, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_RenderPassMaxDrawCount _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.maxDrawCount=*/50000000 _wgpu_COMMA \ +}) + +// Can be chained in WGPURequestAdapterOptions +typedef struct WGPURequestAdapterWebGPUBackendOptions { + WGPUChainedStruct chain; +} WGPURequestAdapterWebGPUBackendOptions WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_REQUEST_ADAPTER_WEBGPU_BACKEND_OPTIONS_INIT _wgpu_MAKE_INIT_STRUCT(WGPURequestAdapterWebGPUBackendOptions, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_RequestAdapterWebGPUBackendOptions _wgpu_COMMA \ + }) _wgpu_COMMA \ +}) + +// Can be chained in WGPURequestAdapterOptions +typedef struct WGPURequestAdapterWebXROptions { + WGPUChainedStruct chain; + WGPUBool xrCompatible; +} WGPURequestAdapterWebXROptions WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_REQUEST_ADAPTER_WEBXR_OPTIONS_INIT _wgpu_MAKE_INIT_STRUCT(WGPURequestAdapterWebXROptions, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_RequestAdapterWebXROptions _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.xrCompatible=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUResourceTableDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + uint32_t size; +} WGPUResourceTableDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RESOURCE_TABLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUResourceTableDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.size=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPULimits +typedef struct WGPUResourceTableLimits { + WGPUChainedStruct chain; + uint32_t maxResourceTableSize; +} WGPUResourceTableLimits WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RESOURCE_TABLE_LIMITS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUResourceTableLimits, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ResourceTableLimits _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.maxResourceTableSize=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ +}) + +typedef struct WGPUSamplerBindingLayout { + WGPUChainedStruct * nextInChain; + WGPUSamplerBindingType type; +} WGPUSamplerBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SAMPLER_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSamplerBindingLayout, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.type=*/WGPUSamplerBindingType_Undefined _wgpu_COMMA \ +}) + +// Can be chained in WGPUShaderModuleDescriptor +typedef struct WGPUShaderModuleCompilationOptions { + WGPUChainedStruct chain; + WGPUBool strictMath; +} WGPUShaderModuleCompilationOptions WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHADER_MODULE_COMPILATION_OPTIONS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUShaderModuleCompilationOptions, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ShaderModuleCompilationOptions _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.strictMath=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUShaderModuleDescriptor +typedef struct WGPUShaderSourceSPIRV { + WGPUChainedStruct chain; + uint32_t codeSize; + uint32_t const * code; +} WGPUShaderSourceSPIRV WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHADER_SOURCE_SPIRV_INIT _wgpu_MAKE_INIT_STRUCT(WGPUShaderSourceSPIRV, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ShaderSourceSPIRV _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.codeSize=*/0 _wgpu_COMMA \ + /*.code=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUShaderModuleDescriptor +typedef struct WGPUShaderSourceWGSL { + WGPUChainedStruct chain; + WGPUStringView code; +} WGPUShaderSourceWGSL WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHADER_SOURCE_WGSL_INIT _wgpu_MAKE_INIT_STRUCT(WGPUShaderSourceWGSL, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_ShaderSourceWGSL _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.code=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSharedBufferMemoryBeginAccessDescriptor { + WGPUChainedStruct * nextInChain; + WGPUBool initialized; + size_t fenceCount; + WGPUSharedFence const * fences; + uint64_t const * signaledValues; +} WGPUSharedBufferMemoryBeginAccessDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_BUFFER_MEMORY_BEGIN_ACCESS_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedBufferMemoryBeginAccessDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.initialized=*/WGPU_FALSE _wgpu_COMMA \ + /*.fenceCount=*/0 _wgpu_COMMA \ + /*.fences=*/NULL _wgpu_COMMA \ + /*.signaledValues=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSharedBufferMemoryDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUSharedBufferMemoryDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_BUFFER_MEMORY_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedBufferMemoryDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSharedBufferMemoryEndAccessState { + WGPUChainedStruct * nextInChain; + WGPUBool initialized; + size_t fenceCount; + WGPUSharedFence const * fences; + uint64_t const * signaledValues; +} WGPUSharedBufferMemoryEndAccessState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_BUFFER_MEMORY_END_ACCESS_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedBufferMemoryEndAccessState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.initialized=*/WGPU_FALSE _wgpu_COMMA \ + /*.fenceCount=*/0 _wgpu_COMMA \ + /*.fences=*/NULL _wgpu_COMMA \ + /*.signaledValues=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSharedBufferMemoryProperties { + WGPUChainedStruct * nextInChain; + WGPUBufferUsage usage; + uint64_t size; +} WGPUSharedBufferMemoryProperties WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_BUFFER_MEMORY_PROPERTIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedBufferMemoryProperties, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.usage=*/WGPUBufferUsage_None _wgpu_COMMA \ + /*.size=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceDescriptor +typedef struct WGPUSharedFenceDXGISharedHandleDescriptor { + WGPUChainedStruct chain; + void * handle; +} WGPUSharedFenceDXGISharedHandleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_DXGI_SHARED_HANDLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceDXGISharedHandleDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceDXGISharedHandleDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceExportInfo +typedef struct WGPUSharedFenceDXGISharedHandleExportInfo { + WGPUChainedStruct chain; + void * handle; +} WGPUSharedFenceDXGISharedHandleExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_DXGI_SHARED_HANDLE_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceDXGISharedHandleExportInfo, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceDXGISharedHandleExportInfo _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceDescriptor +typedef struct WGPUSharedFenceEGLSyncDescriptor { + WGPUChainedStruct chain; + void * sync; +} WGPUSharedFenceEGLSyncDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_EGL_SYNC_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceEGLSyncDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceEGLSyncDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.sync=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceExportInfo +typedef struct WGPUSharedFenceEGLSyncExportInfo { + WGPUChainedStruct chain; + void * sync; +} WGPUSharedFenceEGLSyncExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_EGL_SYNC_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceEGLSyncExportInfo, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceEGLSyncExportInfo _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.sync=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceDescriptor +typedef struct WGPUSharedFenceMTLSharedEventDescriptor { + WGPUChainedStruct chain; + void * sharedEvent; +} WGPUSharedFenceMTLSharedEventDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_MTL_SHARED_EVENT_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceMTLSharedEventDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceMTLSharedEventDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.sharedEvent=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceExportInfo +typedef struct WGPUSharedFenceMTLSharedEventExportInfo { + WGPUChainedStruct chain; + void * sharedEvent; +} WGPUSharedFenceMTLSharedEventExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_MTL_SHARED_EVENT_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceMTLSharedEventExportInfo, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceMTLSharedEventExportInfo _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.sharedEvent=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceDescriptor +typedef struct WGPUSharedFenceSyncFDDescriptor { + WGPUChainedStruct chain; + int handle; +} WGPUSharedFenceSyncFDDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_SYNC_FD_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceSyncFDDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceSyncFDDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceExportInfo +typedef struct WGPUSharedFenceSyncFDExportInfo { + WGPUChainedStruct chain; + int handle; +} WGPUSharedFenceSyncFDExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_SYNC_FD_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceSyncFDExportInfo, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceSyncFDExportInfo _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceDescriptor +typedef struct WGPUSharedFenceVkSemaphoreOpaqueFDDescriptor { + WGPUChainedStruct chain; + int handle; +} WGPUSharedFenceVkSemaphoreOpaqueFDDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_VK_SEMAPHORE_OPAQUE_FD_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceVkSemaphoreOpaqueFDDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceVkSemaphoreOpaqueFDDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceExportInfo +typedef struct WGPUSharedFenceVkSemaphoreOpaqueFDExportInfo { + WGPUChainedStruct chain; + int handle; +} WGPUSharedFenceVkSemaphoreOpaqueFDExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_VK_SEMAPHORE_OPAQUE_FD_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceVkSemaphoreOpaqueFDExportInfo, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceVkSemaphoreOpaqueFDExportInfo _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceDescriptor +typedef struct WGPUSharedFenceVkSemaphoreZirconHandleDescriptor { + WGPUChainedStruct chain; + uint32_t handle; +} WGPUSharedFenceVkSemaphoreZirconHandleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_VK_SEMAPHORE_ZIRCON_HANDLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceVkSemaphoreZirconHandleDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceVkSemaphoreZirconHandleDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedFenceExportInfo +typedef struct WGPUSharedFenceVkSemaphoreZirconHandleExportInfo { + WGPUChainedStruct chain; + uint32_t handle; +} WGPUSharedFenceVkSemaphoreZirconHandleExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_VK_SEMAPHORE_ZIRCON_HANDLE_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceVkSemaphoreZirconHandleExportInfo, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedFenceVkSemaphoreZirconHandleExportInfo _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryAHardwareBufferDescriptor { + WGPUChainedStruct chain; + void * handle; + WGPUBool useExternalFormat; +} WGPUSharedTextureMemoryAHardwareBufferDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_A_HARDWARE_BUFFER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryAHardwareBufferDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryAHardwareBufferDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/NULL _wgpu_COMMA \ + /*.useExternalFormat=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryBeginAccessDescriptor +typedef struct WGPUSharedTextureMemoryD3D11BeginState { + WGPUChainedStruct chain; + WGPUBool requiresEndAccessFence; +} WGPUSharedTextureMemoryD3D11BeginState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_D3D11_BEGIN_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryD3D11BeginState, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryD3D11BeginState _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.requiresEndAccessFence=*/WGPU_TRUE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryBeginAccessDescriptor +typedef struct WGPUSharedTextureMemoryD3DSwapchainBeginState { + WGPUChainedStruct chain; + WGPUBool isSwapchain; +} WGPUSharedTextureMemoryD3DSwapchainBeginState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_D3D_SWAPCHAIN_BEGIN_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryD3DSwapchainBeginState, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryD3DSwapchainBeginState _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.isSwapchain=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUSharedTextureMemoryDmaBufPlane { + int fd; + uint64_t offset; + uint32_t stride; +} WGPUSharedTextureMemoryDmaBufPlane WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_DMA_BUF_PLANE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryDmaBufPlane, { \ + /*.fd=*/0 _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.stride=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryDXGISharedHandleDescriptor { + WGPUChainedStruct chain; + void * handle; + WGPUBool useKeyedMutex; +} WGPUSharedTextureMemoryDXGISharedHandleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_DXGI_SHARED_HANDLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryDXGISharedHandleDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryDXGISharedHandleDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.handle=*/NULL _wgpu_COMMA \ + /*.useKeyedMutex=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryEGLImageDescriptor { + WGPUChainedStruct chain; + void * image; +} WGPUSharedTextureMemoryEGLImageDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_EGL_IMAGE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryEGLImageDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryEGLImageDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.image=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryIOSurfaceDescriptor { + WGPUChainedStruct chain; + void * ioSurface; + WGPUBool allowStorageBinding; +} WGPUSharedTextureMemoryIOSurfaceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_IO_SURFACE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryIOSurfaceDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryIOSurfaceDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.ioSurface=*/NULL _wgpu_COMMA \ + /*.allowStorageBinding=*/WGPU_TRUE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryOpaqueFDDescriptor { + WGPUChainedStruct chain; + void const * vkImageCreateInfo; + int memoryFD; + uint32_t memoryTypeIndex; + uint64_t allocationSize; + WGPUBool dedicatedAllocation; +} WGPUSharedTextureMemoryOpaqueFDDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_OPAQUE_FD_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryOpaqueFDDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryOpaqueFDDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.vkImageCreateInfo=*/NULL _wgpu_COMMA \ + /*.memoryFD=*/0 _wgpu_COMMA \ + /*.memoryTypeIndex=*/0 _wgpu_COMMA \ + /*.allocationSize=*/0 _wgpu_COMMA \ + /*.dedicatedAllocation=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryVkDedicatedAllocationDescriptor { + WGPUChainedStruct chain; + WGPUBool dedicatedAllocation; +} WGPUSharedTextureMemoryVkDedicatedAllocationDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_VK_DEDICATED_ALLOCATION_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryVkDedicatedAllocationDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryVkDedicatedAllocationDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.dedicatedAllocation=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryBeginAccessDescriptor +typedef struct WGPUSharedTextureMemoryVkImageLayoutBeginState { + WGPUChainedStruct chain; + int32_t oldLayout; + int32_t newLayout; +} WGPUSharedTextureMemoryVkImageLayoutBeginState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_VK_IMAGE_LAYOUT_BEGIN_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryVkImageLayoutBeginState, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryVkImageLayoutBeginState _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.oldLayout=*/0 _wgpu_COMMA \ + /*.newLayout=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryEndAccessState +typedef struct WGPUSharedTextureMemoryVkImageLayoutEndState { + WGPUChainedStruct chain; + int32_t oldLayout; + int32_t newLayout; +} WGPUSharedTextureMemoryVkImageLayoutEndState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_VK_IMAGE_LAYOUT_END_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryVkImageLayoutEndState, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryVkImageLayoutEndState _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.oldLayout=*/0 _wgpu_COMMA \ + /*.newLayout=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryZirconHandleDescriptor { + WGPUChainedStruct chain; + uint32_t memoryFD; + uint64_t allocationSize; +} WGPUSharedTextureMemoryZirconHandleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_ZIRCON_HANDLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryZirconHandleDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryZirconHandleDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.memoryFD=*/0 _wgpu_COMMA \ + /*.allocationSize=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUBindGroupLayoutEntry +typedef struct WGPUStaticSamplerBindingLayout { + WGPUChainedStruct chain; + WGPUSampler sampler; + uint32_t sampledTextureBinding; +} WGPUStaticSamplerBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_STATIC_SAMPLER_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUStaticSamplerBindingLayout, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_StaticSamplerBindingLayout _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.sampler=*/NULL _wgpu_COMMA \ + /*.sampledTextureBinding=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ +}) + +typedef struct WGPUStencilFaceState { + WGPUCompareFunction compare; + WGPUStencilOperation failOp; + WGPUStencilOperation depthFailOp; + WGPUStencilOperation passOp; +} WGPUStencilFaceState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_STENCIL_FACE_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUStencilFaceState, { \ + /*.compare=*/WGPUCompareFunction_Undefined _wgpu_COMMA \ + /*.failOp=*/WGPUStencilOperation_Undefined _wgpu_COMMA \ + /*.depthFailOp=*/WGPUStencilOperation_Undefined _wgpu_COMMA \ + /*.passOp=*/WGPUStencilOperation_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUStorageTextureBindingLayout { + WGPUChainedStruct * nextInChain; + WGPUStorageTextureAccess access; + WGPUTextureFormat format; + WGPUTextureViewDimension viewDimension; +} WGPUStorageTextureBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_STORAGE_TEXTURE_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUStorageTextureBindingLayout, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.access=*/WGPUStorageTextureAccess_Undefined _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.viewDimension=*/WGPUTextureViewDimension_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUSubgroupMatrixConfig { + WGPUSubgroupMatrixComponentType componentType; + WGPUSubgroupMatrixComponentType resultComponentType; + uint32_t M; + uint32_t N; + uint32_t K; +} WGPUSubgroupMatrixConfig WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SUBGROUP_MATRIX_CONFIG_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSubgroupMatrixConfig, { \ + /*.componentType=*/_wgpu_ENUM_ZERO_INIT(WGPUSubgroupMatrixComponentType) _wgpu_COMMA \ + /*.resultComponentType=*/_wgpu_ENUM_ZERO_INIT(WGPUSubgroupMatrixComponentType) _wgpu_COMMA \ + /*.M=*/0 _wgpu_COMMA \ + /*.N=*/0 _wgpu_COMMA \ + /*.K=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUSupportedFeatures { + size_t featureCount; + WGPUFeatureName const * features; +} WGPUSupportedFeatures WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SUPPORTED_FEATURES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSupportedFeatures, { \ + /*.featureCount=*/0 _wgpu_COMMA \ + /*.features=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSupportedInstanceFeatures { + size_t featureCount; + WGPUInstanceFeatureName const * features; +} WGPUSupportedInstanceFeatures WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SUPPORTED_INSTANCE_FEATURES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSupportedInstanceFeatures, { \ + /*.featureCount=*/0 _wgpu_COMMA \ + /*.features=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSupportedWGSLLanguageFeatures { + size_t featureCount; + WGPUWGSLLanguageFeatureName const * features; +} WGPUSupportedWGSLLanguageFeatures WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SUPPORTED_WGSL_LANGUAGE_FEATURES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSupportedWGSLLanguageFeatures, { \ + /*.featureCount=*/0 _wgpu_COMMA \ + /*.features=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSurfaceCapabilities { + WGPUChainedStruct * nextInChain; + WGPUTextureUsage usages; + size_t formatCount; + WGPUTextureFormat const * formats; + size_t presentModeCount; + WGPUPresentMode const * presentModes; + size_t alphaModeCount; + WGPUCompositeAlphaMode const * alphaModes; +} WGPUSurfaceCapabilities WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_CAPABILITIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceCapabilities, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.usages=*/WGPUTextureUsage_None _wgpu_COMMA \ + /*.formatCount=*/0 _wgpu_COMMA \ + /*.formats=*/NULL _wgpu_COMMA \ + /*.presentModeCount=*/0 _wgpu_COMMA \ + /*.presentModes=*/NULL _wgpu_COMMA \ + /*.alphaModeCount=*/0 _wgpu_COMMA \ + /*.alphaModes=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceColorManagement { + WGPUChainedStruct chain; + WGPUPredefinedColorSpace colorSpace; + WGPUToneMappingMode toneMappingMode; +} WGPUSurfaceColorManagement WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_COLOR_MANAGEMENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceColorManagement, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceColorManagement _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.colorSpace=*/_wgpu_ENUM_ZERO_INIT(WGPUPredefinedColorSpace) _wgpu_COMMA \ + /*.toneMappingMode=*/_wgpu_ENUM_ZERO_INIT(WGPUToneMappingMode) _wgpu_COMMA \ +}) + +typedef struct WGPUSurfaceConfiguration { + WGPUChainedStruct * nextInChain; + WGPUDevice device; + WGPUTextureFormat format; + WGPUTextureUsage usage; + uint32_t width; + uint32_t height; + size_t viewFormatCount; + WGPUTextureFormat const * viewFormats; + WGPUCompositeAlphaMode alphaMode; + WGPUPresentMode presentMode; +} WGPUSurfaceConfiguration WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_CONFIGURATION_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceConfiguration, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.device=*/NULL _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.usage=*/WGPUTextureUsage_RenderAttachment _wgpu_COMMA \ + /*.width=*/0 _wgpu_COMMA \ + /*.height=*/0 _wgpu_COMMA \ + /*.viewFormatCount=*/0 _wgpu_COMMA \ + /*.viewFormats=*/NULL _wgpu_COMMA \ + /*.alphaMode=*/WGPUCompositeAlphaMode_Auto _wgpu_COMMA \ + /*.presentMode=*/WGPUPresentMode_Undefined _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceDescriptorFromWindowsCoreWindow { + WGPUChainedStruct chain; + void * coreWindow; +} WGPUSurfaceDescriptorFromWindowsCoreWindow WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_DESCRIPTOR_FROM_WINDOWS_CORE_WINDOW_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceDescriptorFromWindowsCoreWindow, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceDescriptorFromWindowsCoreWindow _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.coreWindow=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceDescriptorFromWindowsUWPSwapChainPanel { + WGPUChainedStruct chain; + void * swapChainPanel; +} WGPUSurfaceDescriptorFromWindowsUWPSwapChainPanel WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_DESCRIPTOR_FROM_WINDOWS_UWP_SWAP_CHAIN_PANEL_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceDescriptorFromWindowsUWPSwapChainPanel, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceDescriptorFromWindowsUWPSwapChainPanel _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.swapChainPanel=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceDescriptorFromWindowsWinUISwapChainPanel { + WGPUChainedStruct chain; + void * swapChainPanel; +} WGPUSurfaceDescriptorFromWindowsWinUISwapChainPanel WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_DESCRIPTOR_FROM_WINDOWS_WINUI_SWAP_CHAIN_PANEL_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceDescriptorFromWindowsWinUISwapChainPanel, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceDescriptorFromWindowsWinUISwapChainPanel _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.swapChainPanel=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceSourceAndroidNativeWindow { + WGPUChainedStruct chain; + void * window; +} WGPUSurfaceSourceAndroidNativeWindow WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_SOURCE_ANDROID_NATIVE_WINDOW_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceSourceAndroidNativeWindow, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceSourceAndroidNativeWindow _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.window=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceSourceMetalLayer { + WGPUChainedStruct chain; + void * layer; +} WGPUSurfaceSourceMetalLayer WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_SOURCE_METAL_LAYER_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceSourceMetalLayer, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceSourceMetalLayer _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.layer=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceSourceWaylandSurface { + WGPUChainedStruct chain; + void * display; + void * surface; +} WGPUSurfaceSourceWaylandSurface WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_SOURCE_WAYLAND_SURFACE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceSourceWaylandSurface, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceSourceWaylandSurface _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.display=*/NULL _wgpu_COMMA \ + /*.surface=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceSourceWindowsHWND { + WGPUChainedStruct chain; + void * hinstance; + void * hwnd; +} WGPUSurfaceSourceWindowsHWND WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_SOURCE_WINDOWS_HWND_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceSourceWindowsHWND, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceSourceWindowsHWND _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.hinstance=*/NULL _wgpu_COMMA \ + /*.hwnd=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceSourceXCBWindow { + WGPUChainedStruct chain; + void * connection; + uint32_t window; +} WGPUSurfaceSourceXCBWindow WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_SOURCE_XCB_WINDOW_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceSourceXCBWindow, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceSourceXCBWindow _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.connection=*/NULL _wgpu_COMMA \ + /*.window=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSurfaceDescriptor +typedef struct WGPUSurfaceSourceXlibWindow { + WGPUChainedStruct chain; + void * display; + uint64_t window; +} WGPUSurfaceSourceXlibWindow WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_SOURCE_XLIB_WINDOW_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceSourceXlibWindow, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SurfaceSourceXlibWindow _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.display=*/NULL _wgpu_COMMA \ + /*.window=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUSurfaceTexture { + WGPUChainedStruct * nextInChain; + WGPUTexture texture; + WGPUSurfaceGetCurrentTextureStatus status; +} WGPUSurfaceTexture WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_TEXTURE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceTexture, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.texture=*/NULL _wgpu_COMMA \ + /*.status=*/_wgpu_ENUM_ZERO_INIT(WGPUSurfaceGetCurrentTextureStatus) _wgpu_COMMA \ +}) + +// Can be chained in WGPUBindGroupEntry +typedef struct WGPUTexelBufferBindingEntry { + WGPUChainedStruct chain; + WGPUTexelBufferView texelBufferView; +} WGPUTexelBufferBindingEntry WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXEL_BUFFER_BINDING_ENTRY_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTexelBufferBindingEntry, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_TexelBufferBindingEntry _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.texelBufferView=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUBindGroupLayoutEntry +typedef struct WGPUTexelBufferBindingLayout { + WGPUChainedStruct chain; + WGPUTexelBufferAccess access; + WGPUTextureFormat format; +} WGPUTexelBufferBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXEL_BUFFER_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTexelBufferBindingLayout, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_TexelBufferBindingLayout _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.access=*/WGPUTexelBufferAccess_Undefined _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUTexelBufferViewDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUTextureFormat format; + uint64_t offset; + uint64_t size; +} WGPUTexelBufferViewDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXEL_BUFFER_VIEW_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTexelBufferViewDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.size=*/WGPU_WHOLE_SIZE _wgpu_COMMA \ +}) + +typedef struct WGPUTexelCopyBufferLayout { + uint64_t offset; + uint32_t bytesPerRow; + uint32_t rowsPerImage; +} WGPUTexelCopyBufferLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTexelCopyBufferLayout, { \ + /*.offset=*/0 _wgpu_COMMA \ + /*.bytesPerRow=*/WGPU_COPY_STRIDE_UNDEFINED _wgpu_COMMA \ + /*.rowsPerImage=*/WGPU_COPY_STRIDE_UNDEFINED _wgpu_COMMA \ +}) + +typedef struct WGPUTextureBindingLayout { + WGPUChainedStruct * nextInChain; + WGPUTextureSampleType sampleType; + WGPUTextureViewDimension viewDimension; + WGPUBool multisampled; +} WGPUTextureBindingLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXTURE_BINDING_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTextureBindingLayout, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.sampleType=*/WGPUTextureSampleType_Undefined _wgpu_COMMA \ + /*.viewDimension=*/WGPUTextureViewDimension_Undefined _wgpu_COMMA \ + /*.multisampled=*/WGPU_FALSE _wgpu_COMMA \ +}) + +// Can be chained in WGPUTextureDescriptor +typedef struct WGPUTextureBindingViewDimensionDescriptor { + WGPUChainedStruct chain; + WGPUTextureViewDimension textureBindingViewDimension; +} WGPUTextureBindingViewDimensionDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXTURE_BINDING_VIEW_DIMENSION_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTextureBindingViewDimensionDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_TextureBindingViewDimensionDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.textureBindingViewDimension=*/WGPUTextureViewDimension_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUTextureComponentSwizzle { + WGPUComponentSwizzle r; + WGPUComponentSwizzle g; + WGPUComponentSwizzle b; + WGPUComponentSwizzle a; +} WGPUTextureComponentSwizzle WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXTURE_COMPONENT_SWIZZLE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTextureComponentSwizzle, { \ + /*.r=*/WGPUComponentSwizzle_Undefined _wgpu_COMMA \ + /*.g=*/WGPUComponentSwizzle_Undefined _wgpu_COMMA \ + /*.b=*/WGPUComponentSwizzle_Undefined _wgpu_COMMA \ + /*.a=*/WGPUComponentSwizzle_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUVertexAttribute { + WGPUChainedStruct * nextInChain; + WGPUVertexFormat format; + uint64_t offset; + uint32_t shaderLocation; +} WGPUVertexAttribute WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_VERTEX_ATTRIBUTE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUVertexAttribute, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.format=*/_wgpu_ENUM_ZERO_INIT(WGPUVertexFormat) _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.shaderLocation=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUSamplerDescriptor +// Can be chained in WGPUTextureViewDescriptor +typedef struct WGPUYCbCrVkDescriptor { + WGPUChainedStruct chain; + uint32_t vkFormat; + uint32_t vkYCbCrModel; + uint32_t vkYCbCrRange; + uint32_t vkComponentSwizzleRed; + uint32_t vkComponentSwizzleGreen; + uint32_t vkComponentSwizzleBlue; + uint32_t vkComponentSwizzleAlpha; + uint32_t vkXChromaOffset; + uint32_t vkYChromaOffset; + WGPUFilterMode vkChromaFilter; + WGPUBool forceExplicitReconstruction; + uint64_t externalFormat; +} WGPUYCbCrVkDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_Y_CB_CR_VK_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUYCbCrVkDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_YCbCrVkDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.vkFormat=*/0 _wgpu_COMMA \ + /*.vkYCbCrModel=*/0 _wgpu_COMMA \ + /*.vkYCbCrRange=*/0 _wgpu_COMMA \ + /*.vkComponentSwizzleRed=*/0 _wgpu_COMMA \ + /*.vkComponentSwizzleGreen=*/0 _wgpu_COMMA \ + /*.vkComponentSwizzleBlue=*/0 _wgpu_COMMA \ + /*.vkComponentSwizzleAlpha=*/0 _wgpu_COMMA \ + /*.vkXChromaOffset=*/0 _wgpu_COMMA \ + /*.vkYChromaOffset=*/0 _wgpu_COMMA \ + /*.vkChromaFilter=*/WGPUFilterMode_Undefined _wgpu_COMMA \ + /*.forceExplicitReconstruction=*/WGPU_FALSE _wgpu_COMMA \ + /*.externalFormat=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPUAdapterInfo +typedef struct WGPUAdapterPropertiesMemoryHeaps { + WGPUChainedStruct chain; + size_t heapCount; + WGPUMemoryHeapInfo const * heapInfo; +} WGPUAdapterPropertiesMemoryHeaps WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ADAPTER_PROPERTIES_MEMORY_HEAPS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAdapterPropertiesMemoryHeaps, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_AdapterPropertiesMemoryHeaps _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.heapCount=*/0 _wgpu_COMMA \ + /*.heapInfo=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUAdapterInfo +typedef struct WGPUAdapterPropertiesSubgroupMatrixConfigs { + WGPUChainedStruct chain; + size_t configCount; + WGPUSubgroupMatrixConfig const * configs; +} WGPUAdapterPropertiesSubgroupMatrixConfigs WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ADAPTER_PROPERTIES_SUBGROUP_MATRIX_CONFIGS_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAdapterPropertiesSubgroupMatrixConfigs, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_AdapterPropertiesSubgroupMatrixConfigs _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.configCount=*/0 _wgpu_COMMA \ + /*.configs=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUAHardwareBufferProperties { + WGPUYCbCrVkDescriptor yCbCrInfo; +} WGPUAHardwareBufferProperties WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_A_HARDWARE_BUFFER_PROPERTIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAHardwareBufferProperties, { \ + /*.yCbCrInfo=*/WGPU_Y_CB_CR_VK_DESCRIPTOR_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUBindGroupEntry { + WGPUChainedStruct * nextInChain; + uint32_t binding; + WGPU_NULLABLE WGPUBuffer buffer; + uint64_t offset; + uint64_t size; + WGPU_NULLABLE WGPUSampler sampler; + WGPU_NULLABLE WGPUTextureView textureView; +} WGPUBindGroupEntry WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BIND_GROUP_ENTRY_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBindGroupEntry, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.binding=*/0 _wgpu_COMMA \ + /*.buffer=*/NULL _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.size=*/WGPU_WHOLE_SIZE _wgpu_COMMA \ + /*.sampler=*/NULL _wgpu_COMMA \ + /*.textureView=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUBindGroupLayoutEntry { + WGPUChainedStruct * nextInChain; + uint32_t binding; + WGPUShaderStage visibility; + uint32_t bindingArraySize; + WGPUBufferBindingLayout buffer; + WGPUSamplerBindingLayout sampler; + WGPUTextureBindingLayout texture; + WGPUStorageTextureBindingLayout storageTexture; +} WGPUBindGroupLayoutEntry WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBindGroupLayoutEntry, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.binding=*/0 _wgpu_COMMA \ + /*.visibility=*/WGPUShaderStage_None _wgpu_COMMA \ + /*.bindingArraySize=*/0 _wgpu_COMMA \ + /*.buffer=*/_wgpu_STRUCT_ZERO_INIT _wgpu_COMMA \ + /*.sampler=*/_wgpu_STRUCT_ZERO_INIT _wgpu_COMMA \ + /*.texture=*/_wgpu_STRUCT_ZERO_INIT _wgpu_COMMA \ + /*.storageTexture=*/_wgpu_STRUCT_ZERO_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUBlendState { + WGPUBlendComponent color; + WGPUBlendComponent alpha; +} WGPUBlendState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BLEND_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBlendState, { \ + /*.color=*/WGPU_BLEND_COMPONENT_INIT _wgpu_COMMA \ + /*.alpha=*/WGPU_BLEND_COMPONENT_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUBufferDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUBufferUsage usage; + uint64_t size; + WGPUBool mappedAtCreation; +} WGPUBufferDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BUFFER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBufferDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.usage=*/WGPUBufferUsage_None _wgpu_COMMA \ + /*.size=*/0 _wgpu_COMMA \ + /*.mappedAtCreation=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUCommandEncoderDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUCommandEncoderDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMMAND_ENCODER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCommandEncoderDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUCompilationMessage { + WGPUChainedStruct * nextInChain; + WGPUStringView message; + WGPUCompilationMessageType type; + uint64_t lineNum; + uint64_t linePos; + uint64_t offset; + uint64_t length; +} WGPUCompilationMessage WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPILATION_MESSAGE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCompilationMessage, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.message=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.type=*/_wgpu_ENUM_ZERO_INIT(WGPUCompilationMessageType) _wgpu_COMMA \ + /*.lineNum=*/0 _wgpu_COMMA \ + /*.linePos=*/0 _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.length=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUComputePassDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPU_NULLABLE WGPUPassTimestampWrites const * timestampWrites; +} WGPUComputePassDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPUTE_PASS_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUComputePassDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.timestampWrites=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUComputeState { + WGPUChainedStruct * nextInChain; + WGPUShaderModule module; + WGPUStringView entryPoint; + size_t constantCount; + WGPUConstantEntry const * constants; +} WGPUComputeState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPUTE_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUComputeState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.module=*/NULL _wgpu_COMMA \ + /*.entryPoint=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.constantCount=*/0 _wgpu_COMMA \ + /*.constants=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUDawnFormatCapabilities +typedef struct WGPUDawnDrmFormatCapabilities { + WGPUChainedStruct chain; + size_t propertiesCount; + WGPUDawnDrmFormatProperties const * properties; +} WGPUDawnDrmFormatCapabilities WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_DRM_FORMAT_CAPABILITIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnDrmFormatCapabilities, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_DawnDrmFormatCapabilities _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.propertiesCount=*/0 _wgpu_COMMA \ + /*.properties=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUDepthStencilState { + WGPUChainedStruct * nextInChain; + WGPUTextureFormat format; + WGPUOptionalBool depthWriteEnabled; + WGPUCompareFunction depthCompare; + WGPUStencilFaceState stencilFront; + WGPUStencilFaceState stencilBack; + uint32_t stencilReadMask; + uint32_t stencilWriteMask; + int32_t depthBias; + float depthBiasSlopeScale; + float depthBiasClamp; +} WGPUDepthStencilState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DEPTH_STENCIL_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDepthStencilState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.depthWriteEnabled=*/WGPUOptionalBool_Undefined _wgpu_COMMA \ + /*.depthCompare=*/WGPUCompareFunction_Undefined _wgpu_COMMA \ + /*.stencilFront=*/WGPU_STENCIL_FACE_STATE_INIT _wgpu_COMMA \ + /*.stencilBack=*/WGPU_STENCIL_FACE_STATE_INIT _wgpu_COMMA \ + /*.stencilReadMask=*/0xFFFFFFFF _wgpu_COMMA \ + /*.stencilWriteMask=*/0xFFFFFFFF _wgpu_COMMA \ + /*.depthBias=*/0 _wgpu_COMMA \ + /*.depthBiasSlopeScale=*/0.f _wgpu_COMMA \ + /*.depthBiasClamp=*/0.f _wgpu_COMMA \ +}) + +typedef struct WGPUExternalTextureDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUTextureView plane0; + WGPU_NULLABLE WGPUTextureView plane1; + WGPUOrigin2D cropOrigin; + WGPUExtent2D cropSize; + WGPUExtent2D apparentSize; + WGPUBool doYuvToRgbConversionOnly; + WGPU_NULLABLE float const * yuvToRgbConversionMatrix; + float const * srcTransferFunctionParameters; + float const * dstTransferFunctionParameters; + float const * gamutConversionMatrix; + WGPUBool mirrored; + WGPUExternalTextureRotation rotation; +} WGPUExternalTextureDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_EXTERNAL_TEXTURE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUExternalTextureDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.plane0=*/NULL _wgpu_COMMA \ + /*.plane1=*/NULL _wgpu_COMMA \ + /*.cropOrigin=*/WGPU_ORIGIN_2D_INIT _wgpu_COMMA \ + /*.cropSize=*/WGPU_EXTENT_2D_INIT _wgpu_COMMA \ + /*.apparentSize=*/WGPU_EXTENT_2D_INIT _wgpu_COMMA \ + /*.doYuvToRgbConversionOnly=*/WGPU_FALSE _wgpu_COMMA \ + /*.yuvToRgbConversionMatrix=*/NULL _wgpu_COMMA \ + /*.srcTransferFunctionParameters=*/NULL _wgpu_COMMA \ + /*.dstTransferFunctionParameters=*/NULL _wgpu_COMMA \ + /*.gamutConversionMatrix=*/NULL _wgpu_COMMA \ + /*.mirrored=*/WGPU_FALSE _wgpu_COMMA \ + /*.rotation=*/WGPUExternalTextureRotation_Rotate0Degrees _wgpu_COMMA \ +}) + +typedef struct WGPUFutureWaitInfo { + WGPUFuture future; + WGPUBool completed; +} WGPUFutureWaitInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_FUTURE_WAIT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUFutureWaitInfo, { \ + /*.future=*/WGPU_FUTURE_INIT _wgpu_COMMA \ + /*.completed=*/WGPU_FALSE _wgpu_COMMA \ +}) + +typedef struct WGPUImageCopyExternalTexture { + WGPUChainedStruct * nextInChain; + WGPUExternalTexture externalTexture; + WGPUOrigin3D origin; + WGPUExtent2D naturalSize; +} WGPUImageCopyExternalTexture WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_IMAGE_COPY_EXTERNAL_TEXTURE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUImageCopyExternalTexture, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.externalTexture=*/NULL _wgpu_COMMA \ + /*.origin=*/WGPU_ORIGIN_3D_INIT _wgpu_COMMA \ + /*.naturalSize=*/WGPU_EXTENT_2D_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUInstanceDescriptor { + WGPUChainedStruct * nextInChain; + size_t requiredFeatureCount; + WGPUInstanceFeatureName const * requiredFeatures; + WGPU_NULLABLE WGPUInstanceLimits const * requiredLimits; +} WGPUInstanceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_INSTANCE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUInstanceDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.requiredFeatureCount=*/0 _wgpu_COMMA \ + /*.requiredFeatures=*/NULL _wgpu_COMMA \ + /*.requiredLimits=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPULimits { + WGPUChainedStruct * nextInChain; + uint32_t maxTextureDimension1D; + uint32_t maxTextureDimension2D; + uint32_t maxTextureDimension3D; + uint32_t maxTextureArrayLayers; + uint32_t maxBindGroups; + uint32_t maxBindGroupsPlusVertexBuffers; + uint32_t maxBindingsPerBindGroup; + uint32_t maxDynamicUniformBuffersPerPipelineLayout; + uint32_t maxDynamicStorageBuffersPerPipelineLayout; + uint32_t maxSampledTexturesPerShaderStage; + uint32_t maxSamplersPerShaderStage; + uint32_t maxStorageBuffersPerShaderStage; + uint32_t maxStorageTexturesPerShaderStage; + uint32_t maxUniformBuffersPerShaderStage; + uint64_t maxUniformBufferBindingSize; + uint64_t maxStorageBufferBindingSize; + uint32_t minUniformBufferOffsetAlignment; + uint32_t minStorageBufferOffsetAlignment; + uint32_t maxVertexBuffers; + uint64_t maxBufferSize; + uint32_t maxVertexAttributes; + uint32_t maxVertexBufferArrayStride; + uint32_t maxInterStageShaderVariables; + uint32_t maxColorAttachments; + uint32_t maxColorAttachmentBytesPerSample; + uint32_t maxComputeWorkgroupStorageSize; + uint32_t maxComputeInvocationsPerWorkgroup; + uint32_t maxComputeWorkgroupSizeX; + uint32_t maxComputeWorkgroupSizeY; + uint32_t maxComputeWorkgroupSizeZ; + uint32_t maxComputeWorkgroupsPerDimension; + uint32_t maxImmediateSize; +} WGPULimits WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_LIMITS_INIT _wgpu_MAKE_INIT_STRUCT(WGPULimits, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.maxTextureDimension1D=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxTextureDimension2D=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxTextureDimension3D=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxTextureArrayLayers=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxBindGroups=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxBindGroupsPlusVertexBuffers=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxBindingsPerBindGroup=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxDynamicUniformBuffersPerPipelineLayout=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxDynamicStorageBuffersPerPipelineLayout=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxSampledTexturesPerShaderStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxSamplersPerShaderStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxStorageBuffersPerShaderStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxStorageTexturesPerShaderStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxUniformBuffersPerShaderStage=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxUniformBufferBindingSize=*/WGPU_LIMIT_U64_UNDEFINED _wgpu_COMMA \ + /*.maxStorageBufferBindingSize=*/WGPU_LIMIT_U64_UNDEFINED _wgpu_COMMA \ + /*.minUniformBufferOffsetAlignment=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.minStorageBufferOffsetAlignment=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxVertexBuffers=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxBufferSize=*/WGPU_LIMIT_U64_UNDEFINED _wgpu_COMMA \ + /*.maxVertexAttributes=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxVertexBufferArrayStride=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxInterStageShaderVariables=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxColorAttachments=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxColorAttachmentBytesPerSample=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxComputeWorkgroupStorageSize=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxComputeInvocationsPerWorkgroup=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxComputeWorkgroupSizeX=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxComputeWorkgroupSizeY=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxComputeWorkgroupSizeZ=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxComputeWorkgroupsPerDimension=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ + /*.maxImmediateSize=*/WGPU_LIMIT_U32_UNDEFINED _wgpu_COMMA \ +}) + +// Can be chained in WGPUPipelineLayoutDescriptor +typedef struct WGPUPipelineLayoutPixelLocalStorage { + WGPUChainedStruct chain; + uint64_t totalPixelLocalStorageSize; + size_t storageAttachmentCount; + WGPUPipelineLayoutStorageAttachment const * storageAttachments; +} WGPUPipelineLayoutPixelLocalStorage WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_PIPELINE_LAYOUT_PIXEL_LOCAL_STORAGE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPipelineLayoutPixelLocalStorage, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_PipelineLayoutPixelLocalStorage _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.totalPixelLocalStorageSize=*/0 _wgpu_COMMA \ + /*.storageAttachmentCount=*/0 _wgpu_COMMA \ + /*.storageAttachments=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPURenderPassColorAttachment { + WGPUChainedStruct * nextInChain; + WGPU_NULLABLE WGPUTextureView view; + uint32_t depthSlice; + WGPU_NULLABLE WGPUTextureView resolveTarget; + WGPULoadOp loadOp; + WGPUStoreOp storeOp; + WGPUColor clearValue; +} WGPURenderPassColorAttachment WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_COLOR_ATTACHMENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassColorAttachment, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.view=*/NULL _wgpu_COMMA \ + /*.depthSlice=*/WGPU_DEPTH_SLICE_UNDEFINED _wgpu_COMMA \ + /*.resolveTarget=*/NULL _wgpu_COMMA \ + /*.loadOp=*/WGPULoadOp_Undefined _wgpu_COMMA \ + /*.storeOp=*/WGPUStoreOp_Undefined _wgpu_COMMA \ + /*.clearValue=*/WGPU_COLOR_INIT _wgpu_COMMA \ +}) + +typedef struct WGPURenderPassStorageAttachment { + WGPUChainedStruct * nextInChain; + uint64_t offset; + WGPUTextureView storage; + WGPULoadOp loadOp; + WGPUStoreOp storeOp; + WGPUColor clearValue; +} WGPURenderPassStorageAttachment WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_STORAGE_ATTACHMENT_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassStorageAttachment, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.offset=*/0 _wgpu_COMMA \ + /*.storage=*/NULL _wgpu_COMMA \ + /*.loadOp=*/WGPULoadOp_Undefined _wgpu_COMMA \ + /*.storeOp=*/WGPUStoreOp_Undefined _wgpu_COMMA \ + /*.clearValue=*/WGPU_COLOR_INIT _wgpu_COMMA \ +}) + +typedef struct WGPURequestAdapterOptions { + WGPUChainedStruct * nextInChain; + WGPUFeatureLevel featureLevel; + WGPUPowerPreference powerPreference; + WGPUBool forceFallbackAdapter; + WGPUBackendType backendType; + WGPU_NULLABLE WGPUSurface compatibleSurface; +} WGPURequestAdapterOptions WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_REQUEST_ADAPTER_OPTIONS_INIT _wgpu_MAKE_INIT_STRUCT(WGPURequestAdapterOptions, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.featureLevel=*/WGPUFeatureLevel_Undefined _wgpu_COMMA \ + /*.powerPreference=*/WGPUPowerPreference_Undefined _wgpu_COMMA \ + /*.forceFallbackAdapter=*/WGPU_FALSE _wgpu_COMMA \ + /*.backendType=*/WGPUBackendType_Undefined _wgpu_COMMA \ + /*.compatibleSurface=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSamplerDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUAddressMode addressModeU; + WGPUAddressMode addressModeV; + WGPUAddressMode addressModeW; + WGPUFilterMode magFilter; + WGPUFilterMode minFilter; + WGPUMipmapFilterMode mipmapFilter; + float lodMinClamp; + float lodMaxClamp; + WGPUCompareFunction compare; + uint16_t maxAnisotropy; +} WGPUSamplerDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SAMPLER_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSamplerDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.addressModeU=*/WGPUAddressMode_Undefined _wgpu_COMMA \ + /*.addressModeV=*/WGPUAddressMode_Undefined _wgpu_COMMA \ + /*.addressModeW=*/WGPUAddressMode_Undefined _wgpu_COMMA \ + /*.magFilter=*/WGPUFilterMode_Undefined _wgpu_COMMA \ + /*.minFilter=*/WGPUFilterMode_Undefined _wgpu_COMMA \ + /*.mipmapFilter=*/WGPUMipmapFilterMode_Undefined _wgpu_COMMA \ + /*.lodMinClamp=*/0.f _wgpu_COMMA \ + /*.lodMaxClamp=*/32.f _wgpu_COMMA \ + /*.compare=*/WGPUCompareFunction_Undefined _wgpu_COMMA \ + /*.maxAnisotropy=*/1 _wgpu_COMMA \ +}) + +typedef struct WGPUShaderModuleDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUShaderModuleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHADER_MODULE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUShaderModuleDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSharedFenceDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUSharedFenceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSharedFenceExportInfo { + WGPUChainedStruct * nextInChain; + WGPUSharedFenceType type; +} WGPUSharedFenceExportInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_FENCE_EXPORT_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedFenceExportInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.type=*/_wgpu_ENUM_ZERO_INIT(WGPUSharedFenceType) _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryProperties +typedef struct WGPUSharedTextureMemoryAHardwareBufferProperties { + WGPUChainedStruct chain; + WGPUYCbCrVkDescriptor yCbCrInfo; +} WGPUSharedTextureMemoryAHardwareBufferProperties WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_A_HARDWARE_BUFFER_PROPERTIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryAHardwareBufferProperties, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryAHardwareBufferProperties _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.yCbCrInfo=*/WGPU_Y_CB_CR_VK_DESCRIPTOR_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSharedTextureMemoryBeginAccessDescriptor { + WGPUChainedStruct * nextInChain; + WGPUBool concurrentRead; + WGPUBool initialized; + size_t fenceCount; + WGPUSharedFence const * fences; + uint64_t const * signaledValues; +} WGPUSharedTextureMemoryBeginAccessDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_BEGIN_ACCESS_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryBeginAccessDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.concurrentRead=*/WGPU_FALSE _wgpu_COMMA \ + /*.initialized=*/WGPU_FALSE _wgpu_COMMA \ + /*.fenceCount=*/0 _wgpu_COMMA \ + /*.fences=*/NULL _wgpu_COMMA \ + /*.signaledValues=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryDescriptor +typedef struct WGPUSharedTextureMemoryDmaBufDescriptor { + WGPUChainedStruct chain; + WGPUExtent3D size; + uint32_t drmFormat; + uint64_t drmModifier; + size_t planeCount; + WGPUSharedTextureMemoryDmaBufPlane const * planes; +} WGPUSharedTextureMemoryDmaBufDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_DMA_BUF_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryDmaBufDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryDmaBufDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.size=*/WGPU_EXTENT_3D_INIT _wgpu_COMMA \ + /*.drmFormat=*/0 _wgpu_COMMA \ + /*.drmModifier=*/0 _wgpu_COMMA \ + /*.planeCount=*/0 _wgpu_COMMA \ + /*.planes=*/NULL _wgpu_COMMA \ +}) + +// Can be chained in WGPUSharedTextureMemoryEndAccessState +typedef struct WGPUSharedTextureMemoryMetalEndAccessState { + WGPUChainedStruct chain; + WGPUFuture commandsScheduledFuture; +} WGPUSharedTextureMemoryMetalEndAccessState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_METAL_END_ACCESS_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryMetalEndAccessState, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_SharedTextureMemoryMetalEndAccessState _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.commandsScheduledFuture=*/WGPU_FUTURE_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSurfaceDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUSurfaceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SURFACE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSurfaceDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUTexelCopyBufferInfo { + WGPUTexelCopyBufferLayout layout; + WGPUBuffer buffer; +} WGPUTexelCopyBufferInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXEL_COPY_BUFFER_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTexelCopyBufferInfo, { \ + /*.layout=*/WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT _wgpu_COMMA \ + /*.buffer=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUTexelCopyTextureInfo { + WGPUTexture texture; + uint32_t mipLevel; + WGPUOrigin3D origin; + WGPUTextureAspect aspect; +} WGPUTexelCopyTextureInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXEL_COPY_TEXTURE_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTexelCopyTextureInfo, { \ + /*.texture=*/NULL _wgpu_COMMA \ + /*.mipLevel=*/0 _wgpu_COMMA \ + /*.origin=*/WGPU_ORIGIN_3D_INIT _wgpu_COMMA \ + /*.aspect=*/WGPUTextureAspect_Undefined _wgpu_COMMA \ +}) + +// Can be chained in WGPUTextureViewDescriptor +typedef struct WGPUTextureComponentSwizzleDescriptor { + WGPUChainedStruct chain; + WGPUTextureComponentSwizzle swizzle; +} WGPUTextureComponentSwizzleDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXTURE_COMPONENT_SWIZZLE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTextureComponentSwizzleDescriptor, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_TextureComponentSwizzleDescriptor _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.swizzle=*/WGPU_TEXTURE_COMPONENT_SWIZZLE_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUTextureDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUTextureUsage usage; + WGPUTextureDimension dimension; + WGPUExtent3D size; + WGPUTextureFormat format; + uint32_t mipLevelCount; + uint32_t sampleCount; + size_t viewFormatCount; + WGPUTextureFormat const * viewFormats; +} WGPUTextureDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXTURE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTextureDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.usage=*/WGPUTextureUsage_None _wgpu_COMMA \ + /*.dimension=*/WGPUTextureDimension_Undefined _wgpu_COMMA \ + /*.size=*/WGPU_EXTENT_3D_INIT _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.mipLevelCount=*/1 _wgpu_COMMA \ + /*.sampleCount=*/1 _wgpu_COMMA \ + /*.viewFormatCount=*/0 _wgpu_COMMA \ + /*.viewFormats=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUVertexBufferLayout { + WGPUChainedStruct * nextInChain; + WGPUVertexStepMode stepMode; + uint64_t arrayStride; + size_t attributeCount; + WGPUVertexAttribute const * attributes; +} WGPUVertexBufferLayout WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_VERTEX_BUFFER_LAYOUT_INIT _wgpu_MAKE_INIT_STRUCT(WGPUVertexBufferLayout, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.stepMode=*/WGPUVertexStepMode_Undefined _wgpu_COMMA \ + /*.arrayStride=*/0 _wgpu_COMMA \ + /*.attributeCount=*/0 _wgpu_COMMA \ + /*.attributes=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUAdapterInfo { + WGPUChainedStruct * nextInChain; + WGPUStringView vendor; + WGPUStringView architecture; + WGPUStringView device; + WGPUStringView description; + WGPUBackendType backendType; + WGPUAdapterType adapterType; + uint32_t vendorID; + uint32_t deviceID; + uint32_t subgroupMinSize; + uint32_t subgroupMaxSize; +} WGPUAdapterInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_ADAPTER_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUAdapterInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.vendor=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.architecture=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.device=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.description=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.backendType=*/WGPUBackendType_Undefined _wgpu_COMMA \ + /*.adapterType=*/_wgpu_ENUM_ZERO_INIT(WGPUAdapterType) _wgpu_COMMA \ + /*.vendorID=*/0 _wgpu_COMMA \ + /*.deviceID=*/0 _wgpu_COMMA \ + /*.subgroupMinSize=*/0 _wgpu_COMMA \ + /*.subgroupMaxSize=*/0 _wgpu_COMMA \ +}) + +typedef struct WGPUBindGroupDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUBindGroupLayout layout; + size_t entryCount; + WGPUBindGroupEntry const * entries; +} WGPUBindGroupDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BIND_GROUP_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBindGroupDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.layout=*/NULL _wgpu_COMMA \ + /*.entryCount=*/0 _wgpu_COMMA \ + /*.entries=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUBindGroupLayoutDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + size_t entryCount; + WGPUBindGroupLayoutEntry const * entries; +} WGPUBindGroupLayoutDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUBindGroupLayoutDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.entryCount=*/0 _wgpu_COMMA \ + /*.entries=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUColorTargetState { + WGPUChainedStruct * nextInChain; + WGPUTextureFormat format; + WGPU_NULLABLE WGPUBlendState const * blend; + WGPUColorWriteMask writeMask; +} WGPUColorTargetState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COLOR_TARGET_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUColorTargetState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.blend=*/NULL _wgpu_COMMA \ + /*.writeMask=*/WGPUColorWriteMask_All _wgpu_COMMA \ +}) + +typedef struct WGPUCompilationInfo { + WGPUChainedStruct * nextInChain; + size_t messageCount; + WGPUCompilationMessage const * messages; +} WGPUCompilationInfo WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPILATION_INFO_INIT _wgpu_MAKE_INIT_STRUCT(WGPUCompilationInfo, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.messageCount=*/0 _wgpu_COMMA \ + /*.messages=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUComputePipelineDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPU_NULLABLE WGPUPipelineLayout layout; + WGPUComputeState compute; +} WGPUComputePipelineDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_COMPUTE_PIPELINE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUComputePipelineDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.layout=*/NULL _wgpu_COMMA \ + /*.compute=*/WGPU_COMPUTE_STATE_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUDawnFormatCapabilities { + WGPUChainedStruct * nextInChain; +} WGPUDawnFormatCapabilities WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DAWN_FORMAT_CAPABILITIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDawnFormatCapabilities, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUDeviceDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + size_t requiredFeatureCount; + WGPUFeatureName const * requiredFeatures; + WGPU_NULLABLE WGPULimits const * requiredLimits; + WGPUQueueDescriptor defaultQueue; + WGPUDeviceLostCallbackInfo deviceLostCallbackInfo; + WGPUUncapturedErrorCallbackInfo uncapturedErrorCallbackInfo; +} WGPUDeviceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_DEVICE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUDeviceDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.requiredFeatureCount=*/0 _wgpu_COMMA \ + /*.requiredFeatures=*/NULL _wgpu_COMMA \ + /*.requiredLimits=*/NULL _wgpu_COMMA \ + /*.defaultQueue=*/WGPU_QUEUE_DESCRIPTOR_INIT _wgpu_COMMA \ + /*.deviceLostCallbackInfo=*/WGPU_DEVICE_LOST_CALLBACK_INFO_INIT _wgpu_COMMA \ + /*.uncapturedErrorCallbackInfo=*/WGPU_UNCAPTURED_ERROR_CALLBACK_INFO_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUPipelineLayoutDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + size_t bindGroupLayoutCount; + WGPUBindGroupLayout const * bindGroupLayouts; + uint32_t immediateSize; +} WGPUPipelineLayoutDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_PIPELINE_LAYOUT_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUPipelineLayoutDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.bindGroupLayoutCount=*/0 _wgpu_COMMA \ + /*.bindGroupLayouts=*/NULL _wgpu_COMMA \ + /*.immediateSize=*/0 _wgpu_COMMA \ +}) + +// Can be chained in WGPURenderPassDescriptor +typedef struct WGPURenderPassPixelLocalStorage { + WGPUChainedStruct chain; + uint64_t totalPixelLocalStorageSize; + size_t storageAttachmentCount; + WGPURenderPassStorageAttachment const * storageAttachments; +} WGPURenderPassPixelLocalStorage WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_PIXEL_LOCAL_STORAGE_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassPixelLocalStorage, { \ + /*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \ + /*.next=*/NULL _wgpu_COMMA \ + /*.sType=*/WGPUSType_RenderPassPixelLocalStorage _wgpu_COMMA \ + }) _wgpu_COMMA \ + /*.totalPixelLocalStorageSize=*/0 _wgpu_COMMA \ + /*.storageAttachmentCount=*/0 _wgpu_COMMA \ + /*.storageAttachments=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSharedTextureMemoryDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; +} WGPUSharedTextureMemoryDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ +}) + +typedef struct WGPUSharedTextureMemoryEndAccessState { + WGPUChainedStruct * nextInChain; + WGPUBool initialized; + size_t fenceCount; + WGPUSharedFence const * fences; + uint64_t const * signaledValues; +} WGPUSharedTextureMemoryEndAccessState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_END_ACCESS_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryEndAccessState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.initialized=*/WGPU_FALSE _wgpu_COMMA \ + /*.fenceCount=*/0 _wgpu_COMMA \ + /*.fences=*/NULL _wgpu_COMMA \ + /*.signaledValues=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUSharedTextureMemoryProperties { + WGPUChainedStruct * nextInChain; + WGPUTextureUsage usage; + WGPUExtent3D size; + WGPUTextureFormat format; +} WGPUSharedTextureMemoryProperties WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_SHARED_TEXTURE_MEMORY_PROPERTIES_INIT _wgpu_MAKE_INIT_STRUCT(WGPUSharedTextureMemoryProperties, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.usage=*/WGPUTextureUsage_None _wgpu_COMMA \ + /*.size=*/WGPU_EXTENT_3D_INIT _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ +}) + +typedef struct WGPUTextureViewDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPUTextureFormat format; + WGPUTextureViewDimension dimension; + uint32_t baseMipLevel; + uint32_t mipLevelCount; + uint32_t baseArrayLayer; + uint32_t arrayLayerCount; + WGPUTextureAspect aspect; + WGPUTextureUsage usage; +} WGPUTextureViewDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPUTextureViewDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.format=*/WGPUTextureFormat_Undefined _wgpu_COMMA \ + /*.dimension=*/WGPUTextureViewDimension_Undefined _wgpu_COMMA \ + /*.baseMipLevel=*/0 _wgpu_COMMA \ + /*.mipLevelCount=*/WGPU_MIP_LEVEL_COUNT_UNDEFINED _wgpu_COMMA \ + /*.baseArrayLayer=*/0 _wgpu_COMMA \ + /*.arrayLayerCount=*/WGPU_ARRAY_LAYER_COUNT_UNDEFINED _wgpu_COMMA \ + /*.aspect=*/WGPUTextureAspect_Undefined _wgpu_COMMA \ + /*.usage=*/WGPUTextureUsage_None _wgpu_COMMA \ +}) + +typedef struct WGPUVertexState { + WGPUChainedStruct * nextInChain; + WGPUShaderModule module; + WGPUStringView entryPoint; + size_t constantCount; + WGPUConstantEntry const * constants; + size_t bufferCount; + WGPUVertexBufferLayout const * buffers; +} WGPUVertexState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_VERTEX_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUVertexState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.module=*/NULL _wgpu_COMMA \ + /*.entryPoint=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.constantCount=*/0 _wgpu_COMMA \ + /*.constants=*/NULL _wgpu_COMMA \ + /*.bufferCount=*/0 _wgpu_COMMA \ + /*.buffers=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPUFragmentState { + WGPUChainedStruct * nextInChain; + WGPUShaderModule module; + WGPUStringView entryPoint; + size_t constantCount; + WGPUConstantEntry const * constants; + size_t targetCount; + WGPUColorTargetState const * targets; +} WGPUFragmentState WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_FRAGMENT_STATE_INIT _wgpu_MAKE_INIT_STRUCT(WGPUFragmentState, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.module=*/NULL _wgpu_COMMA \ + /*.entryPoint=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.constantCount=*/0 _wgpu_COMMA \ + /*.constants=*/NULL _wgpu_COMMA \ + /*.targetCount=*/0 _wgpu_COMMA \ + /*.targets=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPURenderPassDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + size_t colorAttachmentCount; + WGPURenderPassColorAttachment const * colorAttachments; + WGPU_NULLABLE WGPURenderPassDepthStencilAttachment const * depthStencilAttachment; + WGPU_NULLABLE WGPUQuerySet occlusionQuerySet; + WGPU_NULLABLE WGPUPassTimestampWrites const * timestampWrites; +} WGPURenderPassDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PASS_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPassDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.colorAttachmentCount=*/0 _wgpu_COMMA \ + /*.colorAttachments=*/NULL _wgpu_COMMA \ + /*.depthStencilAttachment=*/NULL _wgpu_COMMA \ + /*.occlusionQuerySet=*/NULL _wgpu_COMMA \ + /*.timestampWrites=*/NULL _wgpu_COMMA \ +}) + +typedef struct WGPURenderPipelineDescriptor { + WGPUChainedStruct * nextInChain; + WGPUStringView label; + WGPU_NULLABLE WGPUPipelineLayout layout; + WGPUVertexState vertex; + WGPUPrimitiveState primitive; + WGPU_NULLABLE WGPUDepthStencilState const * depthStencil; + WGPUMultisampleState multisample; + WGPU_NULLABLE WGPUFragmentState const * fragment; +} WGPURenderPipelineDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT _wgpu_MAKE_INIT_STRUCT(WGPURenderPipelineDescriptor, { \ + /*.nextInChain=*/NULL _wgpu_COMMA \ + /*.label=*/WGPU_STRING_VIEW_INIT _wgpu_COMMA \ + /*.layout=*/NULL _wgpu_COMMA \ + /*.vertex=*/WGPU_VERTEX_STATE_INIT _wgpu_COMMA \ + /*.primitive=*/WGPU_PRIMITIVE_STATE_INIT _wgpu_COMMA \ + /*.depthStencil=*/NULL _wgpu_COMMA \ + /*.multisample=*/WGPU_MULTISAMPLE_STATE_INIT _wgpu_COMMA \ + /*.fragment=*/NULL _wgpu_COMMA \ +}) + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(WGPU_SKIP_PROCS) +// TODO(374150686): Remove these Emscripten specific declarations from the +// header once they are fully deprecated. +WGPU_EXPORT WGPUDevice emscripten_webgpu_get_device(void); +// Global procs +typedef WGPUInstance (*WGPUProcCreateInstance)(WGPU_NULLABLE WGPUInstanceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcGetInstanceFeatures)(WGPUSupportedInstanceFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcGetInstanceLimits)(WGPUInstanceLimits * limits) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBool (*WGPUProcHasInstanceFeature)(WGPUInstanceFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUStringView procName) WGPU_FUNCTION_ATTRIBUTE; + + +// Procs of Adapter +typedef WGPUDevice (*WGPUProcAdapterCreateDevice)(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcAdapterGetFeatures)(WGPUAdapter adapter, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcAdapterGetFormatCapabilities)(WGPUAdapter adapter, WGPUTextureFormat format, WGPUDawnFormatCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcAdapterGetInfo)(WGPUAdapter adapter, WGPUAdapterInfo * info) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUInstance (*WGPUProcAdapterGetInstance)(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcAdapterGetLimits)(WGPUAdapter adapter, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBool (*WGPUProcAdapterHasFeature)(WGPUAdapter adapter, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcAdapterRequestDevice)(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor, WGPURequestDeviceCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcAdapterAddRef)(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcAdapterRelease)(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of AdapterInfo +typedef void (*WGPUProcAdapterInfoFreeMembers)(WGPUAdapterInfo adapterInfo) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of AdapterPropertiesMemoryHeaps +typedef void (*WGPUProcAdapterPropertiesMemoryHeapsFreeMembers)(WGPUAdapterPropertiesMemoryHeaps adapterPropertiesMemoryHeaps) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of AdapterPropertiesSubgroupMatrixConfigs +typedef void (*WGPUProcAdapterPropertiesSubgroupMatrixConfigsFreeMembers)(WGPUAdapterPropertiesSubgroupMatrixConfigs adapterPropertiesSubgroupMatrixConfigs) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of BindGroup +typedef void (*WGPUProcBindGroupSetLabel)(WGPUBindGroup bindGroup, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBindGroupAddRef)(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBindGroupRelease)(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of BindGroupLayout +typedef void (*WGPUProcBindGroupLayoutSetLabel)(WGPUBindGroupLayout bindGroupLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBindGroupLayoutAddRef)(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBindGroupLayoutRelease)(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Buffer +typedef WGPUTexelBufferView (*WGPUProcBufferCreateTexelView)(WGPUBuffer buffer, WGPUTexelBufferViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBufferDestroy)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +typedef void const * (*WGPUProcBufferGetConstMappedRange)(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void * (*WGPUProcBufferGetMappedRange)(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBufferMapState (*WGPUProcBufferGetMapState)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +typedef uint64_t (*WGPUProcBufferGetSize)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBufferUsage (*WGPUProcBufferGetUsage)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcBufferMapAsync)(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcBufferReadMappedRange)(WGPUBuffer buffer, size_t offset, void * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBufferSetLabel)(WGPUBuffer buffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBufferUnmap)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcBufferWriteMappedRange)(WGPUBuffer buffer, size_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBufferAddRef)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcBufferRelease)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of CommandBuffer +typedef void (*WGPUProcCommandBufferSetLabel)(WGPUCommandBuffer commandBuffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandBufferAddRef)(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandBufferRelease)(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of CommandEncoder +typedef WGPUComputePassEncoder (*WGPUProcCommandEncoderBeginComputePass)(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUComputePassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPURenderPassEncoder (*WGPUProcCommandEncoderBeginRenderPass)(WGPUCommandEncoder commandEncoder, WGPURenderPassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderClearBuffer)(WGPUCommandEncoder commandEncoder, WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderCopyBufferToBuffer)(WGPUCommandEncoder commandEncoder, WGPUBuffer source, uint64_t sourceOffset, WGPUBuffer destination, uint64_t destinationOffset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderCopyBufferToTexture)(WGPUCommandEncoder commandEncoder, WGPUTexelCopyBufferInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderCopyTextureToBuffer)(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyBufferInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderCopyTextureToTexture)(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUCommandBuffer (*WGPUProcCommandEncoderFinish)(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUCommandBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderInjectValidationError)(WGPUCommandEncoder commandEncoder, WGPUStringView message) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderInsertDebugMarker)(WGPUCommandEncoder commandEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderPopDebugGroup)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderPushDebugGroup)(WGPUCommandEncoder commandEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderResolveQuerySet)(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t firstQuery, uint32_t queryCount, WGPUBuffer destination, uint64_t destinationOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderSetLabel)(WGPUCommandEncoder commandEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderSetResourceTable)(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUResourceTable table) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderWriteBuffer)(WGPUCommandEncoder commandEncoder, WGPUBuffer buffer, uint64_t bufferOffset, uint8_t const * data, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderWriteTimestamp)(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderAddRef)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcCommandEncoderRelease)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of ComputePassEncoder +typedef void (*WGPUProcComputePassEncoderDispatchWorkgroups)(WGPUComputePassEncoder computePassEncoder, uint32_t workgroupCountX, uint32_t workgroupCountY, uint32_t workgroupCountZ) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderDispatchWorkgroupsIndirect)(WGPUComputePassEncoder computePassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderEnd)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderInsertDebugMarker)(WGPUComputePassEncoder computePassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderPopDebugGroup)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderPushDebugGroup)(WGPUComputePassEncoder computePassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderSetBindGroup)(WGPUComputePassEncoder computePassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderSetImmediates)(WGPUComputePassEncoder computePassEncoder, uint32_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderSetLabel)(WGPUComputePassEncoder computePassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderSetPipeline)(WGPUComputePassEncoder computePassEncoder, WGPUComputePipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderWriteTimestamp)(WGPUComputePassEncoder computePassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderAddRef)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePassEncoderRelease)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of ComputePipeline +typedef WGPUBindGroupLayout (*WGPUProcComputePipelineGetBindGroupLayout)(WGPUComputePipeline computePipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePipelineSetLabel)(WGPUComputePipeline computePipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePipelineAddRef)(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcComputePipelineRelease)(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of DawnDrmFormatCapabilities +typedef void (*WGPUProcDawnDrmFormatCapabilitiesFreeMembers)(WGPUDawnDrmFormatCapabilities dawnDrmFormatCapabilities) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Device +typedef WGPUBindGroup (*WGPUProcDeviceCreateBindGroup)(WGPUDevice device, WGPUBindGroupDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBindGroupLayout (*WGPUProcDeviceCreateBindGroupLayout)(WGPUDevice device, WGPUBindGroupLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPU_NULLABLE WGPUBuffer (*WGPUProcDeviceCreateBuffer)(WGPUDevice device, WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUCommandEncoder (*WGPUProcDeviceCreateCommandEncoder)(WGPUDevice device, WGPU_NULLABLE WGPUCommandEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUComputePipeline (*WGPUProcDeviceCreateComputePipeline)(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcDeviceCreateComputePipelineAsync)(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUCreateComputePipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBuffer (*WGPUProcDeviceCreateErrorBuffer)(WGPUDevice device, WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUExternalTexture (*WGPUProcDeviceCreateErrorExternalTexture)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUShaderModule (*WGPUProcDeviceCreateErrorShaderModule)(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor, WGPUStringView errorMessage) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTexture (*WGPUProcDeviceCreateErrorTexture)(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUExternalTexture (*WGPUProcDeviceCreateExternalTexture)(WGPUDevice device, WGPUExternalTextureDescriptor const * externalTextureDescriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUPipelineLayout (*WGPUProcDeviceCreatePipelineLayout)(WGPUDevice device, WGPUPipelineLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUQuerySet (*WGPUProcDeviceCreateQuerySet)(WGPUDevice device, WGPUQuerySetDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPURenderBundleEncoder (*WGPUProcDeviceCreateRenderBundleEncoder)(WGPUDevice device, WGPURenderBundleEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPURenderPipeline (*WGPUProcDeviceCreateRenderPipeline)(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcDeviceCreateRenderPipelineAsync)(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUCreateRenderPipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUResourceTable (*WGPUProcDeviceCreateResourceTable)(WGPUDevice device, WGPUResourceTableDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUSampler (*WGPUProcDeviceCreateSampler)(WGPUDevice device, WGPU_NULLABLE WGPUSamplerDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUShaderModule (*WGPUProcDeviceCreateShaderModule)(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTexture (*WGPUProcDeviceCreateTexture)(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceDestroy)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceForceLoss)(WGPUDevice device, WGPUDeviceLostReason type, WGPUStringView message) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUAdapter (*WGPUProcDeviceGetAdapter)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcDeviceGetAdapterInfo)(WGPUDevice device, WGPUAdapterInfo * adapterInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcDeviceGetAHardwareBufferProperties)(WGPUDevice device, void * handle, WGPUAHardwareBufferProperties * properties) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceGetFeatures)(WGPUDevice device, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcDeviceGetLimits)(WGPUDevice device, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcDeviceGetLostFuture)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUQueue (*WGPUProcDeviceGetQueue)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBool (*WGPUProcDeviceHasFeature)(WGPUDevice device, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUSharedBufferMemory (*WGPUProcDeviceImportSharedBufferMemory)(WGPUDevice device, WGPUSharedBufferMemoryDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUSharedFence (*WGPUProcDeviceImportSharedFence)(WGPUDevice device, WGPUSharedFenceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUSharedTextureMemory (*WGPUProcDeviceImportSharedTextureMemory)(WGPUDevice device, WGPUSharedTextureMemoryDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceInjectError)(WGPUDevice device, WGPUErrorType type, WGPUStringView message) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcDevicePopErrorScope)(WGPUDevice device, WGPUPopErrorScopeCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDevicePushErrorScope)(WGPUDevice device, WGPUErrorFilter filter) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceSetLabel)(WGPUDevice device, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceSetLoggingCallback)(WGPUDevice device, WGPULoggingCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceTick)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceValidateTextureDescriptor)(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceAddRef)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcDeviceRelease)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of ExternalTexture +typedef void (*WGPUProcExternalTextureDestroy)(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcExternalTextureExpire)(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcExternalTextureRefresh)(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcExternalTextureSetLabel)(WGPUExternalTexture externalTexture, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcExternalTextureAddRef)(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcExternalTextureRelease)(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Instance +typedef WGPUSurface (*WGPUProcInstanceCreateSurface)(WGPUInstance instance, WGPUSurfaceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcInstanceGetWGSLLanguageFeatures)(WGPUInstance instance, WGPUSupportedWGSLLanguageFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBool (*WGPUProcInstanceHasWGSLLanguageFeature)(WGPUInstance instance, WGPUWGSLLanguageFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcInstanceProcessEvents)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcInstanceRequestAdapter)(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPURequestAdapterCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUWaitStatus (*WGPUProcInstanceWaitAny)(WGPUInstance instance, size_t futureCount, WGPU_NULLABLE WGPUFutureWaitInfo * futures, uint64_t timeoutNS) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcInstanceAddRef)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcInstanceRelease)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of PipelineLayout +typedef void (*WGPUProcPipelineLayoutSetLabel)(WGPUPipelineLayout pipelineLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcPipelineLayoutAddRef)(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcPipelineLayoutRelease)(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of QuerySet +typedef void (*WGPUProcQuerySetDestroy)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcQuerySetGetCount)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUQueryType (*WGPUProcQuerySetGetType)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQuerySetSetLabel)(WGPUQuerySet querySet, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQuerySetAddRef)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQuerySetRelease)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Queue +typedef void (*WGPUProcQueueCopyExternalTextureForBrowser)(WGPUQueue queue, WGPUImageCopyExternalTexture const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize, WGPUCopyTextureForBrowserOptions const * options) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueCopyTextureForBrowser)(WGPUQueue queue, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize, WGPUCopyTextureForBrowserOptions const * options) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUFuture (*WGPUProcQueueOnSubmittedWorkDone)(WGPUQueue queue, WGPUQueueWorkDoneCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueSetLabel)(WGPUQueue queue, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueSubmit)(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueWriteBuffer)(WGPUQueue queue, WGPUBuffer buffer, uint64_t bufferOffset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueWriteTexture)(WGPUQueue queue, WGPUTexelCopyTextureInfo const * destination, void const * data, size_t dataSize, WGPUTexelCopyBufferLayout const * dataLayout, WGPUExtent3D const * writeSize) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueAddRef)(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcQueueRelease)(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of RenderBundle +typedef void (*WGPUProcRenderBundleSetLabel)(WGPURenderBundle renderBundle, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleAddRef)(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleRelease)(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of RenderBundleEncoder +typedef void (*WGPUProcRenderBundleEncoderDraw)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderDrawIndexed)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderDrawIndexedIndirect)(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderDrawIndirect)(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPURenderBundle (*WGPUProcRenderBundleEncoderFinish)(WGPURenderBundleEncoder renderBundleEncoder, WGPU_NULLABLE WGPURenderBundleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderInsertDebugMarker)(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderPopDebugGroup)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderPushDebugGroup)(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderSetBindGroup)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderSetImmediates)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderSetIndexBuffer)(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderSetLabel)(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderSetPipeline)(WGPURenderBundleEncoder renderBundleEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderSetVertexBuffer)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderAddRef)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderBundleEncoderRelease)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of RenderPassEncoder +typedef void (*WGPUProcRenderPassEncoderBeginOcclusionQuery)(WGPURenderPassEncoder renderPassEncoder, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderDraw)(WGPURenderPassEncoder renderPassEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderDrawIndexed)(WGPURenderPassEncoder renderPassEncoder, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderDrawIndexedIndirect)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderDrawIndirect)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderEnd)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderEndOcclusionQuery)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderExecuteBundles)(WGPURenderPassEncoder renderPassEncoder, size_t bundleCount, WGPURenderBundle const * bundles) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderInsertDebugMarker)(WGPURenderPassEncoder renderPassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderMultiDrawIndexedIndirect)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset, uint32_t maxDrawCount, WGPU_NULLABLE WGPUBuffer drawCountBuffer, uint64_t drawCountBufferOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderMultiDrawIndirect)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset, uint32_t maxDrawCount, WGPU_NULLABLE WGPUBuffer drawCountBuffer, uint64_t drawCountBufferOffset) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderPixelLocalStorageBarrier)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderPopDebugGroup)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderPushDebugGroup)(WGPURenderPassEncoder renderPassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetBindGroup)(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetBlendConstant)(WGPURenderPassEncoder renderPassEncoder, WGPUColor const * color) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetImmediates)(WGPURenderPassEncoder renderPassEncoder, uint32_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetIndexBuffer)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetLabel)(WGPURenderPassEncoder renderPassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetPipeline)(WGPURenderPassEncoder renderPassEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetScissorRect)(WGPURenderPassEncoder renderPassEncoder, uint32_t x, uint32_t y, uint32_t width, uint32_t height) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetStencilReference)(WGPURenderPassEncoder renderPassEncoder, uint32_t reference) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetVertexBuffer)(WGPURenderPassEncoder renderPassEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderSetViewport)(WGPURenderPassEncoder renderPassEncoder, float x, float y, float width, float height, float minDepth, float maxDepth) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderWriteTimestamp)(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderAddRef)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPassEncoderRelease)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of RenderPipeline +typedef WGPUBindGroupLayout (*WGPUProcRenderPipelineGetBindGroupLayout)(WGPURenderPipeline renderPipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPipelineSetLabel)(WGPURenderPipeline renderPipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPipelineAddRef)(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcRenderPipelineRelease)(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of ResourceTable +typedef void (*WGPUProcResourceTableDestroy)(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcResourceTableGetSize)(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcResourceTableInsertBinding)(WGPUResourceTable resourceTable, WGPUBindingResource const * resource) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcResourceTableRemoveBinding)(WGPUResourceTable resourceTable, uint32_t slot) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcResourceTableUpdate)(WGPUResourceTable resourceTable, uint32_t slot, WGPUBindingResource const * resource) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcResourceTableAddRef)(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcResourceTableRelease)(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Sampler +typedef void (*WGPUProcSamplerSetLabel)(WGPUSampler sampler, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSamplerAddRef)(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSamplerRelease)(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of ShaderModule +typedef WGPUFuture (*WGPUProcShaderModuleGetCompilationInfo)(WGPUShaderModule shaderModule, WGPUCompilationInfoCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcShaderModuleSetLabel)(WGPUShaderModule shaderModule, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcShaderModuleAddRef)(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcShaderModuleRelease)(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SharedBufferMemory +typedef WGPUStatus (*WGPUProcSharedBufferMemoryBeginAccess)(WGPUSharedBufferMemory sharedBufferMemory, WGPUBuffer buffer, WGPUSharedBufferMemoryBeginAccessDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBuffer (*WGPUProcSharedBufferMemoryCreateBuffer)(WGPUSharedBufferMemory sharedBufferMemory, WGPU_NULLABLE WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcSharedBufferMemoryEndAccess)(WGPUSharedBufferMemory sharedBufferMemory, WGPUBuffer buffer, WGPUSharedBufferMemoryEndAccessState * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcSharedBufferMemoryGetProperties)(WGPUSharedBufferMemory sharedBufferMemory, WGPUSharedBufferMemoryProperties * properties) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBool (*WGPUProcSharedBufferMemoryIsDeviceLost)(WGPUSharedBufferMemory sharedBufferMemory) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedBufferMemorySetLabel)(WGPUSharedBufferMemory sharedBufferMemory, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedBufferMemoryAddRef)(WGPUSharedBufferMemory sharedBufferMemory) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedBufferMemoryRelease)(WGPUSharedBufferMemory sharedBufferMemory) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SharedBufferMemoryEndAccessState +typedef void (*WGPUProcSharedBufferMemoryEndAccessStateFreeMembers)(WGPUSharedBufferMemoryEndAccessState sharedBufferMemoryEndAccessState) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SharedFence +typedef void (*WGPUProcSharedFenceExportInfo)(WGPUSharedFence sharedFence, WGPUSharedFenceExportInfo * info) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedFenceAddRef)(WGPUSharedFence sharedFence) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedFenceRelease)(WGPUSharedFence sharedFence) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SharedTextureMemory +typedef WGPUStatus (*WGPUProcSharedTextureMemoryBeginAccess)(WGPUSharedTextureMemory sharedTextureMemory, WGPUTexture texture, WGPUSharedTextureMemoryBeginAccessDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTexture (*WGPUProcSharedTextureMemoryCreateTexture)(WGPUSharedTextureMemory sharedTextureMemory, WGPU_NULLABLE WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcSharedTextureMemoryEndAccess)(WGPUSharedTextureMemory sharedTextureMemory, WGPUTexture texture, WGPUSharedTextureMemoryEndAccessState * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcSharedTextureMemoryGetProperties)(WGPUSharedTextureMemory sharedTextureMemory, WGPUSharedTextureMemoryProperties * properties) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUBool (*WGPUProcSharedTextureMemoryIsDeviceLost)(WGPUSharedTextureMemory sharedTextureMemory) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedTextureMemorySetLabel)(WGPUSharedTextureMemory sharedTextureMemory, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedTextureMemoryAddRef)(WGPUSharedTextureMemory sharedTextureMemory) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSharedTextureMemoryRelease)(WGPUSharedTextureMemory sharedTextureMemory) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SharedTextureMemoryEndAccessState +typedef void (*WGPUProcSharedTextureMemoryEndAccessStateFreeMembers)(WGPUSharedTextureMemoryEndAccessState sharedTextureMemoryEndAccessState) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SupportedFeatures +typedef void (*WGPUProcSupportedFeaturesFreeMembers)(WGPUSupportedFeatures supportedFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SupportedInstanceFeatures +typedef void (*WGPUProcSupportedInstanceFeaturesFreeMembers)(WGPUSupportedInstanceFeatures supportedInstanceFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SupportedWGSLLanguageFeatures +typedef void (*WGPUProcSupportedWGSLLanguageFeaturesFreeMembers)(WGPUSupportedWGSLLanguageFeatures supportedWGSLLanguageFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Surface +typedef void (*WGPUProcSurfaceConfigure)(WGPUSurface surface, WGPUSurfaceConfiguration const * config) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcSurfaceGetCapabilities)(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSurfaceGetCurrentTexture)(WGPUSurface surface, WGPUSurfaceTexture * surfaceTexture) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUStatus (*WGPUProcSurfacePresent)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSurfaceSetLabel)(WGPUSurface surface, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSurfaceUnconfigure)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSurfaceAddRef)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcSurfaceRelease)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SurfaceCapabilities +typedef void (*WGPUProcSurfaceCapabilitiesFreeMembers)(WGPUSurfaceCapabilities surfaceCapabilities) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of TexelBufferView +typedef void (*WGPUProcTexelBufferViewSetLabel)(WGPUTexelBufferView texelBufferView, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTexelBufferViewAddRef)(WGPUTexelBufferView texelBufferView) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTexelBufferViewRelease)(WGPUTexelBufferView texelBufferView) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of Texture +typedef WGPUTextureView (*WGPUProcTextureCreateErrorView)(WGPUTexture texture, WGPU_NULLABLE WGPUTextureViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTextureView (*WGPUProcTextureCreateView)(WGPUTexture texture, WGPU_NULLABLE WGPUTextureViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureDestroy)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcTextureGetDepthOrArrayLayers)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTextureDimension (*WGPUProcTextureGetDimension)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTextureFormat (*WGPUProcTextureGetFormat)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcTextureGetHeight)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcTextureGetMipLevelCount)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcTextureGetSampleCount)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTextureViewDimension (*WGPUProcTextureGetTextureBindingViewDimension)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef WGPUTextureUsage (*WGPUProcTextureGetUsage)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef uint32_t (*WGPUProcTextureGetWidth)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTexturePin)(WGPUTexture texture, WGPUTextureUsage usage) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureSetLabel)(WGPUTexture texture, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureSetOwnershipForMemoryDump)(WGPUTexture texture, uint64_t ownerGuid) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureUnpin)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureAddRef)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureRelease)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of TextureView +typedef void (*WGPUProcTextureViewSetLabel)(WGPUTextureView textureView, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureViewAddRef)(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProcTextureViewRelease)(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; + +#endif // !defined(WGPU_SKIP_PROCS) + +#if !defined(WGPU_SKIP_DECLARATIONS) +WGPU_EXPORT WGPUInstance wgpuCreateInstance(WGPU_NULLABLE WGPUInstanceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuGetInstanceFeatures(WGPUSupportedInstanceFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuGetInstanceLimits(WGPUInstanceLimits * limits) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuHasInstanceFeature(WGPUInstanceFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUStringView procName) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Adapter +WGPU_EXPORT WGPUDevice wgpuAdapterCreateDevice(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuAdapterGetFeatures(WGPUAdapter adapter, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuAdapterGetFormatCapabilities(WGPUAdapter adapter, WGPUTextureFormat format, WGPUDawnFormatCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuAdapterGetInfo(WGPUAdapter adapter, WGPUAdapterInfo * info) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUInstance wgpuAdapterGetInstance(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuAdapterGetLimits(WGPUAdapter adapter, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuAdapterHasFeature(WGPUAdapter adapter, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor, WGPURequestDeviceCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuAdapterAddRef(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuAdapterRelease(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of AdapterInfo +WGPU_EXPORT void wgpuAdapterInfoFreeMembers(WGPUAdapterInfo adapterInfo) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of AdapterPropertiesMemoryHeaps +WGPU_EXPORT void wgpuAdapterPropertiesMemoryHeapsFreeMembers(WGPUAdapterPropertiesMemoryHeaps adapterPropertiesMemoryHeaps) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of AdapterPropertiesSubgroupMatrixConfigs +WGPU_EXPORT void wgpuAdapterPropertiesSubgroupMatrixConfigsFreeMembers(WGPUAdapterPropertiesSubgroupMatrixConfigs adapterPropertiesSubgroupMatrixConfigs) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of BindGroup +WGPU_EXPORT void wgpuBindGroupSetLabel(WGPUBindGroup bindGroup, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupAddRef(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupRelease(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of BindGroupLayout +WGPU_EXPORT void wgpuBindGroupLayoutSetLabel(WGPUBindGroupLayout bindGroupLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupLayoutAddRef(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupLayoutRelease(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Buffer +WGPU_EXPORT WGPUTexelBufferView wgpuBufferCreateTexelView(WGPUBuffer buffer, WGPUTexelBufferViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferDestroy(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void const * wgpuBufferGetConstMappedRange(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void * wgpuBufferGetMappedRange(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBufferMapState wgpuBufferGetMapState(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint64_t wgpuBufferGetSize(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBufferUsage wgpuBufferGetUsage(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuBufferMapAsync(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuBufferReadMappedRange(WGPUBuffer buffer, size_t offset, void * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferSetLabel(WGPUBuffer buffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferUnmap(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuBufferWriteMappedRange(WGPUBuffer buffer, size_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferAddRef(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferRelease(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of CommandBuffer +WGPU_EXPORT void wgpuCommandBufferSetLabel(WGPUCommandBuffer commandBuffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandBufferAddRef(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandBufferRelease(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of CommandEncoder +WGPU_EXPORT WGPUComputePassEncoder wgpuCommandEncoderBeginComputePass(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUComputePassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPURenderPassEncoder wgpuCommandEncoderBeginRenderPass(WGPUCommandEncoder commandEncoder, WGPURenderPassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderClearBuffer(WGPUCommandEncoder commandEncoder, WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyBufferToBuffer(WGPUCommandEncoder commandEncoder, WGPUBuffer source, uint64_t sourceOffset, WGPUBuffer destination, uint64_t destinationOffset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyBufferToTexture(WGPUCommandEncoder commandEncoder, WGPUTexelCopyBufferInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyTextureToBuffer(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyBufferInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyTextureToTexture(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUCommandBuffer wgpuCommandEncoderFinish(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUCommandBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderInjectValidationError(WGPUCommandEncoder commandEncoder, WGPUStringView message) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderInsertDebugMarker(WGPUCommandEncoder commandEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderPopDebugGroup(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderPushDebugGroup(WGPUCommandEncoder commandEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderResolveQuerySet(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t firstQuery, uint32_t queryCount, WGPUBuffer destination, uint64_t destinationOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderSetLabel(WGPUCommandEncoder commandEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderSetResourceTable(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUResourceTable table) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderWriteBuffer(WGPUCommandEncoder commandEncoder, WGPUBuffer buffer, uint64_t bufferOffset, uint8_t const * data, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderWriteTimestamp(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderAddRef(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderRelease(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of ComputePassEncoder +WGPU_EXPORT void wgpuComputePassEncoderDispatchWorkgroups(WGPUComputePassEncoder computePassEncoder, uint32_t workgroupCountX, uint32_t workgroupCountY, uint32_t workgroupCountZ) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderDispatchWorkgroupsIndirect(WGPUComputePassEncoder computePassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderEnd(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderInsertDebugMarker(WGPUComputePassEncoder computePassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderPopDebugGroup(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderPushDebugGroup(WGPUComputePassEncoder computePassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderSetBindGroup(WGPUComputePassEncoder computePassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderSetImmediates(WGPUComputePassEncoder computePassEncoder, uint32_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderSetLabel(WGPUComputePassEncoder computePassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderSetPipeline(WGPUComputePassEncoder computePassEncoder, WGPUComputePipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderWriteTimestamp(WGPUComputePassEncoder computePassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderAddRef(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderRelease(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of ComputePipeline +WGPU_EXPORT WGPUBindGroupLayout wgpuComputePipelineGetBindGroupLayout(WGPUComputePipeline computePipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePipelineSetLabel(WGPUComputePipeline computePipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePipelineAddRef(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePipelineRelease(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of DawnDrmFormatCapabilities +WGPU_EXPORT void wgpuDawnDrmFormatCapabilitiesFreeMembers(WGPUDawnDrmFormatCapabilities dawnDrmFormatCapabilities) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Device +WGPU_EXPORT WGPUBindGroup wgpuDeviceCreateBindGroup(WGPUDevice device, WGPUBindGroupDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBindGroupLayout wgpuDeviceCreateBindGroupLayout(WGPUDevice device, WGPUBindGroupLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPU_NULLABLE WGPUBuffer wgpuDeviceCreateBuffer(WGPUDevice device, WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUCommandEncoder wgpuDeviceCreateCommandEncoder(WGPUDevice device, WGPU_NULLABLE WGPUCommandEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUComputePipeline wgpuDeviceCreateComputePipeline(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDeviceCreateComputePipelineAsync(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUCreateComputePipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBuffer wgpuDeviceCreateErrorBuffer(WGPUDevice device, WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUExternalTexture wgpuDeviceCreateErrorExternalTexture(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUShaderModule wgpuDeviceCreateErrorShaderModule(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor, WGPUStringView errorMessage) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTexture wgpuDeviceCreateErrorTexture(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUExternalTexture wgpuDeviceCreateExternalTexture(WGPUDevice device, WGPUExternalTextureDescriptor const * externalTextureDescriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUPipelineLayout wgpuDeviceCreatePipelineLayout(WGPUDevice device, WGPUPipelineLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUQuerySet wgpuDeviceCreateQuerySet(WGPUDevice device, WGPUQuerySetDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPURenderBundleEncoder wgpuDeviceCreateRenderBundleEncoder(WGPUDevice device, WGPURenderBundleEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPURenderPipeline wgpuDeviceCreateRenderPipeline(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDeviceCreateRenderPipelineAsync(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUCreateRenderPipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUResourceTable wgpuDeviceCreateResourceTable(WGPUDevice device, WGPUResourceTableDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUSampler wgpuDeviceCreateSampler(WGPUDevice device, WGPU_NULLABLE WGPUSamplerDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUShaderModule wgpuDeviceCreateShaderModule(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTexture wgpuDeviceCreateTexture(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceDestroy(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceForceLoss(WGPUDevice device, WGPUDeviceLostReason type, WGPUStringView message) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUAdapter wgpuDeviceGetAdapter(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuDeviceGetAdapterInfo(WGPUDevice device, WGPUAdapterInfo * adapterInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuDeviceGetAHardwareBufferProperties(WGPUDevice device, void * handle, WGPUAHardwareBufferProperties * properties) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceGetFeatures(WGPUDevice device, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuDeviceGetLimits(WGPUDevice device, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDeviceGetLostFuture(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUQueue wgpuDeviceGetQueue(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuDeviceHasFeature(WGPUDevice device, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUSharedBufferMemory wgpuDeviceImportSharedBufferMemory(WGPUDevice device, WGPUSharedBufferMemoryDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUSharedFence wgpuDeviceImportSharedFence(WGPUDevice device, WGPUSharedFenceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUSharedTextureMemory wgpuDeviceImportSharedTextureMemory(WGPUDevice device, WGPUSharedTextureMemoryDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceInjectError(WGPUDevice device, WGPUErrorType type, WGPUStringView message) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDevicePopErrorScope(WGPUDevice device, WGPUPopErrorScopeCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDevicePushErrorScope(WGPUDevice device, WGPUErrorFilter filter) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceSetLabel(WGPUDevice device, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceSetLoggingCallback(WGPUDevice device, WGPULoggingCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceTick(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceValidateTextureDescriptor(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceAddRef(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceRelease(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of ExternalTexture +WGPU_EXPORT void wgpuExternalTextureDestroy(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuExternalTextureExpire(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuExternalTextureRefresh(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuExternalTextureSetLabel(WGPUExternalTexture externalTexture, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuExternalTextureAddRef(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuExternalTextureRelease(WGPUExternalTexture externalTexture) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Instance +WGPU_EXPORT WGPUSurface wgpuInstanceCreateSurface(WGPUInstance instance, WGPUSurfaceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuInstanceGetWGSLLanguageFeatures(WGPUInstance instance, WGPUSupportedWGSLLanguageFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuInstanceHasWGSLLanguageFeature(WGPUInstance instance, WGPUWGSLLanguageFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuInstanceProcessEvents(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuInstanceRequestAdapter(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPURequestAdapterCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUWaitStatus wgpuInstanceWaitAny(WGPUInstance instance, size_t futureCount, WGPU_NULLABLE WGPUFutureWaitInfo * futures, uint64_t timeoutNS) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuInstanceAddRef(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuInstanceRelease(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of PipelineLayout +WGPU_EXPORT void wgpuPipelineLayoutSetLabel(WGPUPipelineLayout pipelineLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuPipelineLayoutAddRef(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuPipelineLayoutRelease(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of QuerySet +WGPU_EXPORT void wgpuQuerySetDestroy(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuQuerySetGetCount(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUQueryType wgpuQuerySetGetType(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQuerySetSetLabel(WGPUQuerySet querySet, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQuerySetAddRef(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQuerySetRelease(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Queue +WGPU_EXPORT void wgpuQueueCopyExternalTextureForBrowser(WGPUQueue queue, WGPUImageCopyExternalTexture const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize, WGPUCopyTextureForBrowserOptions const * options) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueCopyTextureForBrowser(WGPUQueue queue, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize, WGPUCopyTextureForBrowserOptions const * options) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuQueueOnSubmittedWorkDone(WGPUQueue queue, WGPUQueueWorkDoneCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueSetLabel(WGPUQueue queue, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueSubmit(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueWriteBuffer(WGPUQueue queue, WGPUBuffer buffer, uint64_t bufferOffset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueWriteTexture(WGPUQueue queue, WGPUTexelCopyTextureInfo const * destination, void const * data, size_t dataSize, WGPUTexelCopyBufferLayout const * dataLayout, WGPUExtent3D const * writeSize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueAddRef(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueRelease(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of RenderBundle +WGPU_EXPORT void wgpuRenderBundleSetLabel(WGPURenderBundle renderBundle, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleAddRef(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleRelease(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of RenderBundleEncoder +WGPU_EXPORT void wgpuRenderBundleEncoderDraw(WGPURenderBundleEncoder renderBundleEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderDrawIndexed(WGPURenderBundleEncoder renderBundleEncoder, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderDrawIndexedIndirect(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderDrawIndirect(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPURenderBundle wgpuRenderBundleEncoderFinish(WGPURenderBundleEncoder renderBundleEncoder, WGPU_NULLABLE WGPURenderBundleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderInsertDebugMarker(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderPopDebugGroup(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderPushDebugGroup(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetBindGroup(WGPURenderBundleEncoder renderBundleEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetImmediates(WGPURenderBundleEncoder renderBundleEncoder, uint32_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetIndexBuffer(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetLabel(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetPipeline(WGPURenderBundleEncoder renderBundleEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetVertexBuffer(WGPURenderBundleEncoder renderBundleEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderAddRef(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderRelease(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of RenderPassEncoder +WGPU_EXPORT void wgpuRenderPassEncoderBeginOcclusionQuery(WGPURenderPassEncoder renderPassEncoder, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderDraw(WGPURenderPassEncoder renderPassEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderDrawIndexed(WGPURenderPassEncoder renderPassEncoder, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderDrawIndexedIndirect(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderDrawIndirect(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderEnd(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderEndOcclusionQuery(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderExecuteBundles(WGPURenderPassEncoder renderPassEncoder, size_t bundleCount, WGPURenderBundle const * bundles) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderInsertDebugMarker(WGPURenderPassEncoder renderPassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderMultiDrawIndexedIndirect(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset, uint32_t maxDrawCount, WGPU_NULLABLE WGPUBuffer drawCountBuffer, uint64_t drawCountBufferOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderMultiDrawIndirect(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset, uint32_t maxDrawCount, WGPU_NULLABLE WGPUBuffer drawCountBuffer, uint64_t drawCountBufferOffset) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderPixelLocalStorageBarrier(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderPopDebugGroup(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderPushDebugGroup(WGPURenderPassEncoder renderPassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetBindGroup(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetBlendConstant(WGPURenderPassEncoder renderPassEncoder, WGPUColor const * color) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetImmediates(WGPURenderPassEncoder renderPassEncoder, uint32_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetIndexBuffer(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetLabel(WGPURenderPassEncoder renderPassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetPipeline(WGPURenderPassEncoder renderPassEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetScissorRect(WGPURenderPassEncoder renderPassEncoder, uint32_t x, uint32_t y, uint32_t width, uint32_t height) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetStencilReference(WGPURenderPassEncoder renderPassEncoder, uint32_t reference) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetVertexBuffer(WGPURenderPassEncoder renderPassEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetViewport(WGPURenderPassEncoder renderPassEncoder, float x, float y, float width, float height, float minDepth, float maxDepth) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderWriteTimestamp(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderAddRef(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderRelease(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of RenderPipeline +WGPU_EXPORT WGPUBindGroupLayout wgpuRenderPipelineGetBindGroupLayout(WGPURenderPipeline renderPipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPipelineSetLabel(WGPURenderPipeline renderPipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPipelineAddRef(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPipelineRelease(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of ResourceTable +WGPU_EXPORT void wgpuResourceTableDestroy(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuResourceTableGetSize(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuResourceTableInsertBinding(WGPUResourceTable resourceTable, WGPUBindingResource const * resource) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuResourceTableRemoveBinding(WGPUResourceTable resourceTable, uint32_t slot) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuResourceTableUpdate(WGPUResourceTable resourceTable, uint32_t slot, WGPUBindingResource const * resource) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuResourceTableAddRef(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuResourceTableRelease(WGPUResourceTable resourceTable) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Sampler +WGPU_EXPORT void wgpuSamplerSetLabel(WGPUSampler sampler, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSamplerAddRef(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSamplerRelease(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of ShaderModule +WGPU_EXPORT WGPUFuture wgpuShaderModuleGetCompilationInfo(WGPUShaderModule shaderModule, WGPUCompilationInfoCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuShaderModuleSetLabel(WGPUShaderModule shaderModule, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuShaderModuleAddRef(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuShaderModuleRelease(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SharedBufferMemory +WGPU_EXPORT WGPUStatus wgpuSharedBufferMemoryBeginAccess(WGPUSharedBufferMemory sharedBufferMemory, WGPUBuffer buffer, WGPUSharedBufferMemoryBeginAccessDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBuffer wgpuSharedBufferMemoryCreateBuffer(WGPUSharedBufferMemory sharedBufferMemory, WGPU_NULLABLE WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuSharedBufferMemoryEndAccess(WGPUSharedBufferMemory sharedBufferMemory, WGPUBuffer buffer, WGPUSharedBufferMemoryEndAccessState * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuSharedBufferMemoryGetProperties(WGPUSharedBufferMemory sharedBufferMemory, WGPUSharedBufferMemoryProperties * properties) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuSharedBufferMemoryIsDeviceLost(WGPUSharedBufferMemory sharedBufferMemory) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedBufferMemorySetLabel(WGPUSharedBufferMemory sharedBufferMemory, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedBufferMemoryAddRef(WGPUSharedBufferMemory sharedBufferMemory) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedBufferMemoryRelease(WGPUSharedBufferMemory sharedBufferMemory) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SharedBufferMemoryEndAccessState +WGPU_EXPORT void wgpuSharedBufferMemoryEndAccessStateFreeMembers(WGPUSharedBufferMemoryEndAccessState sharedBufferMemoryEndAccessState) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SharedFence +WGPU_EXPORT void wgpuSharedFenceExportInfo(WGPUSharedFence sharedFence, WGPUSharedFenceExportInfo * info) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedFenceAddRef(WGPUSharedFence sharedFence) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedFenceRelease(WGPUSharedFence sharedFence) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SharedTextureMemory +WGPU_EXPORT WGPUStatus wgpuSharedTextureMemoryBeginAccess(WGPUSharedTextureMemory sharedTextureMemory, WGPUTexture texture, WGPUSharedTextureMemoryBeginAccessDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTexture wgpuSharedTextureMemoryCreateTexture(WGPUSharedTextureMemory sharedTextureMemory, WGPU_NULLABLE WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuSharedTextureMemoryEndAccess(WGPUSharedTextureMemory sharedTextureMemory, WGPUTexture texture, WGPUSharedTextureMemoryEndAccessState * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuSharedTextureMemoryGetProperties(WGPUSharedTextureMemory sharedTextureMemory, WGPUSharedTextureMemoryProperties * properties) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuSharedTextureMemoryIsDeviceLost(WGPUSharedTextureMemory sharedTextureMemory) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedTextureMemorySetLabel(WGPUSharedTextureMemory sharedTextureMemory, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedTextureMemoryAddRef(WGPUSharedTextureMemory sharedTextureMemory) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSharedTextureMemoryRelease(WGPUSharedTextureMemory sharedTextureMemory) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SharedTextureMemoryEndAccessState +WGPU_EXPORT void wgpuSharedTextureMemoryEndAccessStateFreeMembers(WGPUSharedTextureMemoryEndAccessState sharedTextureMemoryEndAccessState) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SupportedFeatures +WGPU_EXPORT void wgpuSupportedFeaturesFreeMembers(WGPUSupportedFeatures supportedFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SupportedInstanceFeatures +WGPU_EXPORT void wgpuSupportedInstanceFeaturesFreeMembers(WGPUSupportedInstanceFeatures supportedInstanceFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SupportedWGSLLanguageFeatures +WGPU_EXPORT void wgpuSupportedWGSLLanguageFeaturesFreeMembers(WGPUSupportedWGSLLanguageFeatures supportedWGSLLanguageFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Surface +WGPU_EXPORT void wgpuSurfaceConfigure(WGPUSurface surface, WGPUSurfaceConfiguration const * config) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuSurfaceGetCapabilities(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSurfaceGetCurrentTexture(WGPUSurface surface, WGPUSurfaceTexture * surfaceTexture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUStatus wgpuSurfacePresent(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSurfaceSetLabel(WGPUSurface surface, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSurfaceUnconfigure(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSurfaceAddRef(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSurfaceRelease(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of SurfaceCapabilities +WGPU_EXPORT void wgpuSurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities surfaceCapabilities) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of TexelBufferView +WGPU_EXPORT void wgpuTexelBufferViewSetLabel(WGPUTexelBufferView texelBufferView, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTexelBufferViewAddRef(WGPUTexelBufferView texelBufferView) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTexelBufferViewRelease(WGPUTexelBufferView texelBufferView) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of Texture +WGPU_EXPORT WGPUTextureView wgpuTextureCreateErrorView(WGPUTexture texture, WGPU_NULLABLE WGPUTextureViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTextureView wgpuTextureCreateView(WGPUTexture texture, WGPU_NULLABLE WGPUTextureViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureDestroy(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuTextureGetDepthOrArrayLayers(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTextureDimension wgpuTextureGetDimension(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTextureFormat wgpuTextureGetFormat(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuTextureGetHeight(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuTextureGetMipLevelCount(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuTextureGetSampleCount(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTextureViewDimension wgpuTextureGetTextureBindingViewDimension(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTextureUsage wgpuTextureGetUsage(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT uint32_t wgpuTextureGetWidth(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTexturePin(WGPUTexture texture, WGPUTextureUsage usage) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureSetLabel(WGPUTexture texture, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureSetOwnershipForMemoryDump(WGPUTexture texture, uint64_t ownerGuid) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureUnpin(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureAddRef(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureRelease(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; + +// Methods of TextureView +WGPU_EXPORT void wgpuTextureViewSetLabel(WGPUTextureView textureView, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureViewAddRef(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureViewRelease(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; + +#endif // !defined(WGPU_SKIP_DECLARATIONS) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBGPU_H_ diff --git a/3rdparty/dawn/src/tint/api/common/binding_point.h b/3rdparty/dawn/src/tint/api/common/binding_point.h new file mode 100644 index 000000000..f6110d4f0 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/binding_point.h @@ -0,0 +1,109 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_BINDING_POINT_H_ +#define SRC_TINT_API_COMMON_BINDING_POINT_H_ + +#include + +#include + +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint { + +/// BindingPoint holds a group and binding index. +struct BindingPoint { + /// The `@group` part of the binding point + uint32_t group = 0; + /// The `@binding` part of the binding point + uint32_t binding = 0; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(BindingPoint, group, binding); + + /// @returns the hash code of the BindingPoint + tint::HashCode HashCode() const { return tint::Hash(group, binding); } + + /// Equality operator + /// @param rhs the BindingPoint to compare against + /// @returns true if this BindingPoint is equal to `rhs` + bool operator==(const BindingPoint& rhs) const { + return group == rhs.group && binding == rhs.binding; + } + + /// Inequality operator + /// @param rhs the BindingPoint to compare against + /// @returns true if this BindingPoint is not equal to `rhs` + bool operator!=(const BindingPoint& rhs) const { return !(*this == rhs); } + + /// Less-than operator + /// @param rhs the BindingPoint to compare against + /// @returns true if this BindingPoint comes before @p rhs + bool operator<(const BindingPoint& rhs) const { + if (group < rhs.group) { + return true; + } + if (group > rhs.group) { + return false; + } + return binding < rhs.binding; + } +}; + +/// Prints the BindingPoint @p bp to @p o +/// @param o the stream to write to +/// @param bp the BindingPoint +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, const BindingPoint& bp) { + return o << "[group: " << bp.group << ", binding: " << bp.binding << "]"; +} + +} // namespace tint + +namespace std { + +/// Custom std::hash specialization for tint::BindingPoint so BindingPoints can be used as keys for +/// std::unordered_map and std::unordered_set. +template <> +class hash { + public: + /// @param binding_point the binding point to create a hash for + /// @return the hash value + size_t operator()(const tint::BindingPoint& binding_point) const { + return (static_cast(binding_point.group) << 16) | + static_cast(binding_point.binding); + } +}; + +} // namespace std + +#endif // SRC_TINT_API_COMMON_BINDING_POINT_H_ diff --git a/3rdparty/dawn/src/tint/api/common/bindings.h b/3rdparty/dawn/src/tint/api/common/bindings.h new file mode 100644 index 000000000..8972170ff --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/bindings.h @@ -0,0 +1,90 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_BINDINGS_H_ +#define SRC_TINT_API_COMMON_BINDINGS_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/utils/reflection.h" + +namespace tint { + +/// An external texture +struct ExternalTexture { + /// Metadata + BindingPoint metadata{}; + /// Plane0 binding data + BindingPoint plane0{}; + /// Plane1 binding data + BindingPoint plane1{}; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(ExternalTexture, metadata, plane0, plane1); + + TINT_REFLECT_EQUALS(ExternalTexture); + TINT_REFLECT_HASH_CODE(ExternalTexture); +}; + +using BindingMap = std::unordered_map; +using ExternalTextureBindings = std::unordered_map; + +/// Binding information +struct Bindings { + /// Uniform bindings + BindingMap uniform{}; + /// Storage bindings + BindingMap storage{}; + /// Texture bindings + BindingMap texture{}; + /// Storage texture bindings + BindingMap storage_texture{}; + /// Sampler bindings + BindingMap sampler{}; + /// External bindings + ExternalTextureBindings external_texture{}; + /// Input attachment bindings + BindingMap input_attachment{}; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(Bindings, + uniform, + storage, + texture, + storage_texture, + sampler, + external_texture, + input_attachment); + + TINT_REFLECT_EQUALS(Bindings); + TINT_REFLECT_HASH_CODE(Bindings); +}; + +} // namespace tint + +#endif // SRC_TINT_API_COMMON_BINDINGS_H_ diff --git a/3rdparty/dawn/src/tint/api/common/override_id.h b/3rdparty/dawn/src/tint/api/common/override_id.h new file mode 100644 index 000000000..0a39b376c --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/override_id.h @@ -0,0 +1,84 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_OVERRIDE_ID_H_ +#define SRC_TINT_API_COMMON_OVERRIDE_ID_H_ + +#include +#include + +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/reflection.h" + +namespace tint { + +/// OverrideId is a numerical identifier for an override variable, unique per program. +struct OverrideId { + /// The identifier value + uint16_t value = 0; + + /// Reflect the fields of this struct so that it can be used by tint::ForeachField() + TINT_REFLECT(OverrideId, value); + + /// @returns the hash code of the OverrideId + tint::HashCode HashCode() const { return Hash(value); } +}; + +/// Equality operator for OverrideId +/// @param lhs the OverrideId on the left of the '=' operator +/// @param rhs the OverrideId on the right of the '=' operator +/// @returns true if `lhs` is equal to `rhs` +inline bool operator==(OverrideId lhs, OverrideId rhs) { + return lhs.value == rhs.value; +} + +/// Less-than operator for OverrideId +/// @param lhs the OverrideId on the left of the '<' operator +/// @param rhs the OverrideId on the right of the '<' operator +/// @returns true if `lhs` comes before `rhs` +inline bool operator<(OverrideId lhs, OverrideId rhs) { + return lhs.value < rhs.value; +} + +} // namespace tint + +namespace std { + +/// Custom std::hash specialization for tint::OverrideId. +template <> +class hash { + public: + /// @param id the override identifier + /// @return the hash of the override identifier + inline size_t operator()(tint::OverrideId id) const { + return std::hash()(id.value); + } +}; + +} // namespace std + +#endif // SRC_TINT_API_COMMON_OVERRIDE_ID_H_ diff --git a/3rdparty/dawn/src/tint/api/common/resource_table_config.h b/3rdparty/dawn/src/tint/api/common/resource_table_config.h new file mode 100644 index 000000000..28eab08ae --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/resource_table_config.h @@ -0,0 +1,98 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_RESOURCE_TABLE_CONFIG_H_ +#define SRC_TINT_API_COMMON_RESOURCE_TABLE_CONFIG_H_ + +#include +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/api/common/resource_type.h" +#include "src/tint/utils/reflection.h" + +namespace tint { + +// Configuration for the resource table transform. +// +// The resource table transform assumes that for each resource table entry there will be an +// entry in the `bindings` hash map. That binding will provide information on the storage buffer +// attached for the resource table. Specifically, the storage buffer should have a format of: +// +// ``` +// struct SB { +// array_length: u32, +// bindings: array, // Has `array_length` entries (doesn't include the default bindings). +// } +// ``` +// +// The values used in the `bindings` are from the `u32` conversion of the `ResourceType` enum +// entries. +// +struct ResourceTableConfig { + // The binding point for the resource_table. This is a post-remapping binding point. + BindingPoint resource_table_binding; + + // The binding point for the supporting storage buffer. This is a post-remapping binding point. + BindingPoint storage_buffer_binding; + + // The ordering of default bindings which are placed after the user bindings. These will be used + // as the index to lookup the given `ResourceType` if the user accesses with an incorrect + // texture type (or out of bounds). + // + // These `default_binding_type_order` entries will be used when we need to substitute in a + // default binding. So, we assume that Dawn is providing the resource table memory as: + // + // `[user 1 (2d_i32), user 2 (3d_f32), user 3 (1d_u32), 1d_u32_default, 2d_f32_default, + // 3d_f32_default]` + // + // We would then have `default_binding_type_order` entries of: + // + // `[1d_u32, 2d_f32, 3d_f32]` + // + // Then when we compile a `getResource(i)` call, we will have created the storage buffer, + // call it `metadata` in this case: + // + // ``` + // const len = metadata.array_length; + // if (i < len && type_to_u32(T) == metadata.bindings[i]) { + // return bindings[i]; + // } + // return bindings[len + index_in_binding_order(T)]; + // ``` + // + std::vector default_binding_type_order; + + TINT_REFLECT(ResourceTableConfig, + resource_table_binding, + storage_buffer_binding, + default_binding_type_order); +}; + +} // namespace tint + +#endif // SRC_TINT_API_COMMON_RESOURCE_TABLE_CONFIG_H_ diff --git a/3rdparty/dawn/src/tint/api/common/resource_type.h b/3rdparty/dawn/src/tint/api/common/resource_type.h new file mode 100644 index 000000000..0d23267fc --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/resource_type.h @@ -0,0 +1,71 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_RESOURCE_TYPE_H_ +#define SRC_TINT_API_COMMON_RESOURCE_TYPE_H_ + +#include "src/tint/utils/reflection.h" + +namespace tint { + +enum class ResourceType : uint32_t { + kEmpty, + + kTexture1d_f32, + kTexture1d_i32, + kTexture1d_u32, + kTexture2d_f32, + kTexture2d_i32, + kTexture2d_u32, + kTexture2dArray_f32, + kTexture2dArray_i32, + kTexture2dArray_u32, + kTexture3d_f32, + kTexture3d_i32, + kTexture3d_u32, + kTextureCube_f32, + kTextureCube_i32, + kTextureCube_u32, + kTextureCubeArray_f32, + kTextureCubeArray_i32, + kTextureCubeArray_u32, + + kTextureMultisampled2d_f32, + kTextureMultisampled2d_i32, + kTextureMultisampled2d_u32, + + kTextureDepth2d, + kTextureDepth2dArray, + kTextureDepthCube, + kTextureDepthCubeArray, + kTextureDepthMultisampled2d, +}; +TINT_REFLECT_ENUM_RANGE(tint::ResourceType, kEmpty, kTextureDepthMultisampled2d); + +} // namespace tint + +#endif // SRC_TINT_API_COMMON_RESOURCE_TYPE_H_ diff --git a/3rdparty/dawn/src/tint/api/common/subgroup_matrix.h b/3rdparty/dawn/src/tint/api/common/subgroup_matrix.h new file mode 100644 index 000000000..653abcb90 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/subgroup_matrix.h @@ -0,0 +1,113 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_SUBGROUP_MATRIX_H_ +#define SRC_TINT_API_COMMON_SUBGROUP_MATRIX_H_ + +#include + +#include "src/tint/utils/math/hash.h" + +#include "src/tint/utils/reflection.h" + +namespace tint { + +enum class SubgroupMatrixType : uint8_t { + kF16 = 0, + kF32, + kU8, + kI8, + kU32, + kI32, +}; +TINT_REFLECT_ENUM_RANGE(tint::SubgroupMatrixType, kF16, kI32); + +struct SubgroupMatrixMultiply { + uint32_t M; + uint32_t N; + uint32_t K; + + SubgroupMatrixType input_type; + SubgroupMatrixType output_type; + + TINT_REFLECT(SubgroupMatrixMultiply, M, N, K, input_type, output_type); + TINT_REFLECT_EQUALS(SubgroupMatrixMultiply); + TINT_REFLECT_HASH_CODE(SubgroupMatrixMultiply); +}; + +enum class SubgroupMatrixDirection : uint8_t { + kLeft, + kRight, + kResult, +}; +TINT_REFLECT_ENUM_RANGE(tint::SubgroupMatrixDirection, kLeft, kResult); + +struct SubgroupMatrixConfig { + uint32_t M; + uint32_t N; + uint32_t K; + + SubgroupMatrixType type; + SubgroupMatrixDirection direction; + + TINT_REFLECT(SubgroupMatrixConfig, M, N, K, type, direction); + TINT_REFLECT_EQUALS(SubgroupMatrixConfig); + TINT_REFLECT_HASH_CODE(SubgroupMatrixConfig); +}; + +} // namespace tint + +template <> +class std::hash { + public: + inline std::size_t operator()(const tint::SubgroupMatrixMultiply& sm) const { + return tint::Hash(sm.M, sm.N, sm.K, sm.input_type, sm.output_type); + } +}; + +template <> +class std::hash { + public: + inline std::size_t operator()(const tint::SubgroupMatrixConfig sm) const { + return tint::Hash(sm.M, sm.N, sm.K, sm.type, sm.direction); + } +}; + +namespace tint { + +struct SubgroupMatrixInfo { + std::unordered_set multiplies; + std::unordered_set configs; + + TINT_REFLECT(SubgroupMatrixInfo, multiplies, configs); + TINT_REFLECT_EQUALS(SubgroupMatrixInfo); + TINT_REFLECT_HASH_CODE(SubgroupMatrixInfo); +}; + +} // namespace tint + +#endif // SRC_TINT_API_COMMON_SUBGROUP_MATRIX_H_ diff --git a/3rdparty/dawn/src/tint/api/common/substitute_overrides_config.h b/3rdparty/dawn/src/tint/api/common/substitute_overrides_config.h new file mode 100644 index 000000000..78db68944 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/substitute_overrides_config.h @@ -0,0 +1,53 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_SUBSTITUTE_OVERRIDES_CONFIG_H_ +#define SRC_TINT_API_COMMON_SUBSTITUTE_OVERRIDES_CONFIG_H_ + +#include + +#include "src/tint/api/common/override_id.h" +#include "src/tint/utils/reflection.h" + +namespace tint { + +/// Configuration options for the transform +struct SubstituteOverridesConfig { + /// The map of override identifier to the override value. + /// The value is always a double coming into the transform and will be + /// converted to the correct type through and initializer. + std::unordered_map map; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(SubstituteOverridesConfig, map); + TINT_REFLECT_EQUALS(SubstituteOverridesConfig); + TINT_REFLECT_HASH_CODE(SubstituteOverridesConfig); +}; + +} // namespace tint + +#endif // SRC_TINT_API_COMMON_SUBSTITUTE_OVERRIDES_CONFIG_H_ diff --git a/3rdparty/dawn/src/tint/api/common/vertex_pulling_config.cc b/3rdparty/dawn/src/tint/api/common/vertex_pulling_config.cc new file mode 100644 index 000000000..92afda564 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/vertex_pulling_config.cc @@ -0,0 +1,44 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/api/common/vertex_pulling_config.h" + +#include + +namespace tint { + +VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor() = default; + +VertexBufferLayoutDescriptor::VertexBufferLayoutDescriptor( + uint32_t in_array_stride, + VertexStepMode in_step_mode, + std::vector in_attributes) + : array_stride(in_array_stride), + step_mode(in_step_mode), + attributes(std::move(in_attributes)) {} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/api/common/vertex_pulling_config.h b/3rdparty/dawn/src/tint/api/common/vertex_pulling_config.h new file mode 100644 index 000000000..58ca1a117 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/common/vertex_pulling_config.h @@ -0,0 +1,148 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_COMMON_VERTEX_PULLING_CONFIG_H_ +#define SRC_TINT_API_COMMON_VERTEX_PULLING_CONFIG_H_ + +#include +#include + +#include "src/tint/utils/reflection.h" + +namespace tint { + +/// Describes the format of data in a vertex buffer. +enum class VertexFormat : uint8_t { + kUint8, // uint8 + kUint8x2, // uint8x2 + kUint8x4, // uint8x4 + kSint8, // sint8 + kSint8x2, // sint8x2 + kSint8x4, // sint8x4 + kUnorm8, // unorm8 + kUnorm8x2, // unorm8x2 + kUnorm8x4, // unorm8x4 + kSnorm8, // snorm8 + kSnorm8x2, // snorm8x2 + kSnorm8x4, // snorm8x4 + kUint16, // uint16 + kUint16x2, // uint16x2 + kUint16x4, // uint16x4 + kSint16, // sint16 + kSint16x2, // sint16x2 + kSint16x4, // sint16x4 + kUnorm16, // unorm16 + kUnorm16x2, // unorm16x2 + kUnorm16x4, // unorm16x4 + kSnorm16, // snorm16 + kSnorm16x2, // snorm16x2 + kSnorm16x4, // snorm16x4 + kFloat16, // float16 + kFloat16x2, // float16x2 + kFloat16x4, // float16x4 + kFloat32, // float32 + kFloat32x2, // float32x2 + kFloat32x3, // float32x3 + kFloat32x4, // float32x4 + kUint32, // uint32 + kUint32x2, // uint32x2 + kUint32x3, // uint32x3 + kUint32x4, // uint32x4 + kSint32, // sint32 + kSint32x2, // sint32x2 + kSint32x3, // sint32x3 + kSint32x4, // sint32x4 + kUnorm10_10_10_2, // unorm10-10-10-2 + kUnorm8x4BGRA, // unorm8x4-bgra +}; + +/// Describes if a vertex attribute increments with vertex index or instance index. +enum class VertexStepMode : uint8_t { kVertex, kInstance }; + +/// Describes a vertex attribute within a buffer +struct VertexAttributeDescriptor { + /// The format of the attribute. + VertexFormat format; + /// The byte offset of the attribute in the buffer. + uint32_t offset; + /// The shader location used for the attribute. + uint32_t shader_location; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(VertexAttributeDescriptor, format, offset, shader_location); + TINT_REFLECT_EQUALS(VertexAttributeDescriptor); + TINT_REFLECT_HASH_CODE(VertexAttributeDescriptor); +}; + +/// Describes a buffer containing multiple vertex attributes +struct VertexBufferLayoutDescriptor { + /// Constructor + VertexBufferLayoutDescriptor(); + /// Constructor + /// @param in_array_stride the array stride in bytes of the in buffer + /// @param in_step_mode the step mode of the in buffer + /// @param in_attributes the in attributes + VertexBufferLayoutDescriptor(uint32_t in_array_stride, + VertexStepMode in_step_mode, + std::vector in_attributes); + /// The array stride in bytes used in the in buffer. + uint32_t array_stride = 0u; + /// The input step mode used. + VertexStepMode step_mode = VertexStepMode::kVertex; + /// The vertex attributes. + std::vector attributes; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(VertexBufferLayoutDescriptor, array_stride, step_mode, attributes); + TINT_REFLECT_EQUALS(VertexBufferLayoutDescriptor); + TINT_REFLECT_HASH_CODE(VertexBufferLayoutDescriptor); +}; + +/// Configuration options that control the vertex pulling transform. +struct VertexPullingConfig { + /// The vertex state descriptor, containing info about attributes. + std::vector vertex_state; + + /// The "group" we will put all our vertex buffers into (as storage buffers). + /// Default to 4 as it is past the limits of user-accessible groups. + uint32_t pulling_group = 4u; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(VertexPullingConfig, vertex_state, pulling_group); + TINT_REFLECT_EQUALS(VertexPullingConfig); + TINT_REFLECT_HASH_CODE(VertexPullingConfig); +}; + +/// Reflection for VertexFormat. +TINT_REFLECT_ENUM_RANGE(tint::VertexFormat, kUint8x2, kUnorm8x4BGRA); + +/// Reflection for VertexStepMode. +TINT_REFLECT_ENUM_RANGE(tint::VertexStepMode, kVertex, kInstance); + +} // namespace tint + +#endif // SRC_TINT_API_COMMON_VERTEX_PULLING_CONFIG_H_ diff --git a/3rdparty/dawn/src/tint/api/helpers/generate_bindings.cc b/3rdparty/dawn/src/tint/api/helpers/generate_bindings.cc new file mode 100644 index 000000000..937daed17 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/helpers/generate_bindings.cc @@ -0,0 +1,174 @@ +/// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/api/helpers/generate_bindings.h" + +#include +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/referenced_module_vars.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint { + +Bindings GenerateBindings(const core::ir::Module& module, + const std::string& ep, + bool set_group_to_zero, + bool flatten_bindings) { + Bindings bindings{}; + + uint32_t next_buffer_idx = 0; + uint32_t next_sampler_idx = 0; + uint32_t next_texture_idx = 0; + + // Collect next valid binding number per group + Hashmap group_to_next_binding_number; + Vector ext_tex_bps; + + core::ir::Function* ep_func = nullptr; + for (auto* f : module.functions) { + if (!f->IsEntryPoint()) { + continue; + } + if (module.NameOf(f).NameView() == ep) { + ep_func = f; + break; + } + } + // No entrypoint, so no bindings needed + if (!ep_func) { + return bindings; + } + + core::ir::ReferencedModuleVars referenced_module_vars{module}; + auto& refs = referenced_module_vars.TransitiveReferences(ep_func); + + for (auto* var : refs) { + auto bp = var->BindingPoint(); + if (!bp.has_value()) { + continue; + } + + if (auto val = group_to_next_binding_number.Get(bp->group)) { + *val = std::max(*val, bp->binding + 1); + } else { + group_to_next_binding_number.Add(bp->group, bp->binding + 1); + } + + auto* ptr = var->Result()->Type()->As(); + + // Store up the external textures, we'll add them in the next step + if (ptr->StoreType()->Is()) { + ext_tex_bps.Push(*bp); + continue; + } + + switch (ptr->AddressSpace()) { + case core::AddressSpace::kHandle: + Switch( + ptr->StoreType(), // + [&](const core::type::Sampler*) { + tint::BindingPoint info{ + .group = set_group_to_zero ? 0 : bp->group, + .binding = flatten_bindings ? next_sampler_idx++ : bp->binding, + }; + bindings.sampler.emplace(*bp, info); + }, + [&](const core::type::StorageTexture*) { + tint::BindingPoint info{ + .group = set_group_to_zero ? 0 : bp->group, + .binding = flatten_bindings ? next_texture_idx++ : bp->binding, + }; + bindings.storage_texture.emplace(*bp, info); + }, + [&](const core::type::Texture*) { + tint::BindingPoint info{ + .group = set_group_to_zero ? 0 : bp->group, + .binding = flatten_bindings ? next_texture_idx++ : bp->binding, + }; + bindings.texture.emplace(*bp, info); + }); + break; + case core::AddressSpace::kStorage: { + tint::BindingPoint info{ + .group = set_group_to_zero ? 0 : bp->group, + .binding = flatten_bindings ? next_buffer_idx++ : bp->binding, + }; + bindings.storage.emplace(*bp, info); + break; + } + case core::AddressSpace::kUniform: { + tint::BindingPoint info{ + .group = set_group_to_zero ? 0 : bp->group, + .binding = flatten_bindings ? next_buffer_idx++ : bp->binding, + }; + bindings.uniform.emplace(*bp, info); + break; + } + case core::AddressSpace::kUndefined: + case core::AddressSpace::kPixelLocal: + case core::AddressSpace::kPrivate: + case core::AddressSpace::kImmediate: + case core::AddressSpace::kIn: + case core::AddressSpace::kOut: + case core::AddressSpace::kFunction: + case core::AddressSpace::kWorkgroup: + break; + } + } + + if (flatten_bindings) { + for (auto bp : ext_tex_bps) { + uint32_t g = set_group_to_zero ? 0 : bp.group; + + tint::BindingPoint plane0{.group = g, .binding = next_texture_idx++}; + tint::BindingPoint plane1{.group = g, .binding = next_texture_idx++}; + tint::BindingPoint metadata{.group = g, .binding = next_buffer_idx++}; + bindings.external_texture.emplace(bp, ExternalTexture{metadata, plane0, plane1}); + } + } else { + for (auto bp : ext_tex_bps) { + uint32_t& next_num = group_to_next_binding_number.GetOrAddZero(bp.group); + uint32_t g = set_group_to_zero ? 0 : bp.group; + + tint::BindingPoint plane0{.group = g, .binding = bp.binding}; + tint::BindingPoint plane1{.group = g, .binding = next_num++}; + tint::BindingPoint metadata{.group = g, .binding = next_num++}; + bindings.external_texture.emplace(bp, ExternalTexture{metadata, plane0, plane1}); + } + } + + return bindings; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/api/helpers/generate_bindings.h b/3rdparty/dawn/src/tint/api/helpers/generate_bindings.h new file mode 100644 index 000000000..987852202 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/helpers/generate_bindings.h @@ -0,0 +1,54 @@ +/// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_HELPERS_GENERATE_BINDINGS_H_ +#define SRC_TINT_API_HELPERS_GENERATE_BINDINGS_H_ + +#include + +#include "src/tint/api/common/bindings.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint { + +/// Generate the resource bindings +/// @param module the module to generate from +/// @param set_group_to_zero if true, the group used for bindings will always be zero +/// @param flatten_bindings if true, the bindings will remap to count from 0 +/// @returns the bindings +Bindings GenerateBindings(const core::ir::Module& module, + const std::string& ep, + bool set_group_to_zero, + bool flatten_bindings); + +} // namespace tint + +#endif // SRC_TINT_API_HELPERS_GENERATE_BINDINGS_H_ diff --git a/3rdparty/dawn/src/tint/api/tint.cc b/3rdparty/dawn/src/tint/api/tint.cc new file mode 100644 index 000000000..1f95b1ba4 --- /dev/null +++ b/3rdparty/dawn/src/tint/api/tint.cc @@ -0,0 +1,116 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/api/tint.h" + +//////////////////////////////////////////////////////////////////////////////// +// The following includes are used by './tools/run gen' to add an implicit +// dependency from 'tint/api' to the libraries used to make up the Tint API. +//////////////////////////////////////////////////////////////////////////////// +// IWYU pragma: begin_keep +#include "src/tint/api/common/override_id.h" + +#if TINT_BUILD_GLSL_WRITER +#include "src/tint/lang/glsl/writer/writer.h" // nogncheck +#endif + +#if TINT_BUILD_HLSL_WRITER +#include "src/tint/lang/hlsl/writer/writer.h" // nogncheck +#endif + +#if TINT_BUILD_MSL_WRITER +#include "src/tint/lang/msl/writer/writer.h" // nogncheck +#endif + +#if TINT_BUILD_SPV_READER +#include "src/tint/lang/spirv/reader/reader.h" // nogncheck +#endif + +#if TINT_BUILD_SPV_WRITER +#include "src/tint/lang/spirv/writer/writer.h" // nogncheck +#endif + +#if TINT_BUILD_WGSL_READER +#include "src/tint/lang/wgsl/inspector/inspector.h" // nogncheck +#include "src/tint/lang/wgsl/reader/reader.h" // nogncheck +#endif + +#if TINT_BUILD_WGSL_WRITER +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/writer/writer.h" // nogncheck +#endif + +#if TINT_BUILD_NULL_WRITER +#include "src/tint/lang/null/writer/writer.h" // nogncheck +#endif + +// IWYU pragma: end_keep + +#if TINT_BUILD_SPV_READER && TINT_BUILD_WGSL_WRITER +#include "src/tint/lang/core/ir/module.h" +#endif + +namespace tint { + +/// Initialize initializes the Tint library. Call before using the Tint API. +void Initialize() { +#if TINT_BUILD_WGSL_WRITER + // Register the Program printer. This is used for debugging purposes. + tint::Program::printer = [](const tint::Program& program) { + auto result = wgsl::writer::Generate(program); + if (result != Success) { + return result.Failure().reason; + } + return result->wgsl; + }; +#endif +} + +/// Shutdown uninitializes the Tint library. Call after using the Tint API. +void Shutdown() { + // Currently no-op, but may release tint resources in the future. +} + +Result SpirvToWgsl([[maybe_unused]] const std::vector& spirv, + [[maybe_unused]] const wgsl::writer::Options& wgsl_options) { +#if !TINT_BUILD_SPV_READER + return Failure{"Tint SPIR-V reader is not enabled"}; +#elif !TINT_BUILD_WGSL_WRITER + return Failure{"Tint WGSL writer is not enabled"}; +#else + // Convert the SPIR-V program to an IR module. + TINT_CHECK_RESULT_UNWRAP(ir_from_spirv, tint::spirv::reader::ReadIR(spirv)); + + // Convert the IR module to WGSL. + TINT_CHECK_RESULT_UNWRAP(wgsl_from_ir, + tint::wgsl::writer::WgslFromIR(ir_from_spirv, wgsl_options)); + + return wgsl_from_ir.wgsl; +#endif // TINT_BUILD_SPV_READER && TINT_BUILD_WGSL_WRITER +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/api/tint.h b/3rdparty/dawn/src/tint/api/tint.h new file mode 100644 index 000000000..930c6fa8f --- /dev/null +++ b/3rdparty/dawn/src/tint/api/tint.h @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_API_TINT_H_ +#define SRC_TINT_API_TINT_H_ + +#include +#include +#include + +#include "src/tint/lang/wgsl/writer/common/options.h" +#include "src/tint/utils/result.h" + +namespace tint { + +/// Initialize initializes the Tint library. Call before using the Tint API. +void Initialize(); + +/// Shutdown uninitializes the Tint library. Call after using the Tint API. +void Shutdown(); + +/// Convert a SPIR-V binary to a WGSL shader module string. +/// @param spirv the SPIR-V binary +/// @param wgsl_options the options to use for generating WGSL +/// @returns the WGSL module, or a failure +tint::Result SpirvToWgsl(const std::vector& spirv, + const wgsl::writer::Options& wgsl_options = {}); + +} // namespace tint + +#endif // SRC_TINT_API_TINT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/binary_op.cc b/3rdparty/dawn/src/tint/lang/core/binary_op.cc new file mode 100644 index 000000000..c73eba918 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/binary_op.cc @@ -0,0 +1,74 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/binary_op.h" + +namespace tint::core { + +std::string_view ToString(BinaryOp value) { + switch (value) { + case BinaryOp::kAnd: + return "&"; + case BinaryOp::kOr: + return "|"; + case BinaryOp::kXor: + return "^"; + case BinaryOp::kLogicalAnd: + return "&&"; + case BinaryOp::kLogicalOr: + return "||"; + case BinaryOp::kEqual: + return "=="; + case BinaryOp::kNotEqual: + return "!="; + case BinaryOp::kLessThan: + return "<"; + case BinaryOp::kGreaterThan: + return ">"; + case BinaryOp::kLessThanEqual: + return "<="; + case BinaryOp::kGreaterThanEqual: + return ">="; + case BinaryOp::kShiftLeft: + return "<<"; + case BinaryOp::kShiftRight: + return ">>"; + case BinaryOp::kAdd: + return "+"; + case BinaryOp::kSubtract: + return "-"; + case BinaryOp::kMultiply: + return "*"; + case BinaryOp::kDivide: + return "/"; + case BinaryOp::kModulo: + return "%"; + } + return ""; +} + +} // namespace tint::core diff --git a/3rdparty/dawn/src/tint/lang/core/binary_op.h b/3rdparty/dawn/src/tint/lang/core/binary_op.h new file mode 100644 index 000000000..c73416d00 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/binary_op.h @@ -0,0 +1,72 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_BINARY_OP_H_ +#define SRC_TINT_LANG_CORE_BINARY_OP_H_ + +#include "src/tint/utils/rtti/traits.h" + +namespace tint::core { + +/// An enumerator of binary operators. +enum class BinaryOp { + kAnd, // & + kOr, // | + kXor, + kLogicalAnd, // && + kLogicalOr, // || + kEqual, + kNotEqual, + kLessThan, + kGreaterThan, + kLessThanEqual, + kGreaterThanEqual, + kShiftLeft, + kShiftRight, + kAdd, + kSubtract, + kMultiply, + kDivide, + kModulo, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(BinaryOp value); + +/// @param out the stream to write to +/// @param value the BinaryOp +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, BinaryOp value) { + return out << ToString(value); +} + +} // namespace tint::core + +#endif // SRC_TINT_LANG_CORE_BINARY_OP_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/clone_context.h b/3rdparty/dawn/src/tint/lang/core/constant/clone_context.h new file mode 100644 index 000000000..7d909b659 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/clone_context.h @@ -0,0 +1,51 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_CLONE_CONTEXT_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_CLONE_CONTEXT_H_ + +#include "src/tint/lang/core/type/clone_context.h" + +// Forward declarations +namespace tint::core::constant { +class Manager; +} // namespace tint::core::constant + +namespace tint::core::constant { + +/// Context information for cloning of constants +struct CloneContext { + /// The context for cloning type information + core::type::CloneContext type_ctx; + + /// Destination information + constant::Manager& dst; +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_CLONE_CONTEXT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/composite.cc b/3rdparty/dawn/src/tint/lang/core/constant/composite.cc new file mode 100644 index 000000000..fe8ba19c8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/composite.cc @@ -0,0 +1,58 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/composite.h" + +#include + +#include "src/tint/lang/core/constant/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Composite); + +namespace tint::core::constant { + +Composite::Composite(const core::type::Type* t, VectorRef els, bool all_0, bool any_0) + : type(t), elements(std::move(els)), all_zero(all_0), any_zero(any_0), hash(CalcHash()) { + const size_t n = elements.Length(); + TINT_ASSERT(n == t->Elements().count); + for (size_t i = 0; i < n; i++) { + TINT_ASSERT(t->Element(static_cast(i)) == elements[i]->Type()); + } +} + +Composite::~Composite() = default; + +const Composite* Composite::Clone(CloneContext& ctx) const { + auto* ty = type->Clone(ctx.type_ctx); + Vector els; + for (const auto* el : elements) { + els.Push(el->Clone(ctx)); + } + return ctx.dst.Get(ty, std::move(els), all_zero, any_zero); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/composite.h b/3rdparty/dawn/src/tint/lang/core/constant/composite.h new file mode 100644 index 000000000..1b359febc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/composite.h @@ -0,0 +1,106 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_COMPOSITE_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_COMPOSITE_H_ + +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// Composite holds a number of mixed child values. +/// Composite may be of a vector, matrix, array or structure type. +/// If each element is the same type and value, then a Splat would be a more efficient constant +/// implementation. Use CreateComposite() to create the appropriate type. +class Composite : public Castable { + public: + /// Constructor + /// @param t the compsite type + /// @param els the composite elements + /// @param all_0 true if all elements are 0 + /// @param any_0 true if any element is 0 + Composite(const core::type::Type* t, VectorRef els, bool all_0, bool any_0); + ~Composite() override; + + /// @copydoc Value::Type() + const core::type::Type* Type() const override { return type; } + + /// @copydoc Value::Index() + const Value* Index(size_t i) const override { + return i < elements.Length() ? elements[i] : nullptr; + } + + /// @copydoc Value::NumElements() + size_t NumElements() const override { return elements.Length(); } + + /// @copydoc Value::AllZero() + bool AllZero() const override { return all_zero; } + + /// @copydoc Value::AnyZero() + bool AnyZero() const override { return any_zero; } + + /// @copydoc Value::Hash() + HashCode Hash() const override { return hash; } + + /// Clones the constant into the provided context + /// @param ctx the clone context + /// @returns the cloned node + const Composite* Clone(CloneContext& ctx) const override; + + /// The composite type + core::type::Type const* const type; + /// The composite elements + const Vector elements; + /// True if all elements are zero + const bool all_zero; + /// True if any element is zero + const bool any_zero; + /// The hash of the composite + const HashCode hash; + + protected: + /// @copydoc Value::InternalValue() + std::variant InternalValue() const override { return {}; } + + private: + HashCode CalcHash() { + auto h = tint::Hash(type, all_zero, any_zero); + for (auto* el : elements) { + h = HashCombine(h, el->Hash()); + } + return h; + } +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_COMPOSITE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/eval.cc b/3rdparty/dawn/src/tint/lang/core/constant/eval.cc new file mode 100644 index 000000000..d948b84ab --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/eval.cc @@ -0,0 +1,3727 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/eval.h" + +#include +#include +#include +#include +#include +#include + +#include "src/tint/lang/core/constant/composite.h" +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/constant/splat.h" +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/containers/map.h" +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/memory/bitcast.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/string_stream.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::constant { +namespace { + +/// Returns the first element of a parameter pack +template +T First(T&& first, ...) { + return std::forward(first); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_iu32(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::I32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::U32*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_ia_iu32(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::AbstractInt*) { return f(cs->template ValueAs()...); }, + [&](const core::type::I32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::U32*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_ia_iu32_bool(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::AbstractInt*) { return f(cs->template ValueAs()...); }, + [&](const core::type::I32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::U32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::Bool*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_fia_fi32_f16(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::AbstractInt*) { return f(cs->template ValueAs()...); }, + [&](const core::type::AbstractFloat*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::I32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F16*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_fia_fiu32_f16(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::AbstractInt*) { return f(cs->template ValueAs()...); }, + [&](const core::type::AbstractFloat*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::I32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::U32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F16*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_fia_fiu32_f16_bool(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::AbstractInt*) { return f(cs->template ValueAs()...); }, + [&](const core::type::AbstractFloat*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::I32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::U32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F16*) { return f(cs->template ValueAs()...); }, + [&](const core::type::Bool*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_fa_f32_f16(F&& f, CONSTANTS&&... cs) { + return Switch( + First(cs...)->Type(), // + [&](const core::type::AbstractFloat*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F32*) { return f(cs->template ValueAs()...); }, + [&](const core::type::F16*) { return f(cs->template ValueAs()...); }); +} + +/// Helper that calls `f` passing in the value of all `cs`. +/// Calls `f` with all constants cast to the type of the first `cs` argument. +template +auto Dispatch_bool(F&& f, CONSTANTS&&... cs) { + return f(cs->template ValueAs()...); +} + +/// ZeroTypeDispatch is a helper for calling the function `f`, passing a single zero-value argument +/// of the C++ type that corresponds to the core::type::Type `type`. For example, calling +/// `ZeroTypeDispatch()` with a type of `type::I32*` will call the function f with a single argument +/// of `i32(0)`. +/// @returns the value returned by calling `f`. +/// @note `type` must be a scalar or abstract numeric type. Other types will not call `f`, and will +/// return the zero-initialized value of the return type for `f`. +template +auto ZeroTypeDispatch(const core::type::Type* type, F&& f) { + return Switch( + type, // + [&](const core::type::AbstractInt*) { return f(AInt(0)); }, // + [&](const core::type::AbstractFloat*) { return f(AFloat(0)); }, // + [&](const core::type::I32*) { return f(i32(0)); }, // + [&](const core::type::U32*) { return f(u32(0)); }, // + [&](const core::type::F32*) { return f(f32(0)); }, // + [&](const core::type::F16*) { return f(f16(0)); }, // + [&](const core::type::Bool*) { return f(static_cast(0)); }); +} + +template +std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs) { + StringStream ss; + ss << "'" << lhs.value << " " << op << " " << rhs.value << "' cannot be represented as '" + << FriendlyName() << "'"; + return ss.str(); +} + +template +std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) { + StringStream ss; + ss << "value " << value << " cannot be represented as " << "'" << target_ty << "'"; + return ss.str(); +} + +template +std::string OverflowExpErrorMessage(std::string_view base, NumberT exp) { + StringStream ss; + ss << base << "^" << exp << " cannot be represented as " << "'" << FriendlyName() + << "'"; + return ss.str(); +} + +/// @returns the number of consecutive leading bits in `@p e` set to `@p bit_value_to_count`. +template +std::make_unsigned_t CountLeadingBits(T e, T bit_value_to_count) { + using UT = std::make_unsigned_t; + constexpr UT kNumBits = sizeof(UT) * 8; + constexpr UT kLeftMost = UT{1} << (kNumBits - 1); + const UT b = bit_value_to_count == 0 ? UT{0} : kLeftMost; + + auto v = static_cast(e); + auto count = UT{0}; + while ((count < kNumBits) && ((v & kLeftMost) == b)) { + ++count; + v <<= 1; + } + return count; +} + +/// @returns the number of consecutive trailing bits set to `@p bit_value_to_count` in `@p e` +template +std::make_unsigned_t CountTrailingBits(T e, T bit_value_to_count) { + using UT = std::make_unsigned_t; + constexpr UT kNumBits = sizeof(UT) * 8; + constexpr UT kRightMost = UT{1}; + const UT b = static_cast(bit_value_to_count); + + auto v = static_cast(e); + auto count = UT{0}; + while ((count < kNumBits) && ((v & kRightMost) == b)) { + ++count; + v >>= 1; + } + return count; +} + +/// Common data for constant conversion. +struct ConvertContext { + Manager& mgr; + diag::List& diags; + const Source& source; + bool use_runtime_semantics; +}; + +/// Converts the constant scalar value to the target type. +/// @returns the converted scalar, or nullptr on error. +template +const ScalarBase* ScalarConvert(const Scalar* scalar, + const core::type::Type* target_ty, + ConvertContext& ctx) { + TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE); + if (target_ty == scalar->type) { + // If the types are identical, then no conversion is needed. + return scalar; + } + return ZeroTypeDispatch(target_ty, [&](auto zero_to) -> const ScalarBase* { + // `value` is the source value. + // `FROM` is the source type. + // `TO` is the target type. + using TO = std::decay_t; + using FROM = T; + if constexpr (std::is_same_v) { + // [x -> bool] + return ctx.mgr.Get>(target_ty, !scalar->IsZero()); + } else if constexpr (std::is_same_v) { + // [bool -> x] + return ctx.mgr.Get>(target_ty, TO(scalar->value ? 1 : 0)); + } else if (auto conv = CheckedConvert(scalar->value); conv == Success) { + // Conversion success + return ctx.mgr.Get>(target_ty, conv.Get()); + // --- Below this point are the failure cases --- + } else if constexpr (IsAbstract) { + // [abstract-numeric -> x] - materialization failure + auto msg = OverflowErrorMessage(scalar->value, target_ty->FriendlyName()); + if (ctx.use_runtime_semantics) { + ctx.diags.AddWarning(ctx.source) << msg; + switch (conv.Failure()) { + case ConversionFailure::kExceedsNegativeLimit: + return ctx.mgr.Get>(target_ty, TO::Lowest()); + case ConversionFailure::kExceedsPositiveLimit: + return ctx.mgr.Get>(target_ty, TO::Highest()); + } + } else { + ctx.diags.AddError(ctx.source) << msg; + return nullptr; + } + } else if constexpr (IsFloatingPoint) { + // [x -> floating-point] - number not exactly representable + // https://www.w3.org/TR/WGSL/#floating-point-conversion + auto msg = OverflowErrorMessage(scalar->value, target_ty->FriendlyName()); + if (ctx.use_runtime_semantics) { + ctx.diags.AddWarning(ctx.source) << msg; + switch (conv.Failure()) { + case ConversionFailure::kExceedsNegativeLimit: + return ctx.mgr.Get>(target_ty, TO::Lowest()); + case ConversionFailure::kExceedsPositiveLimit: + return ctx.mgr.Get>(target_ty, TO::Highest()); + } + } else { + ctx.diags.AddError(ctx.source) << msg; + return nullptr; + } + } else if constexpr (IsFloatingPoint) { + // [floating-point -> integer] - number not exactly representable + // https://www.w3.org/TR/WGSL/#floating-point-conversion + switch (conv.Failure()) { + case ConversionFailure::kExceedsNegativeLimit: + return ctx.mgr.Get>(target_ty, TO::Lowest()); + case ConversionFailure::kExceedsPositiveLimit: + return ctx.mgr.Get>(target_ty, TO::Highest()); + } + } else if constexpr (IsIntegral) { + // [integer -> integer] - number not exactly representable + // Static cast + return ctx.mgr.Get>(target_ty, static_cast(scalar->value)); + } + TINT_UNREACHABLE() << "Expression is not constant"; + return nullptr; + }); + TINT_END_DISABLE_WARNING(UNREACHABLE_CODE); +} + +/// Converts the constant value to the target type. +/// @returns the converted value, or nullptr on error. +const Value* ConvertInternal(const Value* root_value, + const core::type::Type* root_target_ty, + ConvertContext& ctx) { + struct ActionConvert { + const Value* value = nullptr; + const core::type::Type* target_ty = nullptr; + }; + struct ActionBuildSplat { + size_t count = 0; + const core::type::Type* type = nullptr; + }; + struct ActionBuildComposite { + size_t count = 0; + const core::type::Type* type = nullptr; + }; + using Action = std::variant; + + Vector pending{ + ActionConvert{root_value, root_target_ty}, + }; + + Vector value_stack; + + while (!pending.IsEmpty()) { + auto next = pending.Pop(); + + if (auto* build = std::get_if(&next)) { + TINT_ASSERT(value_stack.Length() >= 1); + auto* el = value_stack.Pop(); + value_stack.Push(ctx.mgr.Splat(build->type, el)); + continue; + } + + if (auto* build = std::get_if(&next)) { + TINT_ASSERT(value_stack.Length() >= build->count); + // Take build->count elements off the top of value_stack + // Note: The values are ordered with the first composite value at the top of the stack. + Vector elements; + elements.Reserve(build->count); + for (size_t i = 0; i < build->count; i++) { + elements.Push(value_stack.Pop()); + } + // Build the composite + value_stack.Push(ctx.mgr.Composite(build->type, std::move(elements))); + continue; + } + + auto* convert = std::get_if(&next); + + bool ok = Switch( + convert->value, + [&](const ScalarBase* scalar) { + auto* converted = Switch( + scalar, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }, + [&](const Scalar* val) { + return ScalarConvert(val, convert->target_ty, ctx); + }); + if (!converted) { + return false; + } + value_stack.Push(converted); + return true; + }, + [&](const Splat* splat) { + const core::type::Type* target_el_ty = nullptr; + if (auto* str = convert->target_ty->As()) { + // Structure conversion. + auto members = str->Members(); + target_el_ty = members[0]->Type(); + + // Structures can only be converted during materialization. The user cannot + // declare the target structure type, so each member type must be the same + // default materialization type. + for (size_t i = 1; i < members.Length(); i++) { + TINT_ASSERT(members[i]->Type() == target_el_ty) + << "inconsistent target struct member types for SplatConvert"; + } + } else { + target_el_ty = convert->target_ty->Elements(convert->target_ty).type; + } + + // Convert the single splatted element type. + pending.Push(ActionBuildSplat{splat->count, convert->target_ty}); + pending.Push(ActionConvert{splat->el, target_el_ty}); + return true; + }, + [&](const Composite* composite) { + const size_t el_count = composite->NumElements(); + + // Build the new composite from the converted element types. + pending.Push(ActionBuildComposite{el_count, convert->target_ty}); + + if (auto* str = convert->target_ty->As()) { + TINT_ASSERT(str->Members().Length() == el_count) + << "const-eval conversion of structure has mismatched element counts"; + + // Struct composites can have different types for each member. + auto members = str->Members(); + for (size_t i = 0; i < el_count; i++) { + pending.Push(ActionConvert{composite->Index(i), members[i]->Type()}); + } + } else { + // Non-struct composites have the same type for all elements. + auto* el_ty = convert->target_ty->Elements(convert->target_ty).type; + for (size_t i = 0; i < el_count; i++) { + auto* el = composite->Index(i); + pending.Push(ActionConvert{el, el_ty}); + } + } + + return true; + }); + if (!ok) { + return nullptr; + } + } + + TINT_ASSERT(value_stack.Length() == 1); + return value_stack.Pop(); +} + +/// TransformElements constructs a new constant of type `composite_ty` by applying the +/// transformation function `f` on each of the most deeply nested elements of 'cs'. Assumes that all +/// input constants `cs` are of the same arity (all scalars or all vectors of the same size). +/// If `f`'s last argument is a `size_t`, then the index of the most deeply nested element inside +/// the most deeply nested aggregate type will be passed in. +template +std::enable_if_t>, Eval::Result> +TransformElements(Manager& mgr, + const core::type::Type* composite_ty, + const F& f, + size_t index, + CONSTANTS&&... cs) { + auto [el_ty, n] = First(cs...)->Type()->Elements(); + if (!el_ty) { + return f(cs..., index); + } + + auto* composite_el_ty = composite_ty->Elements(composite_ty).type; + + Vector els; + els.Reserve(n); + for (uint32_t i = 0; i < n; i++) { + TINT_CHECK_RESULT_UNWRAP( + el, TransformElements(mgr, composite_el_ty, f, index + i, cs->Index(i)...)); + els.Push(el); + } + return mgr.Composite(composite_ty, std::move(els)); +} + +/// Signature of a unary transformation callback +using UnaryTransform = std::function; + +/// TransformUnaryElements constructs a new constant of type `composite_ty` by applying the +/// transformation function 'f' on each of the most deeply nested elements of `c0`. +Eval::Result TransformUnaryElements(Manager& mgr, + const core::type::Type* composite_ty, + const UnaryTransform& f, + const Value* c0) { + auto [el_ty, n] = c0->Type()->Elements(); + if (!el_ty) { + return f(c0); + } + + auto* composite_el_ty = composite_ty->Elements(composite_ty).type; + + Vector els; + els.Reserve(n); + for (uint32_t i = 0; i < n; i++) { + TINT_CHECK_RESULT_UNWRAP(el, TransformUnaryElements(mgr, composite_el_ty, f, c0->Index(i))); + els.Push(el); + } + return mgr.Composite(composite_ty, std::move(els)); +} + +/// Signature of a binary transformation callback. +using BinaryTransform = std::function; + +/// TransformBinaryElements constructs a new constant of type `composite_ty` by applying the +/// transformation function 'f' on each of the most deeply nested elements of both `c0` and `c1`. +Eval::Result TransformBinaryElements(Manager& mgr, + const core::type::Type* composite_ty, + const BinaryTransform& f, + const Value* c0, + const Value* c1) { + auto [el_ty, n] = c0->Type()->Elements(); + if (!el_ty) { + return f(c0, c1); + } + + TINT_ASSERT(n == c1->Type()->Elements().count); + + auto* composite_el_ty = composite_ty->Elements(composite_ty).type; + + Vector els; + els.Reserve(n); + for (uint32_t i = 0; i < n; i++) { + TINT_CHECK_RESULT_UNWRAP( + el, TransformBinaryElements(mgr, composite_el_ty, f, c0->Index(i), c1->Index(i))); + els.Push(el); + } + return mgr.Composite(composite_ty, std::move(els)); +} + +/// TransformBinaryDifferingArityElements constructs a new constant of type `composite_ty` by +/// applying the transformation function 'f' on each of the most deeply nested elements of both `c0` +/// and `c1`. Unlike TransformElements, this function handles the constants being of different +/// arity, e.g. vector-scalar, scalar-vector. +Eval::Result TransformBinaryDifferingArityElements(Manager& mgr, + const core::type::Type* composite_ty, + const BinaryTransform& f, + const Value* c0, + const Value* c1) { + uint32_t n0 = c0->Type()->Elements(nullptr, 1).count; + uint32_t n1 = c1->Type()->Elements(nullptr, 1).count; + uint32_t max_n = std::max(n0, n1); + // If arity of both constants is 1, invoke callback + if (max_n == 1u) { + return f(c0, c1); + } + + const auto* element_ty = composite_ty->Elements(composite_ty).type; + + Vector els; + els.Reserve(max_n); + for (uint32_t i = 0; i < max_n; i++) { + auto nested_or_self = [&](auto* c, uint32_t num_elems) { + return (num_elems == 1) ? c : c->Index(i); + }; + TINT_CHECK_RESULT_UNWRAP( + el, TransformBinaryDifferingArityElements(mgr, element_ty, f, nested_or_self(c0, n0), + nested_or_self(c1, n1))); + els.Push(el); + } + return mgr.Composite(composite_ty, std::move(els)); +} + +/// Signature of a ternary transformation callback +using TernaryTransform = std::function; + +/// TransformTernaryElements constructs a new constant of type `composite_ty` by applying the +/// transformation function 'f' on each of the most deeply nested elements of both `c0`, `c1`, and +/// `c2`. +Eval::Result TransformTernaryElements(Manager& mgr, + const core::type::Type* composite_ty, + const TernaryTransform& f, + const Value* c0, + const Value* c1, + const Value* c2) { + auto [el_ty, n] = c0->Type()->Elements(); + if (!el_ty) { + return f(c0, c1, c2); + } + + auto* composite_el_ty = composite_ty->Elements(composite_ty).type; + + Vector els; + els.Reserve(n); + for (uint32_t i = 0; i < n; i++) { + TINT_CHECK_RESULT_UNWRAP(el, TransformTernaryElements(mgr, composite_el_ty, f, c0->Index(i), + c1->Index(i), c2->Index(i))); + els.Push(el); + } + return mgr.Composite(composite_ty, std::move(els)); +} + +/// @returns the nth byte of an integer value +template +constexpr R GetNthByte(I num, size_t n) { + return static_cast((num >> (8 * n)) & 0xff); +} + +constexpr int8_t (*GetNthSignedByte)(uint32_t, size_t) = &GetNthByte; +constexpr uint8_t (*GetNthUnsignedByte)(uint32_t, size_t) = &GetNthByte; + +} // namespace + +Eval::Eval(Manager& manager, diag::List& diagnostics, bool use_runtime_semantics /* = false */) + : mgr(manager), diags(diagnostics), use_runtime_semantics_(use_runtime_semantics) {} + +template +Eval::Result Eval::CreateScalar(const Source& source, const core::type::Type* t, T v) { + static_assert(IsNumber || std::is_same_v, "T must be a Number or bool"); + TINT_ASSERT(t->Is()); + + if constexpr (IsFloatingPoint) { + if (!std::isfinite(v.value)) { + AddError(source) << OverflowErrorMessage(v, t->FriendlyName()); + if (use_runtime_semantics_) { + return mgr.Zero(t); + } + return Failure(); + } + } + return mgr.Get>(t, v); +} + +template +tint::Result Eval::Add(const Source& source, NumberT a, NumberT b) { + NumberT result; + if constexpr (IsAbstract || IsFloatingPoint) { + if (auto r = CheckedAdd(a, b)) { + result = r->value; + } else { + AddError(source) << OverflowErrorMessage(a, "+", b); + if (use_runtime_semantics_) { + return NumberT{0}; + } + return Failure(); + } + } else { + using T = UnwrapNumber; + auto add_values = [](T lhs, T rhs) { + if constexpr (std::is_integral_v && std::is_signed_v) { + // Ensure no UB for signed overflow + using UT = std::make_unsigned_t; + return static_cast(static_cast(lhs) + static_cast(rhs)); + } else { + return lhs + rhs; + } + }; + result = add_values(a.value, b.value); + } + return result; +} + +template +tint::Result Eval::Sub(const Source& source, NumberT a, NumberT b) { + NumberT result; + if constexpr (IsAbstract || IsFloatingPoint) { + if (auto r = CheckedSub(a, b)) { + result = r->value; + } else { + AddError(source) << OverflowErrorMessage(a, "-", b); + if (use_runtime_semantics_) { + return NumberT{0}; + } else { + return Failure(); + } + } + } else { + using T = UnwrapNumber; + auto sub_values = [](T lhs, T rhs) { + if constexpr (std::is_integral_v && std::is_signed_v) { + // Ensure no UB for signed overflow + using UT = std::make_unsigned_t; + return static_cast(static_cast(lhs) - static_cast(rhs)); + } else { + return lhs - rhs; + } + }; + result = sub_values(a.value, b.value); + } + return result; +} + +template +tint::Result Eval::Mul(const Source& source, NumberT a, NumberT b) { + using T = UnwrapNumber; + NumberT result; + if constexpr (IsAbstract || IsFloatingPoint) { + if (auto r = CheckedMul(a, b)) { + result = r->value; + } else { + AddError(source) << OverflowErrorMessage(a, "*", b); + if (use_runtime_semantics_) { + return NumberT{0}; + } + return Failure(); + } + } else { + auto mul_values = [](T lhs, T rhs) { + if constexpr (std::is_integral_v && std::is_signed_v) { + // For signed integrals, avoid C++ UB by multiplying as unsigned + using UT = std::make_unsigned_t; + return static_cast(static_cast(lhs) * static_cast(rhs)); + } else { + return lhs * rhs; + } + }; + result = mul_values(a.value, b.value); + } + return result; +} + +template +tint::Result Eval::Div(const Source& source, NumberT a, NumberT b) { + NumberT result; + if constexpr (IsAbstract || IsFloatingPoint) { + if (auto r = CheckedDiv(a, b)) { + result = r->value; + } else { + AddError(source) << OverflowErrorMessage(a, "/", b); + if (use_runtime_semantics_) { + return a; + } + return Failure(); + } + } else { + using T = UnwrapNumber; + auto lhs = a.value; + auto rhs = b.value; + if (rhs == 0) { + // For integers (as for floats), lhs / 0 is an error + AddError(source) << OverflowErrorMessage(a, "/", b); + if (use_runtime_semantics_) { + return a; + } + return Failure(); + } + if constexpr (std::is_signed_v) { + // For signed integers, lhs / -1 where lhs is the + // most negative value is an error + if (rhs == -1 && lhs == std::numeric_limits::min()) { + AddError(source) << OverflowErrorMessage(a, "/", b); + if (use_runtime_semantics_) { + return a; + } + return Failure(); + } + } + result = lhs / rhs; + } + return result; +} + +template +tint::Result Eval::Mod(const Source& source, NumberT a, NumberT b) { + NumberT result; + if constexpr (IsAbstract || IsFloatingPoint) { + if (auto r = CheckedMod(a, b)) { + result = r->value; + } else { + AddError(source) << OverflowErrorMessage(a, "%", b); + if (use_runtime_semantics_) { + return NumberT{0}; + } + return Failure(); + } + } else { + using T = UnwrapNumber; + auto lhs = a.value; + auto rhs = b.value; + if (rhs == 0) { + // lhs % 0 is an error + AddError(source) << OverflowErrorMessage(a, "%", b); + if (use_runtime_semantics_) { + return NumberT{0}; + } + return Failure(); + } + if constexpr (std::is_signed_v) { + // For signed integers, lhs % -1 where lhs is the + // most negative value is an error + if (rhs == -1 && lhs == std::numeric_limits::min()) { + AddError(source) << OverflowErrorMessage(a, "%", b); + if (use_runtime_semantics_) { + return NumberT{0}; + } + return Failure(); + } + } + result = lhs % rhs; + } + return result; +} + +template +tint::Result Eval::Dot2(const Source& source, + NumberT a1, + NumberT a2, + NumberT b1, + NumberT b2) { + TINT_CHECK_RESULT_UNWRAP(r1, Mul(source, a1, b1)); + TINT_CHECK_RESULT_UNWRAP(r2, Mul(source, a2, b2)); + return Add(source, r1, r2); +} + +template +tint::Result Eval::Dot3(const Source& source, + NumberT a1, + NumberT a2, + NumberT a3, + NumberT b1, + NumberT b2, + NumberT b3) { + TINT_CHECK_RESULT_UNWRAP(i1, Mul(source, a1, b1)); + TINT_CHECK_RESULT_UNWRAP(i2, Mul(source, a2, b2)); + TINT_CHECK_RESULT_UNWRAP(i3, Mul(source, a3, b3)); + TINT_CHECK_RESULT_UNWRAP(r1, Add(source, i1, i2)); + return Add(source, r1, i3); +} + +template +tint::Result Eval::Dot4(const Source& source, + NumberT a1, + NumberT a2, + NumberT a3, + NumberT a4, + NumberT b1, + NumberT b2, + NumberT b3, + NumberT b4) { + TINT_CHECK_RESULT_UNWRAP(i1, Mul(source, a1, b1)); + TINT_CHECK_RESULT_UNWRAP(i2, Mul(source, a2, b2)); + TINT_CHECK_RESULT_UNWRAP(i3, Mul(source, a3, b3)); + TINT_CHECK_RESULT_UNWRAP(i4, Mul(source, a4, b4)); + TINT_CHECK_RESULT_UNWRAP(r1, Add(source, i1, i2)); + TINT_CHECK_RESULT_UNWRAP(r2, Add(source, r1, i3)); + return Add(source, r2, i4); +} + +template +tint::Result Eval::Det2(const Source& source, NumberT a, NumberT b, NumberT c, NumberT d) { + // | a c | + // | b d | + // + // = + // + // a * d - c * b + + TINT_CHECK_RESULT_UNWRAP(r1, Mul(source, a, d)); + TINT_CHECK_RESULT_UNWRAP(r2, Mul(source, c, b)); + return Sub(source, r1, r2); +} + +template +tint::Result Eval::Det3(const Source& source, + NumberT a, + NumberT b, + NumberT c, + NumberT d, + NumberT e, + NumberT f, + NumberT g, + NumberT h, + NumberT i) { + // | a d g | + // | b e h | + // | c f i | + // + // = + // + // a | e h | - d | b h | + g | b e | + // | f i | | c i | | c f | + + TINT_CHECK_RESULT_UNWRAP(det1, Det2(source, e, f, h, i)); + TINT_CHECK_RESULT_UNWRAP(a_det1, Mul(source, a, det1)); + + TINT_CHECK_RESULT_UNWRAP(det2, Det2(source, b, c, h, i)); + TINT_CHECK_RESULT_UNWRAP(d_det2, Mul(source, d, det2)); + + TINT_CHECK_RESULT_UNWRAP(det3, Det2(source, b, c, e, f)); + TINT_CHECK_RESULT_UNWRAP(g_det3, Mul(source, g, det3)); + + TINT_CHECK_RESULT_UNWRAP(r, Sub(source, a_det1, d_det2)); + return Add(source, r, g_det3); +} + +template +tint::Result Eval::Det4(const Source& source, + NumberT a, + NumberT b, + NumberT c, + NumberT d, + NumberT e, + NumberT f, + NumberT g, + NumberT h, + NumberT i, + NumberT j, + NumberT k, + NumberT l, + NumberT m, + NumberT n, + NumberT o, + NumberT p) { + // | a e i m | + // | b f j n | + // | c g k o | + // | d h l p | + // + // = + // + // a | f j n | - e | b j n | + i | b f n | - m | b f j | + // | g k o | | c k o | | c g o | | c g k | + // | h l p | | d l p | | d h p | | d h l | + + TINT_CHECK_RESULT_UNWRAP(det1, Det3(source, f, g, h, j, k, l, n, o, p)); + TINT_CHECK_RESULT_UNWRAP(a_det1, Mul(source, a, det1)); + + TINT_CHECK_RESULT_UNWRAP(det2, Det3(source, b, c, d, j, k, l, n, o, p)); + TINT_CHECK_RESULT_UNWRAP(e_det2, Mul(source, e, det2)); + + TINT_CHECK_RESULT_UNWRAP(det3, Det3(source, b, c, d, f, g, h, n, o, p)); + TINT_CHECK_RESULT_UNWRAP(i_det3, Mul(source, i, det3)); + + TINT_CHECK_RESULT_UNWRAP(det4, Det3(source, b, c, d, f, g, h, j, k, l)); + TINT_CHECK_RESULT_UNWRAP(m_det4, Mul(source, m, det4)); + + TINT_CHECK_RESULT_UNWRAP(r1, Sub(source, a_det1, e_det2)); + TINT_CHECK_RESULT_UNWRAP(r2, Add(source, r1, i_det3)); + return Sub(source, r2, m_det4); +} + +template +tint::Result Eval::Sqrt(const Source& source, NumberT v) { + if (v < NumberT(0)) { + AddError(source) << "sqrt must be called with a value >= 0"; + if (use_runtime_semantics_) { + return NumberT{0}; + } + return Failure(); + } + return NumberT{std::sqrt(v)}; +} + +auto Eval::SqrtFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto v) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Sqrt(source, v)); + return CreateScalar(source, elem_ty, r); + }; +} + +template +tint::Result Eval::Clamp(const Source& source, NumberT e, NumberT low, NumberT high) { + if (low > high) { + AddError(source) << "clamp called with 'low' (" << low << ") greater than 'high' (" << high + << ")"; + if (!use_runtime_semantics_) { + return Failure(); + } + } + return NumberT{std::min(std::max(e, low), high)}; +} + +auto Eval::ClampFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto e, auto low, auto high) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Clamp(source, e, low, high)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::AddFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Add(source, a1, a2)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::SubFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Sub(source, a1, a2)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::MulFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Mul(source, a1, a2)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::DivFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Div(source, a1, a2)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::ModFunc(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Mod(source, a1, a2)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::Dot2Func(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2, auto b1, auto b2) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Dot2(source, a1, a2, b1, b2)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::Dot3Func(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2, auto a3, auto b1, auto b2, + auto b3) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Dot3(source, a1, a2, a3, b1, b2, b3)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::Dot4Func(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a1, auto a2, auto a3, auto a4, auto b1, auto b2, auto b3, + auto b4) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Dot4(source, a1, a2, a3, a4, b1, b2, b3, b4)); + return CreateScalar(source, elem_ty, r); + }; +} + +Eval::Result Eval::Dot(const Source& source, const Value* v1, const Value* v2) { + auto* vec_ty = v1->Type()->As(); + TINT_ASSERT(vec_ty); + auto* elem_ty = vec_ty->Type(); + switch (vec_ty->Width()) { + case 2: + return Dispatch_fia_fiu32_f16( // + Dot2Func(source, elem_ty), // + v1->Index(0), v1->Index(1), // + v2->Index(0), v2->Index(1)); + case 3: + return Dispatch_fia_fiu32_f16( // + Dot3Func(source, elem_ty), // + v1->Index(0), v1->Index(1), v1->Index(2), // + v2->Index(0), v2->Index(1), v2->Index(2)); + case 4: + return Dispatch_fia_fiu32_f16( // + Dot4Func(source, elem_ty), // + v1->Index(0), v1->Index(1), v1->Index(2), v1->Index(3), // + v2->Index(0), v2->Index(1), v2->Index(2), v2->Index(3)); + } + TINT_ICE() << "Expected vector"; +} + +Eval::Result Eval::Length(const Source& source, const core::type::Type* ty, const Value* c0) { + auto* vec_ty = c0->Type()->As(); + // Evaluates to the absolute value of e if T is scalar. + if (vec_ty == nullptr) { + auto create = [&](auto e) { + using NumberT = decltype(e); + return CreateScalar(source, ty, NumberT{std::abs(e)}); + }; + return Dispatch_fa_f32_f16(create, c0); + } + + // Evaluates to sqrt(e[0]^2 + e[1]^2 + ...) if T is a vector type. + TINT_CHECK_RESULT_UNWRAP(d, Dot(source, c0, c0)); + return Dispatch_fa_f32_f16(SqrtFunc(source, ty), d); +} + +Eval::Result Eval::Mul(const Source& source, + const core::type::Type* ty, + const Value* v1, + const Value* v2) { + auto transform = [&](const Value* c0, const Value* c1) { + return Dispatch_fia_fiu32_f16(MulFunc(source, c0->Type()), c0, c1); + }; + return TransformBinaryDifferingArityElements(mgr, ty, transform, v1, v2); +} + +Eval::Result Eval::Sub(const Source& source, + const core::type::Type* ty, + const Value* v1, + const Value* v2) { + auto transform = [&](const Value* c0, const Value* c1) { + return Dispatch_fia_fiu32_f16(SubFunc(source, c0->Type()), c0, c1); + }; + return TransformBinaryDifferingArityElements(mgr, ty, transform, v1, v2); +} + +auto Eval::Det2Func(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a, auto b, auto c, auto d) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Det2(source, a, b, c, d)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::Det3Func(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h, + auto i) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Det3(source, a, b, c, d, e, f, g, h, i)); + return CreateScalar(source, elem_ty, r); + }; +} + +auto Eval::Det4Func(const Source& source, const core::type::Type* elem_ty) { + return [this, source, elem_ty](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h, + auto i, auto j, auto k, auto l, auto m, auto n, auto o, + auto p) -> Eval::Result { + TINT_CHECK_RESULT_UNWRAP(r, Det4(source, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)); + return CreateScalar(source, elem_ty, r); + }; +} + +Eval::Result Eval::ArrayOrStructCtor(const core::type::Type* ty, VectorRef args) { + if (args.IsEmpty()) { + return mgr.Zero(ty); + } + + if (args.Length() == 1 && args[0]->Type() == ty) { + // Identity constructor. + return args[0]; + } + + // Multiple arguments. Must be a value constructor. + return mgr.Composite(ty, std::move(args)); +} + +Eval::Result Eval::Conv(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* el_ty = ty->Elements(ty).type; + if (!el_ty) { + return nullptr; + } + + if (!args[0]) { + return nullptr; // Single argument is not constant. + } + + return Convert(ty, args[0], source); +} + +Eval::Result Eval::Zero(const core::type::Type* ty, VectorRef, const Source&) { + return mgr.Zero(ty); +} + +Eval::Result Eval::Identity(const core::type::Type*, VectorRef args, const Source&) { + return args[0]; +} + +Eval::Result Eval::VecSplat(const core::type::Type* ty, + VectorRef args, + const Source&) { + if (auto* arg = args[0]) { + return mgr.Splat(ty, arg); + } + return nullptr; +} + +Eval::Result Eval::VecInitS(const core::type::Type* ty, + VectorRef args, + const Source&) { + return mgr.Composite(ty, args); +} + +Eval::Result Eval::VecInitM(const core::type::Type* ty, + VectorRef args, + const Source&) { + Vector els; + for (auto* arg : args) { + auto* val = arg; + if (!val) { + return nullptr; + } + auto* arg_ty = arg->Type(); + if (auto* arg_vec = arg_ty->As()) { + // Extract out vector elements. + for (uint32_t j = 0; j < arg_vec->Width(); j++) { + auto* el = val->Index(j); + if (!el) { + return nullptr; + } + els.Push(el); + } + } else { + els.Push(val); + } + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::MatInitS(const core::type::Type* ty, + VectorRef args, + const Source&) { + auto* m = static_cast(ty); + + Vector els; + for (uint32_t c = 0; c < m->Columns(); c++) { + Vector column; + for (uint32_t r = 0; r < m->Rows(); r++) { + auto i = r + c * m->Rows(); + column.Push(args[i]); + } + els.Push(mgr.Composite(m->ColumnType(), std::move(column))); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::MatInitV(const core::type::Type* ty, + VectorRef args, + const Source&) { + return mgr.Composite(ty, args); +} + +Eval::Result Eval::Index(const Value* obj_val, + const core::type::Type* obj_ty, + const Value* idx_val, + const Source& idx_source) { + // We may not have a Value at this stage but we still want to const evaluate this access based + // on the type of the access op. An example is here is a failure generated by a compile time + // negative index array access. + auto el = obj_val ? obj_val->Type()->Elements() : obj_ty->UnwrapPtrOrRef()->Elements(); + AInt idx = idx_val->ValueAs(); + if (idx < 0 || (el.count > 0 && idx >= el.count)) { + auto& err = AddError(idx_source) << "index " << idx << " out of bounds"; + if (el.count > 0) { + err << " [0.." + std::to_string(el.count - 1) + "]"; + } + + if (use_runtime_semantics_) { + return mgr.Zero(el.type); + } + return Failure(); + } + + return obj_val ? obj_val->Index(static_cast(idx)) : nullptr; +} + +Eval::Result Eval::Swizzle(const core::type::Type* ty, + const Value* object, + VectorRef indices) { + if (indices.Length() == 1) { + return object->Index(static_cast(indices[0])); + } + auto values = tint::Transform<4>( + indices, [&](uint32_t i) { return object->Index(static_cast(i)); }); + return mgr.Composite(ty, std::move(values)); +} + +Eval::Result Eval::bitcast(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* value = args[0]; + bool is_abstract = value->Type()->IsAbstractScalarOrVector(); + + // Target type + auto dst_elements = ty->Elements(ty->DeepestElement(), 1u); + auto dst_el_ty = dst_elements.type; + auto dst_count = dst_elements.count; + // Source type + auto src_elements = value->Type()->Elements(value->Type()->DeepestElement(), 1u); + auto src_el_ty = src_elements.type; + auto src_count = src_elements.count; + + TINT_ASSERT(is_abstract || (dst_count * dst_el_ty->Size() == src_count * src_el_ty->Size())); + uint32_t total_bitwidth = dst_count * dst_el_ty->Size(); + // Buffer holding the bits from source value, result value reinterpreted from it. + Vector buffer; + buffer.Reserve(total_bitwidth); + + // Pushes bits from source value into the buffer. + auto push_src_element_bits = [&](const Value* element) { + auto push_32_bits = [&](uint32_t v) { + buffer.Push(std::byte(v & 0xffu)); + buffer.Push(std::byte((v >> 8) & 0xffu)); + buffer.Push(std::byte((v >> 16) & 0xffu)); + buffer.Push(std::byte((v >> 24) & 0xffu)); + return Success; + }; + auto push_16_bits = [&](uint16_t v) { + buffer.Push(std::byte(v & 0xffu)); + buffer.Push(std::byte((v >> 8) & 0xffu)); + return Success; + }; + return Switch( + src_el_ty, + [&](const core::type::AbstractInt*) -> tint::Result { + if (element->ValueAs() < 0) { + TINT_CHECK_RESULT_UNWRAP(res, Conv(mgr.types.i32(), Vector{element}, source)); + return push_32_bits(tint::Bitcast(res->ValueAs())); + } else { + TINT_CHECK_RESULT_UNWRAP(res, Conv(mgr.types.u32(), Vector{element}, source)); + return push_32_bits(res->ValueAs()); + } + }, + [&](const core::type::U32*) -> tint::Result { + return push_32_bits(element->ValueAs()); + }, + [&](const core::type::I32*) -> tint::Result { + return push_32_bits(tint::Bitcast(element->ValueAs())); + }, + [&](const core::type::F32*) -> tint::Result { + return push_32_bits(tint::Bitcast(element->ValueAs())); + }, + [&](const core::type::F16*) -> tint::Result { + return push_16_bits(element->ValueAs().BitsRepresentation()); + }, + TINT_ICE_ON_NO_MATCH); + }; + if (src_count == 1) { + TINT_CHECK_RESULT(push_src_element_bits(value)); + } else { + for (size_t i = 0; i < src_count; i++) { + TINT_CHECK_RESULT(push_src_element_bits(value->Index(i))); + } + } + + // Vector holding elements of return value + Vector els; + + // Reinterprets the buffer bits as destination element and push the result into the vector. + // Return false if an error occurred, otherwise return true. + auto push_dst_element = [&](size_t offset) -> bool { + uint32_t v; + if (dst_el_ty->Size() == 4) { + v = (std::to_integer(buffer[offset])) | + (std::to_integer(buffer[offset + 1]) << 8) | + (std::to_integer(buffer[offset + 2]) << 16) | + (std::to_integer(buffer[offset + 3]) << 24); + } else { + v = (std::to_integer(buffer[offset])) | + (std::to_integer(buffer[offset + 1]) << 8); + } + + return Switch( + dst_el_ty, + [&](const core::type::U32*) { // + auto r = CreateScalar(source, dst_el_ty, u32(v)); + if (r != Success) { + return false; + } + els.Push(r.Get()); + return true; + }, + [&](const core::type::I32*) { // + auto r = CreateScalar(source, dst_el_ty, tint::Bitcast(v)); + if (r != Success) { + return false; + } + els.Push(r.Get()); + return true; + }, + [&](const core::type::F32*) { // + auto r = CreateScalar(source, dst_el_ty, tint::Bitcast(v)); + if (r != Success) { + return false; + } + els.Push(r.Get()); + return true; + }, + [&](const core::type::F16*) { // + auto r = CreateScalar(source, dst_el_ty, f16::FromBits(static_cast(v))); + if (r != Success) { + return false; + } + els.Push(r.Get()); + return true; + }, + TINT_ICE_ON_NO_MATCH); + }; + + TINT_ASSERT((buffer.Length() == total_bitwidth)); + for (size_t i = 0; i < dst_count; i++) { + if (!push_dst_element(i * dst_el_ty->Size())) { + return Failure(); + } + } + + if (dst_count == 1) { + return std::move(els[0]); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::Complement(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c) { + auto create = [&](auto i) { + return CreateScalar(source, c->Type(), decltype(i)(~i.value)); + }; + return Dispatch_ia_iu32(create, c); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::UnaryMinus(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c) { + auto create = [&](auto i) { + // For signed integrals, avoid C++ UB by not negating the + // smallest negative number. In WGSL, this operation is well + // defined to return the same value, see: + // https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr. + using T = UnwrapNumber; + if constexpr (std::is_integral_v) { + auto v = i.value; + if (v != std::numeric_limits::min()) { + v = -v; + } + return CreateScalar(source, c->Type(), decltype(i)(v)); + } else { + return CreateScalar(source, c->Type(), decltype(i)(-i.value)); + } + }; + return Dispatch_fia_fi32_f16(create, c); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::Not(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c) { + auto create = [&](auto i) { return CreateScalar(source, c->Type(), decltype(i)(!i)); }; + return Dispatch_bool(create, c); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::Plus(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + return Dispatch_fia_fiu32_f16(AddFunc(source, c0->Type()), c0, c1); + }; + + return TransformBinaryDifferingArityElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::Minus(const core::type::Type* ty, + VectorRef args, + const Source& source) { + return Sub(source, ty, args[0], args[1]); +} + +Eval::Result Eval::Multiply(const core::type::Type* ty, + VectorRef args, + const Source& source) { + return Mul(source, ty, args[0], args[1]); +} + +Eval::Result Eval::MultiplyMatVec(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* mat_ty = args[0]->Type()->As(); + auto* vec_ty = args[1]->Type()->As(); + auto* elem_ty = vec_ty->Type(); + + auto dot = [&](const Value* m, size_t row, const Value* v) { + Eval::Result result; + switch (mat_ty->Columns()) { + case 2: + result = Dispatch_fa_f32_f16(Dot2Func(source, elem_ty), // + m->Index(0)->Index(row), // + m->Index(1)->Index(row), // + v->Index(0), // + v->Index(1)); + break; + case 3: + result = Dispatch_fa_f32_f16(Dot3Func(source, elem_ty), // + m->Index(0)->Index(row), // + m->Index(1)->Index(row), // + m->Index(2)->Index(row), // + v->Index(0), // + v->Index(1), v->Index(2)); + break; + case 4: + result = Dispatch_fa_f32_f16(Dot4Func(source, elem_ty), // + m->Index(0)->Index(row), // + m->Index(1)->Index(row), // + m->Index(2)->Index(row), // + m->Index(3)->Index(row), // + v->Index(0), // + v->Index(1), // + v->Index(2), // + v->Index(3)); + break; + } + return result; + }; + + Vector result; + for (size_t i = 0; i < mat_ty->Rows(); ++i) { + TINT_CHECK_RESULT_UNWRAP(r, dot(args[0], i, args[1])); // matrix row i * vector + result.Push(r); + } + return mgr.Composite(ty, result); +} +Eval::Result Eval::MultiplyVecMat(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* vec_ty = args[0]->Type()->As(); + auto* mat_ty = args[1]->Type()->As(); + auto* elem_ty = vec_ty->Type(); + + auto dot = [&](const Value* v, const Value* m, size_t col) { + Eval::Result result; + switch (mat_ty->Rows()) { + case 2: + result = Dispatch_fa_f32_f16(Dot2Func(source, elem_ty), // + m->Index(col)->Index(0), // + m->Index(col)->Index(1), // + v->Index(0), // + v->Index(1)); + break; + case 3: + result = Dispatch_fa_f32_f16(Dot3Func(source, elem_ty), // + m->Index(col)->Index(0), // + m->Index(col)->Index(1), // + m->Index(col)->Index(2), + v->Index(0), // + v->Index(1), // + v->Index(2)); + break; + case 4: + result = Dispatch_fa_f32_f16(Dot4Func(source, elem_ty), // + m->Index(col)->Index(0), // + m->Index(col)->Index(1), // + m->Index(col)->Index(2), // + m->Index(col)->Index(3), // + v->Index(0), // + v->Index(1), // + v->Index(2), // + v->Index(3)); + } + return result; + }; + + Vector result; + for (size_t i = 0; i < mat_ty->Columns(); ++i) { + TINT_CHECK_RESULT_UNWRAP(r, dot(args[0], args[1], i)); // vector * matrix col i + result.Push(r); + } + return mgr.Composite(ty, result); +} + +Eval::Result Eval::MultiplyMatMat(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* mat1 = args[0]; + auto* mat2 = args[1]; + auto* mat1_ty = mat1->Type()->As(); + auto* mat2_ty = mat2->Type()->As(); + auto* elem_ty = mat1_ty->Type(); + + auto dot = [&](const Value* m1, size_t row, const Value* m2, size_t col) { + auto m1e = [&](size_t r, size_t c) { return m1->Index(c)->Index(r); }; + auto m2e = [&](size_t r, size_t c) { return m2->Index(c)->Index(r); }; + + Eval::Result result; + switch (mat1_ty->Columns()) { + case 2: + result = Dispatch_fa_f32_f16(Dot2Func(source, elem_ty), // + m1e(row, 0), // + m1e(row, 1), // + m2e(0, col), // + m2e(1, col)); + break; + case 3: + result = Dispatch_fa_f32_f16(Dot3Func(source, elem_ty), // + m1e(row, 0), // + m1e(row, 1), // + m1e(row, 2), // + m2e(0, col), // + m2e(1, col), // + m2e(2, col)); + break; + case 4: + result = Dispatch_fa_f32_f16(Dot4Func(source, elem_ty), // + m1e(row, 0), // + m1e(row, 1), // + m1e(row, 2), // + m1e(row, 3), // + m2e(0, col), // + m2e(1, col), // + m2e(2, col), // + m2e(3, col)); + break; + } + return result; + }; + + Vector result_mat; + for (size_t c = 0; c < mat2_ty->Columns(); ++c) { + Vector col_vec; + for (size_t r = 0; r < mat1_ty->Rows(); ++r) { + TINT_CHECK_RESULT_UNWRAP(v, dot(mat1, r, mat2, c)); // mat1 row r * mat2 col c + col_vec.Push(v); // mat1 row r * mat2 col c + } + + // Add column vector to matrix + auto* col_vec_ty = ty->As()->ColumnType(); + result_mat.Push(mgr.Composite(col_vec_ty, col_vec)); + } + return mgr.Composite(ty, result_mat); +} + +Eval::Result Eval::Divide(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + return Dispatch_fia_fiu32_f16(DivFunc(source, c0->Type()), c0, c1); + }; + + return TransformBinaryDifferingArityElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::Modulo(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + return Dispatch_fia_fiu32_f16(ModFunc(source, c0->Type()), c0, c1); + }; + + return TransformBinaryDifferingArityElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::Equal(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), i == j); + }; + return Dispatch_fia_fiu32_f16_bool(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::NotEqual(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), i != j); + }; + return Dispatch_fia_fiu32_f16_bool(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::LessThan(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), i < j); + }; + return Dispatch_fia_fiu32_f16(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::GreaterThan(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), i > j); + }; + return Dispatch_fia_fiu32_f16(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::LessThanEqual(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), i <= j); + }; + return Dispatch_fia_fiu32_f16(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::GreaterThanEqual(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), i >= j); + }; + return Dispatch_fia_fiu32_f16(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::LogicalAnd(const core::type::Type* ty, + VectorRef args, + const Source& source) { + // Due to short-circuiting, this function is only called if lhs is true, so we only return the + // value of the rhs. + TINT_ASSERT(args[0]->ValueAs()); + return CreateScalar(source, ty, args[1]->ValueAs()); +} + +Eval::Result Eval::LogicalOr(const core::type::Type* ty, + VectorRef args, + const Source& source) { + // Due to short-circuiting, this function is only called if lhs is false, so we only only return + // the value of the rhs. + TINT_ASSERT(!args[0]->ValueAs()); + return CreateScalar(source, ty, args[1]->ValueAs()); +} + +Eval::Result Eval::And(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + using T = decltype(i); + T result; + if constexpr (std::is_same_v) { + result = i && j; + } else { // integral + result = i & j; + } + return CreateScalar(source, ty->DeepestElement(), result); + }; + return Dispatch_ia_iu32_bool(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::Or(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + using T = decltype(i); + T result; + if constexpr (std::is_same_v) { + result = i || j; + } else { // integral + result = i | j; + } + return CreateScalar(source, ty->DeepestElement(), result); + }; + return Dispatch_ia_iu32_bool(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::Xor(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), decltype(i){i ^ j}); + }; + return Dispatch_ia_iu32(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::ShiftLeft(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto e1, auto e2) -> Eval::Result { + using NumberT = decltype(e1); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + constexpr size_t bit_width = BitWidth; + UT e1u = static_cast(e1); + UT e2u = static_cast(e2); + + if constexpr (IsAbstract) { + // The e2 + 1 most significant bits of e1 must have the same bit value, otherwise + // sign change (overflow) would occur. + // Check sign change only if e2 is less than bit width of e1. If e1 is larger + // than bit width, we check for non-representable value below. + if (e2u < bit_width) { + UT must_match_msb = e2u + 1; + UT mask = ~UT{0} << (bit_width - must_match_msb); + if ((e1u & mask) != 0 && (e1u & mask) != mask) { + AddError(source) << "shift left operation results in sign change"; + if (!use_runtime_semantics_) { + return Failure(); + } + } + } else { + // If shift value >= bit_width, then any non-zero value would overflow + if (e1 != 0) { + AddError(source) << OverflowErrorMessage(e1, "<<", e2); + if (!use_runtime_semantics_) { + return Failure(); + } + } + + // It's UB in C++ to shift by greater or equal to the bit width (even if the lhs + // is 0), so we make sure to avoid this by setting the shift value to 0. + e2u = 0; + } + } else { + if (static_cast(e2) >= bit_width && use_runtime_semantics_) { + // At shader/pipeline-creation time, it is an error to shift by the bit width of + // the lhs or greater, which should have already been caught by the validator. + // At runtime, we shift by e2 % (bit width of e1). + AddError(source) + << "shift left value must be less than the bit width of the lhs, which is " + << bit_width; + e2u = e2u % bit_width; + } + + if constexpr (std::is_signed_v) { + // If T is a signed integer type, and the e2+1 most significant bits of e1 do + // not have the same bit value, then error. + size_t must_match_msb = e2u + 1; + UT mask = ~UT{0} << (bit_width - must_match_msb); + if ((e1u & mask) != 0 && (e1u & mask) != mask) { + AddError(source) << "shift left operation results in sign change"; + if (!use_runtime_semantics_) { + return Failure(); + } + } + } else { + // If T is an unsigned integer type, and any of the e2 most significant bits of + // e1 are 1, then error. + if (e2u > 0) { + size_t must_be_zero_msb = e2u; + UT mask = ~UT{0} << (bit_width - must_be_zero_msb); + if ((e1u & mask) != 0) { + AddError(source) << OverflowErrorMessage(e1, "<<", e2); + if (!use_runtime_semantics_) { + return Failure(); + } + } + } + } + } + + // Avoid UB by left shifting as unsigned value + auto result = static_cast(static_cast(e1) << e2u); + return CreateScalar(source, ty->DeepestElement(), NumberT{result}); + }; + return Dispatch_ia_iu32(create, c0, c1); + }; + + TINT_ASSERT(args[1]->Type()->DeepestElement()->Is()) + << "Element type of rhs of ShiftLeft must be a u32"; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::ShiftRight(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto e1, auto e2) -> Eval::Result { + using NumberT = decltype(e1); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + const size_t bit_width = BitWidth; + UT e1u = static_cast(e1); + UT e2u = static_cast(e2); + + [[maybe_unused]] auto signed_shift_right = [&] { + // In C++, right shift of a signed negative number is implementation-defined. + // Although most implementations sign-extend, we do it manually to ensure it works + // correctly on all implementations. + const UT msb = UT{1} << (bit_width - 1); + UT sign_ext = 0; + if (e1u & msb) { + // Set e2 + 1 bits to 1 + UT num_shift_bits_mask = ((UT{1} << e2u) - UT{1}); + sign_ext = (num_shift_bits_mask << (bit_width - e2u - UT{1})) | msb; + } + return static_cast((e1u >> e2u) | sign_ext); + }; + + T result = 0; + if constexpr (IsAbstract) { + if (static_cast(e2) >= bit_width) { + // For an abstract shift right, if e1 is negative, each inserted bit is 1, + // resulting in the value -1 for all 1s. For a non-negative e1, each inserted + // bit is 0, resulting in 0. + result = e1 < 0 ? T{-1} : T{0}; + } else { + result = signed_shift_right(); + } + } else { + if (static_cast(e2) >= bit_width && use_runtime_semantics_) { + // At shader/pipeline-creation time, it is an error to shift by the bit width of + // the lhs or greater, which should have already been caught by the validator. + // At runtime, we shift by e2 % (bit width of e1). + AddError(source) + << "shift right value must be less than the bit width of the lhs, which is " + << bit_width; + e2u = e2u % bit_width; + } + + if constexpr (std::is_signed_v) { + result = signed_shift_right(); + } else { + result = e1 >> e2u; + } + } + return CreateScalar(source, ty->DeepestElement(), NumberT{result}); + }; + return Dispatch_ia_iu32(create, c0, c1); + }; + + TINT_ASSERT(args[1]->Type()->DeepestElement()->Is()) + << "Element type of rhs of ShiftLeft must be a u32"; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::abs(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + NumberT result; + if constexpr (IsUnsignedIntegral) { + result = e; + } else if constexpr (IsSignedIntegral) { + if (e == NumberT::Lowest()) { + result = e; + } else { + result = NumberT{std::abs(e)}; + } + } else { + result = NumberT{std::abs(e)}; + } + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_fia_fiu32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::acos(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = + [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + if (i < NumberT(-1.0) || i > NumberT(1.0)) { + AddError(source) + << "acos must be called with a value in the range [-1 .. 1] (inclusive)"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), NumberT(std::acos(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::acosh(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + if (i < NumberT(1.0)) { + AddError(source) << "acosh must be called with a value >= 1.0"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), NumberT(std::acosh(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::all(const core::type::Type* ty, + VectorRef args, + const Source& source) { + return CreateScalar(source, ty, !args[0]->AnyZero()); +} + +Eval::Result Eval::any(const core::type::Type* ty, + VectorRef args, + const Source& source) { + return CreateScalar(source, ty, !args[0]->AllZero()); +} + +Eval::Result Eval::asin(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = + [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + if (i < NumberT(-1.0) || i > NumberT(1.0)) { + AddError(source) + << "asin must be called with a value in the range [-1 .. 1] (inclusive)"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), NumberT(std::asin(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::asinh(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) { + return CreateScalar(source, c0->Type(), decltype(i)(std::asinh(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::atan(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) { + return CreateScalar(source, c0->Type(), decltype(i)(std::atan(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::atanh(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = + [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + if (i <= NumberT(-1.0) || i >= NumberT(1.0)) { + AddError(source) + << "atanh must be called with a value in the range (-1 .. 1) (exclusive)"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), NumberT(std::atanh(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::atan2(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto i, auto j) { + return CreateScalar(source, c0->Type(), decltype(i)(std::atan2(i.value, j.value))); + }; + return Dispatch_fa_f32_f16(create, c0, c1); + }; + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::ceil(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + return CreateScalar(source, c0->Type(), decltype(e)(std::ceil(e))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::clamp(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1, const Value* c2) { + return Dispatch_fia_fiu32_f16(ClampFunc(source, c0->Type()), c0, c1, c2); + }; + return TransformTernaryElements(mgr, ty, transform, args[0], args[1], args[2]); +} + +Eval::Result Eval::cos(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + return CreateScalar(source, c0->Type(), NumberT(std::cos(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::cosh(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + return CreateScalar(source, c0->Type(), NumberT(std::cosh(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::countLeadingZeros(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + using T = UnwrapNumber; + auto count = CountLeadingBits(T{e}, T{0}); + return CreateScalar(source, c0->Type(), NumberT(count)); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::countOneBits(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + constexpr UT kRightMost = UT{1}; + + auto count = UT{0}; + for (auto v = static_cast(e); v != UT{0}; v >>= 1) { + if ((v & kRightMost) == 1) { + ++count; + } + } + + return CreateScalar(source, c0->Type(), NumberT(count)); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::countTrailingZeros(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + using T = UnwrapNumber; + auto count = CountTrailingBits(T{e}, T{0}); + return CreateScalar(source, c0->Type(), NumberT(count)); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::cross(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* u = args[0]; + auto* v = args[1]; + auto* elem_ty = u->Type()->As()->Type(); + + // cross product of a v3 is the determinant of the 3x3 matrix: + // + // |i j k | + // |u0 u1 u2| + // |v0 v1 v2| + // + // |u1 u2|i - |u0 u2|j + |u0 u1|k + // |v1 v2| |v0 v2| |v0 v1| + // + // |u1 u2|i + |v0 v2|j + |u0 u1|k + // |v1 v2| |u0 u2| |v0 v1| + + auto* u0 = u->Index(0); + auto* u1 = u->Index(1); + auto* u2 = u->Index(2); + auto* v0 = v->Index(0); + auto* v1 = v->Index(1); + auto* v2 = v->Index(2); + + TINT_CHECK_RESULT_UNWRAP(x, Dispatch_fa_f32_f16(Det2Func(source, elem_ty), u1, u2, v1, v2)); + TINT_CHECK_RESULT_UNWRAP(y, Dispatch_fa_f32_f16(Det2Func(source, elem_ty), v0, v2, u0, u2)); + TINT_CHECK_RESULT_UNWRAP(z, Dispatch_fa_f32_f16(Det2Func(source, elem_ty), u0, u1, v0, v1)); + + return mgr.Composite(ty, Vector{x, y, z}); +} + +Eval::Result Eval::degrees(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) -> Eval::Result { + using NumberT = decltype(e); + using T = UnwrapNumber; + + auto scale = Div(source, NumberT(180), NumberT(std::numbers::pi_v)); + if (scale != Success) { + AddNote(source) << "when calculating degrees"; + return Failure(); + } + auto result = Mul(source, e, scale.Get()); + if (result != Success) { + AddNote(source) << "when calculating degrees"; + return Failure(); + } + return CreateScalar(source, c0->Type(), result.Get()); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::determinant(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calculate = [&]() -> Eval::Result { + auto* m = args[0]; + auto* mat_ty = m->Type()->As(); + auto me = [&](size_t r, size_t c) { return m->Index(c)->Index(r); }; + switch (mat_ty->Rows()) { + case 2: + return Dispatch_fa_f32_f16(Det2Func(source, ty), // + me(0, 0), me(1, 0), // + me(0, 1), me(1, 1)); + + case 3: + return Dispatch_fa_f32_f16(Det3Func(source, ty), // + me(0, 0), me(1, 0), me(2, 0), // + me(0, 1), me(1, 1), me(2, 1), // + me(0, 2), me(1, 2), me(2, 2)); + + case 4: + return Dispatch_fa_f32_f16(Det4Func(source, ty), // + me(0, 0), me(1, 0), me(2, 0), me(3, 0), // + me(0, 1), me(1, 1), me(2, 1), me(3, 1), // + me(0, 2), me(1, 2), me(2, 2), me(3, 2), // + me(0, 3), me(1, 3), me(2, 3), me(3, 3)); + } + TINT_ICE() << "Unexpected number of matrix rows"; + }; + auto r = calculate(); + if (r != Success) { + AddNote(source) << "when calculating determinant"; + } + return r; +} + +Eval::Result Eval::distance(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto err = [&]() -> Eval::Result { + AddNote(source) << "when calculating distance"; + return Failure(); + }; + + auto minus = Minus(args[0]->Type(), args, source); + if (minus != Success) { + return err(); + } + + auto len = Length(source, ty, minus.Get()); + if (len != Success) { + return err(); + } + return len; +} + +Eval::Result Eval::dot(const core::type::Type*, + VectorRef args, + const Source& source) { + auto r = Dot(source, args[0], args[1]); + if (r != Success) { + AddNote(source) << "when calculating dot"; + } + return r; +} + +Eval::Result Eval::dot4I8Packed(const core::type::Type* ty, + VectorRef args, + const Source& source) { + uint32_t packed_int8_vec4_1 = args[0]->ValueAs(); + uint32_t packed_int8_vec4_2 = args[1]->ValueAs(); + + int32_t result = 0; + for (size_t i = 0; i < 4; i++) { + result += GetNthSignedByte(packed_int8_vec4_1, i) * GetNthSignedByte(packed_int8_vec4_2, i); + } + + return CreateScalar(source, ty, i32(result)); +} + +Eval::Result Eval::dot4U8Packed(const core::type::Type* ty, + VectorRef args, + const Source& source) { + uint32_t packed_uint8_vec4_1 = args[0]->ValueAs(); + uint32_t packed_uint8_vec4_2 = args[1]->ValueAs(); + + uint32_t result = 0; + for (size_t i = 0; i < 4; i++) { + result += + GetNthUnsignedByte(packed_uint8_vec4_1, i) * GetNthUnsignedByte(packed_uint8_vec4_2, i); + } + + return CreateScalar(source, ty, u32(result)); +} + +Eval::Result Eval::exp(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e0) -> Eval::Result { + using NumberT = decltype(e0); + auto val = NumberT(std::exp(e0)); + if (!std::isfinite(val.value)) { + AddError(source) << OverflowExpErrorMessage("e", e0); + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), val); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::exp2(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e0) -> Eval::Result { + using NumberT = decltype(e0); + auto val = NumberT(std::exp2(e0)); + if (!std::isfinite(val.value)) { + AddError(source) << OverflowExpErrorMessage("2", e0); + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), val); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::extractBits(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = + [&](const Value* c0) { + auto create = [&](auto in_e) -> Eval::Result { + using NumberT = decltype(in_e); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + using NumberUT = Number; + + // Read args that are always scalar + NumberUT in_offset = args[1]->ValueAs(); + NumberUT in_count = args[2]->ValueAs(); + + // Cast all to unsigned + UT e = static_cast(in_e); + UT o = static_cast(in_offset); + UT c = static_cast(in_count); + + constexpr UT w = sizeof(UT) * 8; + if (o > w || c > w || (o + c) > w) { + AddError(source) + << "'offset' + 'count' must be less than or equal to the bit width of 'e'"; + if (!use_runtime_semantics_) { + return Failure(); + } + + o = std::min(o, w); + c = std::min(c, w - o); + } + + NumberT result; + if (c == UT{0}) { + // The result is 0 if c is 0 + result = NumberT{0}; + } else if (c == w) { + // The result is e if c is w + result = NumberT{e}; + } else { + // Otherwise, bits 0..c - 1 of the result are copied from bits o..o + c - 1 of + // e. + UT src_mask = ((UT{1} << c) - UT{1}) << o; + UT r = (e & src_mask) >> o; + if constexpr (IsSignedIntegral) { + // Other bits of the result are the same as bit c - 1 of the result. + // Only need to set other bits if bit at c - 1 of result is 1 + if ((r & (UT{1} << (c - UT{1}))) != UT{0}) { + UT dst_mask = src_mask >> o; + r |= (~UT{0} & ~dst_mask); + } + } + + result = NumberT{r}; + } + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::faceForward(const core::type::Type* ty, + VectorRef args, + const Source& source) { + // Returns e1 if dot(e2, e3) is negative, and -e1 otherwise. + auto* e1 = args[0]; + auto* e2 = args[1]; + auto* e3 = args[2]; + auto r = Dot(source, e2, e3); + if (r != Success) { + AddNote(source) << "when calculating faceForward"; + return Failure(); + } + auto is_negative = [](auto v) { return v < 0; }; + if (Dispatch_fa_f32_f16(is_negative, r.Get())) { + return e1; + } + return UnaryMinus(ty, Vector{e1}, source); +} + +Eval::Result Eval::firstLeadingBit(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + constexpr UT kNumBits = sizeof(UT) * 8; + + NumberT result; + if constexpr (IsUnsignedIntegral) { + if (e == T{0}) { + // T(-1) if e is zero. + result = NumberT(static_cast(-1)); + } else { + // Otherwise the position of the most significant 1 bit in e. + static_assert(std::is_same_v); + UT count = CountLeadingBits(UT{e}, UT{0}); + UT pos = kNumBits - count - 1; + result = NumberT(pos); + } + } else { + if (e == T{0} || e == T{-1}) { + // -1 if e is 0 or -1. + result = NumberT(-1); + } else { + // Otherwise the position of the most significant bit in e that is different + // from e's sign bit. + UT eu = static_cast(e); + UT sign_bit = eu >> (kNumBits - 1); + UT count = CountLeadingBits(eu, sign_bit); + UT pos = kNumBits - count - 1; + result = NumberT(pos); + } + } + + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::firstTrailingBit(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + + NumberT result; + if (e == T{0}) { + // T(-1) if e is zero. + result = NumberT(static_cast(-1)); + } else { + // Otherwise the position of the least significant 1 bit in e. + UT pos = CountTrailingBits(T{e}, T{0}); + result = NumberT(pos); + } + + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::floor(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + return CreateScalar(source, c0->Type(), decltype(e)(std::floor(e))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::fma(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c1, const Value* c2, const Value* c3) { + auto create = [&](auto e1, auto e2, auto e3) -> Eval::Result { + auto err_msg = [&] { + AddNote(source) << "when calculating fma"; + return Failure(); + }; + + auto mul = Mul(source, e1, e2); + if (mul != Success) { + return err_msg(); + } + + auto val = Add(source, mul.Get(), e3); + if (val != Success) { + return err_msg(); + } + return CreateScalar(source, c1->Type(), val.Get()); + }; + return Dispatch_fa_f32_f16(create, c1, c2, c3); + }; + return TransformTernaryElements(mgr, ty, transform, args[0], args[1], args[2]); +} + +Eval::Result Eval::fract(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c1) { + auto create = [&](auto e) -> Eval::Result { + using NumberT = decltype(e); + auto r = e - std::floor(e); + return CreateScalar(source, c1->Type(), NumberT{r}); + }; + return Dispatch_fa_f32_f16(create, c1); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::frexp(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* arg = args[0]; + + struct FractExp { + Eval::Result fract; + Eval::Result exp; + }; + + auto scalar = [&](const Value* s) { + int exp = 0; + double fract = std::frexp(s->ValueAs(), &exp); + return Switch( + s->Type(), + [&](const core::type::F32*) { + return FractExp{ + CreateScalar(source, mgr.types.f32(), f32(fract)), + CreateScalar(source, mgr.types.i32(), i32(exp)), + }; + }, + [&](const core::type::F16*) { + return FractExp{ + CreateScalar(source, mgr.types.f16(), f16(fract)), + CreateScalar(source, mgr.types.i32(), i32(exp)), + }; + }, + [&](const core::type::AbstractFloat*) { + return FractExp{ + CreateScalar(source, mgr.types.AFloat(), AFloat(fract)), + CreateScalar(source, mgr.types.AInt(), AInt(exp)), + }; + }, + TINT_ICE_ON_NO_MATCH); + }; + + if (auto* vec = arg->Type()->As()) { + Vector fract_els; + Vector exp_els; + for (uint32_t i = 0; i < vec->Width(); i++) { + auto fe = scalar(arg->Index(i)); + TINT_CHECK_RESULT(fe.fract); + TINT_CHECK_RESULT(fe.exp); + fract_els.Push(fe.fract.Get()); + exp_els.Push(fe.exp.Get()); + } + auto fract_ty = mgr.types.vec(fract_els[0]->Type(), vec->Width()); + auto exp_ty = mgr.types.vec(exp_els[0]->Type(), vec->Width()); + return mgr.Composite(ty, Vector{ + mgr.Composite(fract_ty, std::move(fract_els)), + mgr.Composite(exp_ty, std::move(exp_els)), + }); + } else { + auto fe = scalar(arg); + TINT_CHECK_RESULT(fe.fract); + TINT_CHECK_RESULT(fe.exp); + return mgr.Composite(ty, Vector{ + fe.fract.Get(), + fe.exp.Get(), + }); + } +} + +Eval::Result Eval::insertBits(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = + [&](const Value* c0, const Value* c1) { + auto create = [&](auto in_e, auto in_newbits) -> Eval::Result { + using NumberT = decltype(in_e); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + using NumberUT = Number; + + // Read args that are always scalar + NumberUT in_offset = args[2]->ValueAs(); + NumberUT in_count = args[3]->ValueAs(); + + // Cast all to unsigned + UT e = static_cast(in_e); + UT newbits = static_cast(in_newbits); + UT o = static_cast(in_offset); + UT c = static_cast(in_count); + + constexpr UT w = sizeof(UT) * 8; + if (o > w || c > w || (o + c) > w) { + AddError(source) + << "'offset' + 'count' must be less than or equal to the bit width of 'e'"; + if (!use_runtime_semantics_) { + return Failure(); + } + o = std::min(o, w); + c = std::min(c, w - o); + } + + NumberT result; + if (c == UT{0}) { + // The result is e if c is 0 + result = NumberT{e}; + } else if (c == w) { + // The result is newbits if c is w + result = NumberT{newbits}; + } else { + // Otherwise, bits o..o + c - 1 of the result are copied from bits 0..c - 1 of + // newbits. Other bits of the result are copied from e. + UT from = newbits << o; + UT mask = ((UT{1} << c) - UT{1}) << UT{o}; + auto r = e; // Start with 'e' as the result + r &= ~mask; // Zero the bits in 'e' we're overwriting + r |= (from & mask); // Overwrite from 'newbits' (shifted into position) + result = NumberT{r}; + } + + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_iu32(create, c0, c1); + }; + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::inverseSqrt(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) -> Eval::Result { + using NumberT = decltype(e); + + if (e <= NumberT(0)) { + AddError(source) << "inverseSqrt must be called with a value > 0"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + + auto err = [&] { + AddNote(source) << "when calculating inverseSqrt"; + return Failure(); + }; + + auto s = Sqrt(source, e); + if (s != Success) { + return err(); + } + auto div = Div(source, NumberT(1), s.Get()); + if (div != Success) { + return err(); + } + + return CreateScalar(source, c0->Type(), div.Get()); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::ldexp(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c1, size_t index) { + auto create = [&](auto e1) -> Eval::Result { + using E1Type = decltype(e1); + // If e1 is AFloat, then e2 is AInt, otherwise it's i32 + using E2Type = std::conditional_t, AInt, i32>; + + E2Type e2; + auto* c2 = args[1]; + if (c2->Type()->Is()) { + e2 = c2->Index(index)->ValueAs(); + } else { + e2 = c2->ValueAs(); + } + + E2Type bias; + if constexpr (std::is_same_v) { + bias = 15; + } else if constexpr (std::is_same_v) { + bias = 127; + } else { + bias = 1023; + } + + if (e2 > bias + 1) { + AddError(source) << "e2 must be less than or equal to " << (bias + 1); + if (use_runtime_semantics_) { + return mgr.Zero(c1->Type()); + } + return Failure(); + } + + auto target_ty = ty->DeepestElement(); + + auto r = std::ldexp(e1, static_cast(e2)); + return CreateScalar(source, target_ty, E1Type{r}); + }; + return Dispatch_fa_f32_f16(create, c1); + }; + + return TransformElements(mgr, ty, transform, 0, args[0]); +} + +Eval::Result Eval::length(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto r = Length(source, ty, args[0]); + if (r != Success) { + AddNote(source) << "when calculating length"; + } + return r; +} + +Eval::Result Eval::log(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto v) -> Eval::Result { + using NumberT = decltype(v); + if (v <= NumberT(0)) { + AddError(source) << "log must be called with a value > 0"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), NumberT(std::log(v))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::log2(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto v) -> Eval::Result { + using NumberT = decltype(v); + if (v <= NumberT(0)) { + AddError(source) << "log2 must be called with a value > 0"; + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), NumberT(std::log2(v))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::max(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto e0, auto e1) { + return CreateScalar(source, c0->Type(), decltype(e0)(std::max(e0, e1))); + }; + return Dispatch_fia_fiu32_f16(create, c0, c1); + }; + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::min(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto e0, auto e1) { + return CreateScalar(source, c0->Type(), decltype(e0)(std::min(e0, e1))); + }; + return Dispatch_fia_fiu32_f16(create, c0, c1); + }; + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::mix(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1, size_t index) { + auto create = [&](auto e1, auto e2) -> Eval::Result { + using NumberT = decltype(e1); + // e3 is either a vector or a scalar + NumberT e3; + auto* c2 = args[2]; + if (c2->Type()->Is()) { + e3 = c2->Index(index)->ValueAs(); + } else { + e3 = c2->ValueAs(); + } + // Implement as `e1 * (1 - e3) + e2 * e3)` instead of as `e1 + e3 * (e2 - e1)` to avoid + // float precision loss when e1 and e2 significantly differ in magnitude. + TINT_CHECK_RESULT_UNWRAP(one_sub_e3, Sub(source, NumberT{1}, e3)); + TINT_CHECK_RESULT_UNWRAP(e1_mul_one_sub_e3, Mul(source, e1, one_sub_e3)); + TINT_CHECK_RESULT_UNWRAP(e2_mul_e3, Mul(source, e2, e3)); + TINT_CHECK_RESULT_UNWRAP(r, Add(source, e1_mul_one_sub_e3, e2_mul_e3)); + return CreateScalar(source, c0->Type(), r); + }; + return Dispatch_fa_f32_f16(create, c0, c1); + }; + auto r = TransformElements(mgr, ty, transform, 0, args[0], args[1]); + if (r != Success) { + AddNote(source) << "when calculating mix"; + } + return r; +} + +Eval::Result Eval::modf(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform_fract = [&](const Value* c) { + auto create = [&](auto e) { + return CreateScalar(source, c->Type(), decltype(e)(e.value - std::trunc(e.value))); + }; + return Dispatch_fa_f32_f16(create, c); + }; + auto transform_whole = [&](const Value* c) { + auto create = [&](auto e) { + return CreateScalar(source, c->Type(), decltype(e)(std::trunc(e.value))); + }; + return Dispatch_fa_f32_f16(create, c); + }; + + Vector fields; + + TINT_CHECK_RESULT_UNWRAP( + fract, TransformUnaryElements(mgr, args[0]->Type(), transform_fract, args[0])); + fields.Push(fract); + + TINT_CHECK_RESULT_UNWRAP( + whole, TransformUnaryElements(mgr, args[0]->Type(), transform_whole, args[0])); + fields.Push(whole); + + return mgr.Composite(ty, std::move(fields)); +} + +Eval::Result Eval::normalize(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* len_ty = ty->DeepestElement(); + auto len = Length(source, len_ty, args[0]); + if (len != Success) { + AddNote(source) << "when calculating normalize"; + return Failure(); + } + auto* v = len.Get(); + if (v->AllZero()) { + AddError(source) << "zero length vector can not be normalized"; + if (use_runtime_semantics_) { + return mgr.Zero(ty); + } + return Failure(); + } + return Divide(ty, Vector{args[0], v}, source); +} + +Eval::Result Eval::pack2x16float(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto convert = [&](f32 val) -> tint::Result { + auto conv = CheckedConvert(val); + if (conv != Success) { + AddError(source) << OverflowErrorMessage(val, "f16"); + if (use_runtime_semantics_) { + return 0; + } + return Failure(); + } + return conv.Get().BitsRepresentation(); + }; + + auto* e = args[0]; + TINT_CHECK_RESULT_UNWRAP(e0, convert(e->Index(0)->ValueAs())); + TINT_CHECK_RESULT_UNWRAP(e1, convert(e->Index(1)->ValueAs())); + + u32 ret = u32((e0 & 0x0000'ffff) | (e1 << 16)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack2x16snorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calc = [&](f32 val) -> u32 { + auto clamped = Clamp(source, val, f32(-1.0f), f32(1.0f)).Get(); + return u32( + tint::Bitcast(static_cast(std::floor(0.5f + (32767.0f * clamped))))); + }; + + auto* e = args[0]; + auto e0 = calc(e->Index(0)->ValueAs()); + auto e1 = calc(e->Index(1)->ValueAs()); + + u32 ret = u32((e0 & 0x0000'ffff) | (e1 << 16)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack2x16unorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calc = [&](f32 val) -> u32 { + auto clamped = Clamp(source, val, f32(0.0f), f32(1.0f)).Get(); + return u32{std::floor(0.5f + (65535.0f * clamped))}; + }; + + auto* e = args[0]; + auto e0 = calc(e->Index(0)->ValueAs()); + auto e1 = calc(e->Index(1)->ValueAs()); + + u32 ret = u32((e0 & 0x0000'ffff) | (e1 << 16)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack4x8snorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calc = [&](f32 val) -> u32 { + auto clamped = Clamp(source, val, f32(-1.0f), f32(1.0f)).Get(); + return u32( + tint::Bitcast(static_cast(std::floor(0.5f + (127.0f * clamped))))); + }; + + auto* e = args[0]; + auto e0 = calc(e->Index(0)->ValueAs()); + auto e1 = calc(e->Index(1)->ValueAs()); + auto e2 = calc(e->Index(2)->ValueAs()); + auto e3 = calc(e->Index(3)->ValueAs()); + + uint32_t mask = 0x0000'00ff; + u32 ret = u32((e0 & mask) | ((e1 & mask) << 8) | ((e2 & mask) << 16) | ((e3 & mask) << 24)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack4x8unorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calc = [&](f32 val) -> u32 { + auto clamped = Clamp(source, val, f32(0.0f), f32(1.0f)).Get(); + return u32{std::floor(0.5f + (255.0f * clamped))}; + }; + + auto* e = args[0]; + auto e0 = calc(e->Index(0)->ValueAs()); + auto e1 = calc(e->Index(1)->ValueAs()); + auto e2 = calc(e->Index(2)->ValueAs()); + auto e3 = calc(e->Index(3)->ValueAs()); + + uint32_t mask = 0x0000'00ff; + u32 ret = u32((e0 & mask) | ((e1 & mask) << 8) | ((e2 & mask) << 16) | ((e3 & mask) << 24)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack4xI8(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* e = args[0]; + auto e0 = e->Index(0)->ValueAs(); + auto e1 = e->Index(1)->ValueAs(); + auto e2 = e->Index(2)->ValueAs(); + auto e3 = e->Index(3)->ValueAs(); + + int32_t mask = 0xff; + u32 ret = u32((e0 & mask) | ((e1 & mask) << 8) | ((e2 & mask) << 16) | ((e3 & mask) << 24)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack4xU8(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* e = args[0]; + auto e0 = e->Index(0)->ValueAs(); + auto e1 = e->Index(1)->ValueAs(); + auto e2 = e->Index(2)->ValueAs(); + auto e3 = e->Index(3)->ValueAs(); + + uint32_t mask = 0xff; + u32 ret = u32((e0 & mask) | ((e1 & mask) << 8) | ((e2 & mask) << 16) | ((e3 & mask) << 24)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack4xI8Clamp(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calc = [&](i32 val) -> i32 { return Clamp(source, val, i32(-128), i32(127)).Get(); }; + + auto* e = args[0]; + auto e0 = calc(e->Index(0)->ValueAs()); + auto e1 = calc(e->Index(1)->ValueAs()); + auto e2 = calc(e->Index(2)->ValueAs()); + auto e3 = calc(e->Index(3)->ValueAs()); + + int32_t mask = 0xff; + u32 ret = u32((e0 & mask) | ((e1 & mask) << 8) | ((e2 & mask) << 16) | ((e3 & mask) << 24)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pack4xU8Clamp(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calc = [&](u32 val) -> u32 { return Clamp(source, val, u32(0), u32(255)).Get(); }; + + auto* e = args[0]; + auto e0 = calc(e->Index(0)->ValueAs()); + auto e1 = calc(e->Index(1)->ValueAs()); + auto e2 = calc(e->Index(2)->ValueAs()); + auto e3 = calc(e->Index(3)->ValueAs()); + + u32 ret = u32(e0 | (e1 << 8) | (e2 << 16) | (e3 << 24)); + return CreateScalar(source, ty, ret); +} + +Eval::Result Eval::pow(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto e1, auto e2) -> Eval::Result { + auto r = CheckedPow(e1, e2); + if (!r) { + AddError(source) << OverflowErrorMessage(e1, "^", e2); + if (use_runtime_semantics_) { + return mgr.Zero(c0->Type()); + } + return Failure(); + } + return CreateScalar(source, c0->Type(), *r); + }; + return Dispatch_fa_f32_f16(create, c0, c1); + }; + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::radians(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) -> Eval::Result { + using NumberT = decltype(e); + using T = UnwrapNumber; + + auto scale = Div(source, NumberT(std::numbers::pi_v), NumberT(180)); + if (scale != Success) { + AddNote(source) << "when calculating radians"; + return Failure(); + } + auto result = Mul(source, e, scale.Get()); + if (result != Success) { + AddNote(source) << "when calculating radians"; + return Failure(); + } + return CreateScalar(source, c0->Type(), result.Get()); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::reflect(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto calculate = [&]() -> Eval::Result { + // For the incident vector e1 and surface orientation e2, returns the reflection direction + // e1 - 2 * dot(e2, e1) * e2. + auto* e1 = args[0]; + auto* e2 = args[1]; + auto* vec_ty = ty->As(); + auto* el_ty = vec_ty->Type(); + + // dot(e2, e1) + TINT_CHECK_RESULT_UNWRAP(dot_e2_e1, Dot(source, e2, e1)); + + // 2 * dot(e2, e1) + auto mul2 = [&](auto v) -> Eval::Result { + using NumberT = decltype(v); + return CreateScalar(source, el_ty, NumberT{NumberT{2} * v}); + }; + TINT_CHECK_RESULT_UNWRAP(dot_e2_e1_2, Dispatch_fa_f32_f16(mul2, dot_e2_e1)); + + // 2 * dot(e2, e1) * e2 + TINT_CHECK_RESULT_UNWRAP(dot_e2_e1_2_e2, Mul(source, ty, dot_e2_e1_2, e2)); + + // e1 - 2 * dot(e2, e1) * e2 + return Sub(source, ty, e1, dot_e2_e1_2_e2); + }; + auto r = calculate(); + if (r != Success) { + AddNote(source) << "when calculating reflect"; + } + return r; +} + +Eval::Result Eval::refract(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* vec_ty = ty->As(); + auto* el_ty = vec_ty->Type(); + + auto compute_k = [&](auto e3, auto dot_e2_e1) -> Eval::Result { + using NumberT = decltype(e3); + // let k = 1.0 - e3 * e3 * (1.0 - dot(e2, e1) * dot(e2, e1)) + TINT_CHECK_RESULT_UNWRAP(e3_squared, Mul(source, e3, e3)); + TINT_CHECK_RESULT_UNWRAP(dot_e2_e1_squared, Mul(source, dot_e2_e1, dot_e2_e1)); + TINT_CHECK_RESULT_UNWRAP(r1, Sub(source, NumberT(1), dot_e2_e1_squared)); + TINT_CHECK_RESULT_UNWRAP(r2, Mul(source, e3_squared, r1)); + TINT_CHECK_RESULT_UNWRAP(r3, Sub(source, NumberT(1), r2)); + return CreateScalar(source, el_ty, r3); + }; + + auto compute_e2_scale = [&](auto e3, auto dot_e2_e1, auto k) -> Eval::Result { + // e3 * dot(e2, e1) + sqrt(k) + TINT_CHECK_RESULT_UNWRAP(sqrt_k, Sqrt(source, k)); + TINT_CHECK_RESULT_UNWRAP(r1, Mul(source, e3, dot_e2_e1)); + TINT_CHECK_RESULT_UNWRAP(r2, Add(source, r1, sqrt_k)); + return CreateScalar(source, el_ty, r2); + }; + + auto calculate = [&]() -> Eval::Result { + auto* e1 = args[0]; + auto* e2 = args[1]; + auto* e3 = args[2]; + + // For the incident vector e1 and surface normal e2, and the ratio of indices of refraction + // e3, let k = 1.0 - e3 * e3 * (1.0 - dot(e2, e1) * dot(e2, e1)). If k < 0.0, returns the + // refraction vector 0.0, otherwise return the refraction vector e3 * e1 - (e3 * dot(e2, e1) + // + sqrt(k)) * e2. + + // dot(e2, e1) + TINT_CHECK_RESULT_UNWRAP(dot_e2_e1, Dot(source, e2, e1)); + + // let k = 1.0 - e3 * e3 * (1.0 - dot(e2, e1) * dot(e2, e1)) + TINT_CHECK_RESULT_UNWRAP(k, Dispatch_fa_f32_f16(compute_k, e3, dot_e2_e1)); + + // If k < 0.0, returns the refraction vector 0.0 + if (k->ValueAs() < 0) { + return mgr.Zero(ty); + } + + // Otherwise return the refraction vector e3 * e1 - (e3 * dot(e2, e1) + sqrt(k)) * e2 + TINT_CHECK_RESULT_UNWRAP(e1_scaled, Mul(source, ty, e3, e1)); + TINT_CHECK_RESULT_UNWRAP(e2_scale, Dispatch_fa_f32_f16(compute_e2_scale, e3, dot_e2_e1, k)); + TINT_CHECK_RESULT_UNWRAP(e2_scaled, Mul(source, ty, e2_scale, e2)); + return Sub(source, ty, e1_scaled, e2_scaled); + }; + auto r = calculate(); + if (r != Success) { + AddNote(source) << "when calculating refract"; + } + return r; +} + +Eval::Result Eval::reverseBits(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto in_e) -> Eval::Result { + using NumberT = decltype(in_e); + using T = UnwrapNumber; + using UT = std::make_unsigned_t; + constexpr UT kNumBits = sizeof(UT) * 8; + + UT e = static_cast(in_e); + UT r = UT{0}; + for (size_t s = 0; s < kNumBits; ++s) { + // Write source 's' bit to destination 'd' bit if 1 + if (e & (UT{1} << s)) { + size_t d = kNumBits - s - 1; + r |= (UT{1} << d); + } + } + + return CreateScalar(source, c0->Type(), NumberT{r}); + }; + return Dispatch_iu32(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::round(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + using T = UnwrapNumber; + + auto integral = NumberT(0); + auto fract = std::abs(std::modf(e.value, &(integral.value))); + // When e lies halfway between integers k and k + 1, the result is k when k is even, + // and k + 1 when k is odd. + NumberT result = NumberT(0.0); + if (fract == NumberT(0.5)) { + // If the integral value is negative, then we need to subtract one in order to move + // to the correct `k`. The half way check is `k` and `k + 1` which in the positive + // case is `x` and `x + 1` but in the negative case is `x - 1` and `x`. + T integral_val = integral.value; + if (std::signbit(integral_val)) { + integral_val = std::abs(integral_val - 1); + } + if (uint64_t(integral_val) % 2 == 0) { + result = NumberT(std::floor(e.value)); + } else { + result = NumberT(std::ceil(e.value)); + } + } else { + result = NumberT(std::round(e.value)); + } + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::saturate(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) { + using NumberT = decltype(e); + return CreateScalar(source, c0->Type(), + NumberT(std::min(std::max(e, NumberT(0.0)), NumberT(1.0)))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::select_bool(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto cond = args[2]->ValueAs(); + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto f, auto t) -> Eval::Result { + return CreateScalar(source, ty->DeepestElement(), cond ? t : f); + }; + return Dispatch_fia_fiu32_f16_bool(create, c0, c1); + }; + + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::select_boolvec(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1, size_t index) { + auto create = [&](auto f, auto t) -> Eval::Result { + // Get corresponding bool value at the current vector value index + auto cond = args[2]->Index(index)->ValueAs(); + return CreateScalar(source, ty->DeepestElement(), cond ? t : f); + }; + return Dispatch_fia_fiu32_f16_bool(create, c0, c1); + }; + + return TransformElements(mgr, ty, transform, 0, args[0], args[1]); +} + +Eval::Result Eval::sign(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto e) -> Eval::Result { + using NumberT = decltype(e); + NumberT result; + NumberT zero{0.0}; + if (e.value < zero) { + result = NumberT{-1.0}; + } else if (e.value > zero) { + result = NumberT{1.0}; + } else { + result = zero; + } + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_fia_fi32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::sin(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + return CreateScalar(source, c0->Type(), NumberT(std::sin(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::sinh(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + return CreateScalar(source, c0->Type(), NumberT(std::sinh(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::smoothstep(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1, const Value* c2) { + auto create = [&](auto low, auto high, auto x) -> Eval::Result { + using NumberT = decltype(low); + + if (low == high) { + AddError(source) << "smoothstep called with 'low' (" << low << ") equal to 'high' (" + << high << ")"; + if (!use_runtime_semantics_) { + return Failure(); + } + } + + auto err = [&] { + AddNote(source) << "when calculating smoothstep"; + return Failure(); + }; + + // t = clamp((x - low) / (high - low), 0.0, 1.0) + auto x_minus_low = Sub(source, x, low); + auto high_minus_low = Sub(source, high, low); + if (x_minus_low != Success || high_minus_low != Success) { + return err(); + } + + auto div = Div(source, x_minus_low.Get(), high_minus_low.Get()); + if (div != Success) { + return err(); + } + + auto clamp = Clamp(source, div.Get(), NumberT(0), NumberT(1)); + auto t = clamp.Get(); + + // result = t * t * (3.0 - 2.0 * t) + auto t_times_t = Mul(source, t, t); + auto t_times_2 = Mul(source, NumberT(2), t); + if (t_times_t != Success || t_times_2 != Success) { + return err(); + } + + auto three_minus_t_times_2 = Sub(source, NumberT(3), t_times_2.Get()); + if (three_minus_t_times_2 != Success) { + return err(); + } + + auto result = Mul(source, t_times_t.Get(), three_minus_t_times_2.Get()); + if (result != Success) { + return err(); + } + return CreateScalar(source, c0->Type(), result.Get()); + }; + return Dispatch_fa_f32_f16(create, c0, c1, c2); + }; + return TransformTernaryElements(mgr, ty, transform, args[0], args[1], args[2]); +} + +Eval::Result Eval::step(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0, const Value* c1) { + auto create = [&](auto edge, auto x) -> Eval::Result { + using NumberT = decltype(edge); + NumberT result = x.value < edge.value ? NumberT(0.0) : NumberT(1.0); + return CreateScalar(source, c0->Type(), result); + }; + return Dispatch_fa_f32_f16(create, c0, c1); + }; + return TransformBinaryElements(mgr, ty, transform, args[0], args[1]); +} + +Eval::Result Eval::sqrt(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + return Dispatch_fa_f32_f16(SqrtFunc(source, c0->Type()), c0); + }; + + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::tan(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + return CreateScalar(source, c0->Type(), NumberT(std::tan(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::tanh(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) -> Eval::Result { + using NumberT = decltype(i); + return CreateScalar(source, c0->Type(), NumberT(std::tanh(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::transpose(const core::type::Type* ty, + VectorRef args, + const Source&) { + auto* m = args[0]; + auto* mat_ty = m->Type()->As(); + auto me = [&](size_t r, size_t c) { return m->Index(c)->Index(r); }; + auto* result_mat_ty = ty->As(); + + // Produce column vectors from each row + Vector result_mat; + for (size_t r = 0; r < mat_ty->Rows(); ++r) { + Vector new_col_vec; + for (size_t c = 0; c < mat_ty->Columns(); ++c) { + new_col_vec.Push(me(r, c)); + } + result_mat.Push(mgr.Composite(result_mat_ty->ColumnType(), new_col_vec)); + } + return mgr.Composite(ty, result_mat); +} + +Eval::Result Eval::trunc(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c0) { + auto create = [&](auto i) { + return CreateScalar(source, c0->Type(), decltype(i)(std::trunc(i.value))); + }; + return Dispatch_fa_f32_f16(create, c0); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::unpack2x16float(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(2); + for (size_t i = 0; i < 2; ++i) { + auto in = f16::FromBits(uint16_t((e >> (16 * i)) & 0x0000'ffff)); + auto val = CheckedConvert(in); + if (val != Success) { + AddError(source) << OverflowErrorMessage(in, "f32"); + if (!use_runtime_semantics_) { + return Failure(); + } + val = f32(0.f); + } + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val.Get())); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::unpack2x16snorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(2); + for (size_t i = 0; i < 2; ++i) { + auto val = f32( + std::max(static_cast(int16_t((e >> (16 * i)) & 0x0000'ffff)) / 32767.f, -1.f)); + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val)); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::unpack2x16unorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(2); + for (size_t i = 0; i < 2; ++i) { + auto val = f32(static_cast(uint16_t((e >> (16 * i)) & 0x0000'ffff)) / 65535.f); + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val)); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::unpack4x8snorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(4); + for (size_t i = 0; i < 4; ++i) { + auto val = + f32(std::max(static_cast(int8_t((e >> (8 * i)) & 0x0000'00ff)) / 127.f, -1.f)); + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val)); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::unpack4x8unorm(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(4); + for (size_t i = 0; i < 4; ++i) { + auto val = f32(static_cast(uint8_t((e >> (8 * i)) & 0x0000'00ff)) / 255.f); + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val)); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::unpack4xI8(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(4); + + for (size_t i = 0; i < 4; ++i) { + uint8_t e_i = (e >> (8 * i)) & 0xff; + auto val = i32(*reinterpret_cast(&e_i)); + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val)); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::unpack4xU8(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto* inner_ty = ty->DeepestElement(); + auto e = args[0]->ValueAs().value; + + Vector els; + els.Reserve(4); + + for (size_t i = 0; i < 4; ++i) { + auto val = u32((e >> (8 * i)) & 0xff); + TINT_CHECK_RESULT_UNWRAP(el, CreateScalar(source, inner_ty, val)); + els.Push(el); + } + return mgr.Composite(ty, std::move(els)); +} + +Eval::Result Eval::quantizeToF16(const core::type::Type* ty, + VectorRef args, + const Source& source) { + auto transform = [&](const Value* c) -> Eval::Result { + auto value = c->ValueAs(); + auto conv = CheckedConvert(f16(value)); + if (conv != Success) { + AddError(source) << OverflowErrorMessage(value, "f16"); + if (use_runtime_semantics_) { + return mgr.Zero(c->Type()); + } + return Failure(); + } + return CreateScalar(source, c->Type(), conv.Get()); + }; + return TransformUnaryElements(mgr, ty, transform, args[0]); +} + +Eval::Result Eval::Convert(const core::type::Type* target_ty, + const Value* value, + const Source& source) { + if (value->Type() == target_ty) { + return value; + } + ConvertContext ctx{mgr, diags, source, use_runtime_semantics_}; + auto* converted = ConvertInternal(value, target_ty, ctx); + if (!converted) { + return Failure(); + } + return converted; +} + +diag::Diagnostic& Eval::AddError(const Source& source) const { + if (use_runtime_semantics_) { + return diags.AddWarning(source); + } + return diags.AddError(source); +} + +diag::Diagnostic& Eval::AddWarning(const Source& source) const { + return diags.AddWarning(source); +} + +diag::Diagnostic& Eval::AddNote(const Source& source) const { + return diags.AddNote(source); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/eval.h b/3rdparty/dawn/src/tint/lang/core/constant/eval.h new file mode 100644 index 000000000..17c5786c8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/eval.h @@ -0,0 +1,1349 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_EVAL_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_EVAL_H_ + +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint { +class Source; +} // namespace tint +namespace tint::core::constant { +class Manager; +class Value; +} // namespace tint::core::constant +namespace tint::diag { +class List; +} // namespace tint::diag + +namespace tint::core::constant { + +/// Eval performs shader creation-time (const-expression) expression evaluation. +class Eval { + public: + /// The result type of a method that may raise a diagnostic error, upon which the caller should + /// handle the error. Can be one of three distinct values: + /// * A non-null Value pointer. Returned when a expression resolves to a creation + /// time value. + /// * A null Value pointer. Returned when a expression cannot resolve to a creation time value, + /// but is otherwise legal. + using Result = tint::Result; + + /// Typedef for a constant evaluation function + using Function = Result (Eval::*)(const core::type::Type* result_ty, + VectorRef, + const Source&); + + /// Constructor + /// @param manager the constant manager + /// @param diagnostics the diagnostic list, used to report errors and warnings + /// @param use_runtime_semantics if `true`, use the behavior defined for runtime evaluation, and + /// emit overflow and range errors as warnings instead of errors + Eval(Manager& manager, diag::List& diagnostics, bool use_runtime_semantics = false); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Constant value evaluation methods + //////////////////////////////////////////////////////////////////////////////////////////////// + + /// @param ty the target type - must be an array or struct + /// @param args the input arguments + /// @return the constructed value, or null if the value cannot be calculated + Result ArrayOrStructCtor(const core::type::Type* ty, VectorRef args); + + /// @param obj the object being indexed. May be null, in which case Index() will still validate + /// the index is in bounds for the type. + /// @param obj_ty the type of the object being indexed. + /// @param idx the index value. + /// @param idx_source the source of the index expression + /// @return the result of the index, or null if the value cannot be calculated + Result Index(const Value* obj, + const core::type::Type* obj_ty, + const Value* idx, + const Source& idx_source); + + /// @param ty the result type + /// @param vector the vector being swizzled + /// @param indices the swizzle indices + /// @return the result of the swizzle, or null if the value cannot be calculated + Result Swizzle(const core::type::Type* ty, const Value* vector, VectorRef indices); + + /// Convert the `value` to `target_type` + /// @param ty the result type + /// @param value the value being converted + /// @param source the source location + /// @return the converted value, or null if the value cannot be calculated + Result Convert(const core::type::Type* ty, const Value* value, const Source& source); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Constant value evaluation methods, to be indirectly called via the intrinsic table + //////////////////////////////////////////////////////////////////////////////////////////////// + + /// Value conversion + /// @param ty the result type + /// @param args the input arguments + /// @param source the source location + /// @return the converted value, or null if the value cannot be calculated + Result Conv(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Zero value constructor + /// @param ty the result type + /// @param args the input arguments (no arguments provided) + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result Zero(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Identity value constructor + /// @param ty the result type + /// @param args the input arguments + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result Identity(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Vector splat constructor + /// @param ty the vector type + /// @param args the input arguments + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result VecSplat(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Vector constructor using scalars + /// @param ty the vector type + /// @param args the input arguments + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result VecInitS(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Vector constructor using a mix of scalars and smaller vectors + /// @param ty the vector type + /// @param args the input arguments + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result VecInitM(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Matrix constructor using scalar values + /// @param ty the matrix type + /// @param args the input arguments + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result MatInitS(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Matrix constructor using column vectors + /// @param ty the matrix type + /// @param args the input arguments + /// @param source the source location + /// @return the constructed value, or null if the value cannot be calculated + Result MatInitV(const core::type::Type* ty, VectorRef args, const Source& source); + + //////////////////////////////////////////////////////////////////////////// + // Unary Operators + //////////////////////////////////////////////////////////////////////////// + + /// Complement operator '~' + /// @param ty the integer type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Complement(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Unary minus operator '-' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result UnaryMinus(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Unary not operator '!' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Not(const core::type::Type* ty, VectorRef args, const Source& source); + + //////////////////////////////////////////////////////////////////////////// + // Binary Operators + //////////////////////////////////////////////////////////////////////////// + + /// Plus operator '+' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Plus(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Minus operator '-' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Minus(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Multiply operator '*' for the same type on the LHS and RHS + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Multiply(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Multiply operator '*' for matCxR * vecC + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result MultiplyMatVec(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Multiply operator '*' for vecR * matCxR + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result MultiplyVecMat(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Multiply operator '*' for matKxR * matCxK + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result MultiplyMatMat(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Divide operator '/' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Divide(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Modulo operator '%' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Modulo(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Equality operator '==' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Equal(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Inequality operator '!=' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result NotEqual(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Less than operator '<' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result LessThan(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Greater than operator '>' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result GreaterThan(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Less than or equal operator '<=' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result LessThanEqual(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Greater than or equal operator '>=' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result GreaterThanEqual(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Logical and operator '&&' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result LogicalAnd(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Logical or operator '||' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result LogicalOr(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Bitwise and operator '&' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result And(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Bitwise or operator '|' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Or(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Bitwise xor operator '^' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result Xor(const core::type::Type* ty, VectorRef args, const Source& source); + + /// Bitwise shift left operator '<<' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result ShiftLeft(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// Bitwise shift right operator '<<' + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result ShiftRight(const core::type::Type* ty, + VectorRef args, + const Source& source); + + //////////////////////////////////////////////////////////////////////////// + // Builtins + //////////////////////////////////////////////////////////////////////////// + + /// abs builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result abs(const core::type::Type* ty, VectorRef args, const Source& source); + + /// acos builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result acos(const core::type::Type* ty, VectorRef args, const Source& source); + + /// acosh builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result acosh(const core::type::Type* ty, VectorRef args, const Source& source); + + /// all builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result all(const core::type::Type* ty, VectorRef args, const Source& source); + + /// any builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result any(const core::type::Type* ty, VectorRef args, const Source& source); + + /// asin builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result asin(const core::type::Type* ty, VectorRef args, const Source& source); + + /// asinh builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result asinh(const core::type::Type* ty, VectorRef args, const Source& source); + + /// atan builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result atan(const core::type::Type* ty, VectorRef args, const Source& source); + + /// atanh builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result atanh(const core::type::Type* ty, VectorRef args, const Source& source); + + /// atan2 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result atan2(const core::type::Type* ty, VectorRef args, const Source& source); + + /// bitcast builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result bitcast(const core::type::Type* ty, VectorRef args, const Source& source); + + /// ceil builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result ceil(const core::type::Type* ty, VectorRef args, const Source& source); + + /// clamp builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result clamp(const core::type::Type* ty, VectorRef args, const Source& source); + + /// cos builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result cos(const core::type::Type* ty, VectorRef args, const Source& source); + + /// cosh builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result cosh(const core::type::Type* ty, VectorRef args, const Source& source); + + /// countLeadingZeros builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result countLeadingZeros(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// countOneBits builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result countOneBits(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// countTrailingZeros builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result countTrailingZeros(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// cross builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result cross(const core::type::Type* ty, VectorRef args, const Source& source); + + /// degrees builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location of the conversion + /// @return the result value, or null if the value cannot be calculated + Result degrees(const core::type::Type* ty, VectorRef args, const Source& source); + + /// determinant builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location of the conversion + /// @return the result value, or null if the value cannot be calculated + Result determinant(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// distance builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location of the conversion + /// @return the result value, or null if the value cannot be calculated + Result distance(const core::type::Type* ty, VectorRef args, const Source& source); + + /// dot builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result dot(const core::type::Type* ty, VectorRef args, const Source& source); + + /// dot4I8Packed builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result dot4I8Packed(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// dot4U8Packed builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result dot4U8Packed(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// exp builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result exp(const core::type::Type* ty, VectorRef args, const Source& source); + + /// exp2 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result exp2(const core::type::Type* ty, VectorRef args, const Source& source); + + /// extractBits builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result extractBits(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// faceForward builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result faceForward(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// firstLeadingBit builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result firstLeadingBit(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// firstTrailingBit builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result firstTrailingBit(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// floor builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result floor(const core::type::Type* ty, VectorRef args, const Source& source); + + /// fma builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result fma(const core::type::Type* ty, VectorRef args, const Source& source); + + /// fract builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result fract(const core::type::Type* ty, VectorRef args, const Source& source); + + /// frexp builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result frexp(const core::type::Type* ty, VectorRef args, const Source& source); + + /// insertBits builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result insertBits(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// inverseSqrt builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result inverseSqrt(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// ldexp builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result ldexp(const core::type::Type* ty, VectorRef args, const Source& source); + + /// length builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result length(const core::type::Type* ty, VectorRef args, const Source& source); + + /// log builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result log(const core::type::Type* ty, VectorRef args, const Source& source); + + /// log2 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result log2(const core::type::Type* ty, VectorRef args, const Source& source); + + /// max builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + // NOLINTNEXTLINE(build/include_what_you_use) This isn't std::max ... + Result max(const core::type::Type* ty, VectorRef args, const Source& source); + + /// min builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result min( + const core::type::Type* ty, // NOLINT(build/include_what_you_use) -- confused by min + VectorRef args, + const Source& source); + + /// mix builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result mix(const core::type::Type* ty, VectorRef args, const Source& source); + + /// modf builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result modf(const core::type::Type* ty, VectorRef args, const Source& source); + + /// normalize builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result normalize(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack2x16float builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack2x16float(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack2x16snorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack2x16snorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack2x16unorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack2x16unorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack4x8snorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack4x8snorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack4x8unorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack4x8unorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack4xI8 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack4xI8(const core::type::Type* ty, VectorRef args, const Source& source); + + /// pack4xU8 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack4xU8(const core::type::Type* ty, VectorRef args, const Source& source); + + /// pack4xI8Clamp builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack4xI8Clamp(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pack4xU8Clamp builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pack4xU8Clamp(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// pow builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result pow(const core::type::Type* ty, VectorRef args, const Source& source); + + /// radians builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location of the conversion + /// @return the result value, or null if the value cannot be calculated + Result radians(const core::type::Type* ty, VectorRef args, const Source& source); + + /// reflect builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location of the conversion + /// @return the result value, or null if the value cannot be calculated + Result reflect(const core::type::Type* ty, VectorRef args, const Source& source); + + /// refract builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location of the conversion + /// @return the result value, or null if the value cannot be calculated + Result refract(const core::type::Type* ty, VectorRef args, const Source& source); + + /// reverseBits builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result reverseBits(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// round builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result round(const core::type::Type* ty, VectorRef args, const Source& source); + + /// saturate builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result saturate(const core::type::Type* ty, VectorRef args, const Source& source); + + /// select builtin with single bool third arg + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result select_bool(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// select builtin with vector of bool third arg + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result select_boolvec(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// sign builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result sign(const core::type::Type* ty, VectorRef args, const Source& source); + + /// sin builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result sin(const core::type::Type* ty, VectorRef args, const Source& source); + + /// sinh builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result sinh(const core::type::Type* ty, VectorRef args, const Source& source); + + /// smoothstep builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result smoothstep(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// step builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result step(const core::type::Type* ty, VectorRef args, const Source& source); + + /// sqrt builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result sqrt(const core::type::Type* ty, VectorRef args, const Source& source); + + /// tan builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result tan(const core::type::Type* ty, VectorRef args, const Source& source); + + /// tanh builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result tanh(const core::type::Type* ty, VectorRef args, const Source& source); + + /// transpose builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result transpose(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// trunc builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result trunc(const core::type::Type* ty, VectorRef args, const Source& source); + + /// unpack2x16float builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack2x16float(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// unpack2x16snorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack2x16snorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// unpack2x16unorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack2x16unorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// unpack4x8snorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack4x8snorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// unpack4x8unorm builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack4x8unorm(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// unpack4xI8 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack4xI8(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// unpack4xU8 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result unpack4xU8(const core::type::Type* ty, + VectorRef args, + const Source& source); + + /// quantizeToF16 builtin + /// @param ty the expression type + /// @param args the input arguments + /// @param source the source location + /// @return the result value, or null if the value cannot be calculated + Result quantizeToF16(const core::type::Type* ty, + VectorRef args, + const Source& source); + + private: + /// @returns a new error diagnostic + diag::Diagnostic& AddError(const Source& source) const; + + /// @returns a new warning diagnostic + diag::Diagnostic& AddWarning(const Source& source) const; + + /// @returns a new note diagnostic + diag::Diagnostic& AddNote(const Source& source) const; + + /// CreateScalar constructs and returns a constant::Scalar. + /// @param source the source location + /// @param t the result type + /// @param v the scalar value + /// @return the constant value with the same type and value + template + Eval::Result CreateScalar(const Source& source, const core::type::Type* t, T v); + + /// Adds two Numbers + /// @param source the source location + /// @param a the lhs number + /// @param b the rhs number + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Add(const Source& source, NumberT a, NumberT b); + + /// Subtracts two Numbers + /// @param source the source location + /// @param a the lhs number + /// @param b the rhs number + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Sub(const Source& source, NumberT a, NumberT b); + + /// Multiplies two Numbers + /// @param source the source location + /// @param a the lhs number + /// @param b the rhs number + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Mul(const Source& source, NumberT a, NumberT b); + + /// Divides two Numbers + /// @param source the source location + /// @param a the lhs number + /// @param b the rhs number + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Div(const Source& source, NumberT a, NumberT b); + + /// Returns the (signed) remainder of the division of two Numbers + /// @param source the source location + /// @param a the lhs number + /// @param b the rhs number + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Mod(const Source& source, NumberT a, NumberT b); + + /// Returns the dot product of (a1,a2) with (b1,b2) + /// @param source the source location + /// @param a1 component 1 of lhs vector + /// @param a2 component 2 of lhs vector + /// @param b1 component 1 of rhs vector + /// @param b2 component 2 of rhs vector + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Dot2(const Source& source, + NumberT a1, + NumberT a2, + NumberT b1, + NumberT b2); + + /// Returns the dot product of (a1,a2,a3) with (b1,b2,b3) + /// @param source the source location + /// @param a1 component 1 of lhs vector + /// @param a2 component 2 of lhs vector + /// @param a3 component 3 of lhs vector + /// @param b1 component 1 of rhs vector + /// @param b2 component 2 of rhs vector + /// @param b3 component 3 of rhs vector + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Dot3(const Source& source, + NumberT a1, + NumberT a2, + NumberT a3, + NumberT b1, + NumberT b2, + NumberT b3); + + /// Returns the dot product of (a1,b1,c1,d1) with (a2,b2,c2,d2) + /// @param source the source location + /// @param a1 component 1 of lhs vector + /// @param a2 component 2 of lhs vector + /// @param a3 component 3 of lhs vector + /// @param a4 component 4 of lhs vector + /// @param b1 component 1 of rhs vector + /// @param b2 component 2 of rhs vector + /// @param b3 component 3 of rhs vector + /// @param b4 component 4 of rhs vector + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Dot4(const Source& source, + NumberT a1, + NumberT a2, + NumberT a3, + NumberT a4, + NumberT b1, + NumberT b2, + NumberT b3, + NumberT b4); + + /// Returns the determinant of the 2x2 matrix: + /// | a c | + /// | b d | + /// @param source the source location + /// @param a component 1 of the first column vector + /// @param b component 2 of the first column vector + /// @param c component 1 of the second column vector + /// @param d component 2 of the second column vector + template + tint::Result Det2(const Source& source, // + NumberT a, + NumberT b, + NumberT c, + NumberT d); + + /// Returns the determinant of the 3x3 matrix: + /// | a d g | + /// | b e h | + /// | c f i | + /// @param source the source location + /// @param a component 1 of the first column vector + /// @param b component 2 of the first column vector + /// @param c component 3 of the first column vector + /// @param d component 1 of the second column vector + /// @param e component 2 of the second column vector + /// @param f component 3 of the second column vector + /// @param g component 1 of the third column vector + /// @param h component 2 of the third column vector + /// @param i component 3 of the third column vector + template + tint::Result Det3(const Source& source, + NumberT a, + NumberT b, + NumberT c, + NumberT d, + NumberT e, + NumberT f, + NumberT g, + NumberT h, + NumberT i); + + /// Returns the determinant of the 4x4 matrix: + /// | a e i m | + /// | b f j n | + /// | c g k o | + /// | d h l p | + /// @param source the source location + /// @param a component 1 of the first column vector + /// @param b component 2 of the first column vector + /// @param c component 3 of the first column vector + /// @param d component 4 of the first column vector + /// @param e component 1 of the second column vector + /// @param f component 2 of the second column vector + /// @param g component 3 of the second column vector + /// @param h component 4 of the second column vector + /// @param i component 1 of the third column vector + /// @param j component 2 of the third column vector + /// @param k component 3 of the third column vector + /// @param l component 4 of the third column vector + /// @param m component 1 of the fourth column vector + /// @param n component 2 of the fourth column vector + /// @param o component 3 of the fourth column vector + /// @param p component 4 of the fourth column vector + template + tint::Result Det4(const Source& source, + NumberT a, + NumberT b, + NumberT c, + NumberT d, + NumberT e, + NumberT f, + NumberT g, + NumberT h, + NumberT i, + NumberT j, + NumberT k, + NumberT l, + NumberT m, + NumberT n, + NumberT o, + NumberT p); + + template + tint::Result Sqrt(const Source& source, NumberT v); + + /// Clamps e between low and high + /// @param source the source location + /// @param e the number to clamp + /// @param low the lower bound + /// @param high the upper bound + /// @returns the result number on success, or logs an error and returns Failure + template + tint::Result Clamp(const Source& source, NumberT e, NumberT low, NumberT high); + + /// Returns a callable that calls Add, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto AddFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Sub, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto SubFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Mul, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto MulFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Div, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto DivFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Mod, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto ModFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Dot2, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto Dot2Func(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Dot3, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto Dot3Func(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Dot4, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto Dot4Func(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Det2, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto Det2Func(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Det3, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto Det3Func(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Det4, and creates a Constant with its result of type `elem_ty` + /// if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto Det4Func(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls Clamp, and creates a Constant with its result of type + /// `elem_ty` if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto ClampFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns a callable that calls SqrtFunc, and creates a Constant with its + /// result of type `elem_ty` if successful, or returns Failure otherwise. + /// @param source the source location + /// @param elem_ty the element type of the Constant to create on success + /// @returns the callable function + auto SqrtFunc(const Source& source, const core::type::Type* elem_ty); + + /// Returns the dot product of v1 and v2. + /// @param source the source location + /// @param v1 the first vector + /// @param v2 the second vector + /// @returns the dot product + Result Dot(const Source& source, const Value* v1, const Value* v2); + + /// Returns the length of c0 + /// @param source the source location + /// @param ty the return type + /// @param c0 the constant to calculate the length of + /// @returns the length of c0 + Result Length(const Source& source, const core::type::Type* ty, const Value* c0); + + /// Returns the product of v1 and v2 + /// @param source the source location + /// @param ty the return type + /// @param v1 lhs value + /// @param v2 rhs value + /// @returns the product of v1 and v2 + Result Mul(const Source& source, const core::type::Type* ty, const Value* v1, const Value* v2); + + /// Returns the difference between v2 and v1 + /// @param source the source location + /// @param ty the return type + /// @param v1 lhs value + /// @param v2 rhs value + /// @returns the difference between v2 and v1 + Result Sub(const Source& source, const core::type::Type* ty, const Value* v1, const Value* v2); + + private: + Manager& mgr; + diag::List& diags; + bool use_runtime_semantics_ = false; +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_EVAL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/invalid.cc b/3rdparty/dawn/src/tint/lang/core/constant/invalid.cc new file mode 100644 index 000000000..ecf434ac5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/invalid.cc @@ -0,0 +1,45 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/invalid.h" + +#include "src/tint/lang/core/constant/manager.h" +#include "src/tint/lang/core/type/invalid.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Invalid); + +namespace tint::core::constant { + +Invalid::Invalid(const core::type::Invalid* ty) : type(ty) {} + +Invalid::~Invalid() = default; + +const Invalid* Invalid::Clone(CloneContext& ctx) const { + return ctx.dst.Invalid(); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/invalid.h b/3rdparty/dawn/src/tint/lang/core/constant/invalid.h new file mode 100644 index 000000000..df4b68a1c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/invalid.h @@ -0,0 +1,81 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_INVALID_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_INVALID_H_ + +#include +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/invalid.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// Invalid represents an invalid constant, used as a placeholder in a failed parse / resolve. +class Invalid : public Castable { + public: + /// Constructor + /// @param ty the Invalid type + explicit Invalid(const core::type::Invalid* ty); + ~Invalid() override; + + /// @returns the type of the Invalid + const core::type::Type* Type() const override { return type; } + + /// Retrieve item at index @p i + /// @param i the index to retrieve + /// @returns the element, or nullptr if out of bounds + const Value* Index([[maybe_unused]] size_t i) const override { return nullptr; } + + /// @copydoc Value::NumElements() + size_t NumElements() const override { return 0; } + + /// @returns true if the element is zero + bool AllZero() const override { return false; } + /// @returns true if the element is zero + bool AnyZero() const override { return false; } + + /// @returns the hash for the Invalid + HashCode Hash() const override { return tint::Hash(type); } + + /// Clones the constant into the provided context + /// @param ctx the clone context + /// @returns the cloned node + const Invalid* Clone(CloneContext& ctx) const override; + + /// The Invalid type + core::type::Invalid const* const type; + + protected: + /// @returns a monostate variant. + std::variant InternalValue() const override { return {}; } +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_INVALID_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/manager.cc b/3rdparty/dawn/src/tint/lang/core/constant/manager.cc new file mode 100644 index 000000000..2312bd68c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/manager.cc @@ -0,0 +1,197 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/manager.h" + +#include "src/tint/lang/core/constant/composite.h" +#include "src/tint/lang/core/constant/invalid.h" +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/constant/splat.h" +#include "src/tint/lang/core/constant/string.h" +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u64.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/containers/predicates.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::constant { + +Manager::Manager() = default; + +Manager::Manager(Manager&&) = default; + +Manager& Manager::operator=(Manager&& rhs) = default; + +Manager::~Manager() = default; + +const constant::Value* Manager::Composite(const core::type::Type* type, + VectorRef elements) { + if (elements.IsEmpty()) { + return nullptr; + } + + bool any_zero = false; + bool all_zero = true; + bool all_equal = true; + auto* first = elements.Front(); + for (auto* el : elements) { + if (DAWN_UNLIKELY(!el)) { + return nullptr; + } + if (!any_zero && el->AnyZero()) { + any_zero = true; + } + if (all_zero && !el->AllZero()) { + all_zero = false; + } + if (all_equal && el != first) { + all_equal = false; + } + } + if (all_equal) { + return Splat(type, elements.Front()); + } + + return Get(type, std::move(elements), all_zero, any_zero); +} + +const constant::Splat* Manager::Splat(const core::type::Type* type, + const constant::Value* element) { + return Get(type, element); +} + +const Scalar* Manager::Get(i32 value) { + return Get>(types.i32(), value); +} + +const Scalar* Manager::Get(u32 value) { + return Get>(types.u32(), value); +} + +const Scalar* Manager::Get(u64 value) { + return Get>(types.u64(), value); +} + +const Scalar* Manager::Get(i8 value) { + return Get>(types.i8(), value); +} + +const Scalar* Manager::Get(u8 value) { + return Get>(types.u8(), value); +} + +const Scalar* Manager::Get(f32 value) { + return Get>(types.f32(), value); +} + +const Scalar* Manager::Get(f16 value) { + return Get>(types.f16(), value); +} + +const Scalar* Manager::Get(bool value) { + return Get>(types.bool_(), value); +} + +const Scalar* Manager::Get(AFloat value) { + return Get>(types.AFloat(), value); +} + +const Scalar* Manager::Get(AInt value) { + return Get>(types.AInt(), value); +} + +const constant::String* Manager::Get(std::string_view value) { + return Get(types.String(), value); +} + +const Value* Manager::Zero(const core::type::Type* type) { + return Switch( + type, // + [&](const core::type::Vector* v) -> const Value* { + auto* zero_el = Zero(v->Type()); + return Splat(type, zero_el); + }, + [&](const core::type::Matrix* m) -> const Value* { + auto* zero_el = Zero(m->ColumnType()); + return Splat(type, zero_el); + }, + [&](const core::type::Array* a) -> const Value* { + if (a->ConstantCount()) { + if (auto* zero_el = Zero(a->ElemType())) { + return Splat(type, zero_el); + } + } + return nullptr; + }, + [&](const core::type::Struct* s) -> const Value* { + Hashmap zero_by_type; + Vector zeros; + zeros.Reserve(s->Members().Length()); + for (auto* member : s->Members()) { + auto* zero = + zero_by_type.GetOrAdd(member->Type(), [&] { return Zero(member->Type()); }); + if (!zero) { + return nullptr; + } + zeros.Push(zero); + } + if (zero_by_type.Count() == 1) { + // All members were of the same type, so the zero value is the same for all members. + return Splat(type, zeros[0]); + } + return Composite(s, std::move(zeros)); + }, + [&](const core::type::AbstractInt*) { return Get(AInt(0)); }, // + [&](const core::type::AbstractFloat*) { return Get(AFloat(0)); }, // + [&](const core::type::I32*) { return Get(i32(0)); }, // + [&](const core::type::U32*) { return Get(u32(0)); }, // + [&](const core::type::I8*) { return Get(i8(0)); }, // + [&](const core::type::U8*) { return Get(u8(0)); }, // + [&](const core::type::U64*) { return Get(u64(0)); }, // + [&](const core::type::F32*) { return Get(f32(0)); }, // + [&](const core::type::F16*) { return Get(f16(0)); }, // + [&](const core::type::Bool*) { return Get(false); }, // + [&](const core::type::Invalid*) { return Invalid(); }, // + TINT_ICE_ON_NO_MATCH); +} + +const constant::Invalid* Manager::Invalid() { + return values_.Get(types.invalid()); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/manager.h b/3rdparty/dawn/src/tint/lang/core/constant/manager.h new file mode 100644 index 000000000..2b6f774ed --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/manager.h @@ -0,0 +1,181 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_MANAGER_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_MANAGER_H_ + +#include + +#include "src/tint/lang/core/constant/invalid.h" +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/containers/unique_allocator.h" +#include "src/tint/utils/math/hash.h" + +namespace tint::core::constant { +class Splat; +class String; + +template +class Scalar; +} // namespace tint::core::constant + +namespace tint::core::constant { + +/// The constant manager holds a type manager and all the pointers to the known constant values. +class Manager final { + public: + /// Iterator is the type returned by begin() and end() + using TypeIterator = BlockAllocator::ConstIterator; + + /// Constructor + Manager(); + + /// Move constructor + Manager(Manager&&); + + /// Move assignment operator + /// @param rhs the Manager to move + /// @return this Manager + Manager& operator=(Manager&& rhs); + + /// Destructor + ~Manager(); + + /// @param args the arguments used to construct the type, unique node or node. + /// @return a pointer to an instance of `T` with the provided arguments. + /// If NODE derives from UniqueNode and an existing instance of `T` has been + /// constructed, then the same pointer is returned. + template + NODE* Get(ARGS&&... args) { + return values_.Get(std::forward(args)...); + } + + /// @returns an iterator to the beginning of the types + TypeIterator begin() const { return values_.begin(); } + /// @returns an iterator to the end of the types + TypeIterator end() const { return values_.end(); } + + /// Constructs a constant of a vector, matrix or array type. + /// + /// Examines the element values and will return either a constant::Composite or a + /// constant::Splat, depending on the element types and values. + /// + /// @param type the composite type + /// @param elements the composite elements + /// @returns the value pointer + const constant::Value* Composite(const core::type::Type* type, + VectorRef elements); + + /// Constructs a splat constant. + /// @param type the splat type + /// @param element the splat element + /// @returns the value pointer + const constant::Splat* Splat(const core::type::Type* type, const constant::Value* element); + + /// @param value the constant value + /// @return a Scalar holding the i32 value @p value + const Scalar* Get(i32 value); + + /// @param value the constant value + /// @return a Scalar holding the u32 value @p value + const Scalar* Get(u32 value); + + /// @param value the constant value + /// @return a Scalar holding the u64 value @p value + const Scalar* Get(u64 value); + + /// @param value the constant value + /// @return a Scalar holding the i8 value @p value + const Scalar* Get(i8 value); + + /// @param value the constant value + /// @return a Scalar holding the u8 value @p value + const Scalar* Get(u8 value); + + /// @param value the constant value + /// @return a Scalar holding the f32 value @p value + const Scalar* Get(f32 value); + + /// @param value the constant value + /// @return a Scalar holding the f16 value @p value + const Scalar* Get(f16 value); + + /// @param value the constant value + /// @return a Scalar holding the bool value @p value + const Scalar* Get(bool value); + + /// @param value the constant value + /// @return a Scalar holding the AFloat value @p value + const Scalar* Get(AFloat value); + + /// @param value the constant value + /// @return a Scalar holding the AInt value @p value + const Scalar* Get(AInt value); + + /// @param value the string value + /// @return a String holding the value @p value + const String* Get(std::string_view value); + + /// Constructs a constant zero-value of the type @p type. + /// @param type the constant type + /// @returns a constant zero-value for the type + const Value* Zero(const core::type::Type* type); + + /// Constructs an invalid constant + /// @returns an invalid constant + const constant::Invalid* Invalid(); + + /// The type manager + core::type::Manager types; + + private: + /// A specialization of Hasher for constant::Value + struct Hasher { + /// @param value the value to hash + /// @returns a hash of the value + HashCode operator()(const constant::Value& value) const { return value.Hash(); } + }; + + /// An equality helper for constant::Value + struct Equal { + /// @param a the LHS value + /// @param b the RHS value + /// @returns true if the two constants are equal + bool operator()(const constant::Value& a, const constant::Value& b) const { + return a.Equal(&b); + } + }; + + /// Unique types owned by the manager + UniqueAllocator values_; +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_MANAGER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/node.cc b/3rdparty/dawn/src/tint/lang/core/constant/node.cc new file mode 100644 index 000000000..784fe2ba1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/node.cc @@ -0,0 +1,40 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/node.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Node); + +namespace tint::core::constant { + +Node::Node() = default; + +Node::Node(const Node&) = default; + +Node::~Node() = default; + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/node.h b/3rdparty/dawn/src/tint/lang/core/constant/node.h new file mode 100644 index 000000000..892c8824a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/node.h @@ -0,0 +1,50 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_NODE_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_NODE_H_ + +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// Node is the base class for all constant nodes +class Node : public Castable { + public: + /// Constructor + Node(); + + /// Copy constructor + Node(const Node&); + + /// Destructor + ~Node() override; +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_NODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/scalar.cc b/3rdparty/dawn/src/tint/lang/core/constant/scalar.cc new file mode 100644 index 000000000..00614d208 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/scalar.cc @@ -0,0 +1,46 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/scalar.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::ScalarBase); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Scalar); + +namespace tint::core::constant { + +ScalarBase::~ScalarBase() = default; + +} diff --git a/3rdparty/dawn/src/tint/lang/core/constant/scalar.h b/3rdparty/dawn/src/tint/lang/core/constant/scalar.h new file mode 100644 index 000000000..29a3c6911 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/scalar.h @@ -0,0 +1,125 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_SCALAR_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_SCALAR_H_ + +#include "src/tint/lang/core/constant/manager.h" +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// ScalarBase is the base class of all Scalar specializations. +/// Used for querying whether a value is a scalar type. +class ScalarBase : public Castable { + public: + ~ScalarBase() override; +}; + +/// Scalar holds a single scalar or abstract-numeric value. +template +class Scalar : public Castable, ScalarBase> { + public: + static_assert(!std::is_same_v, T> || std::is_same_v, + "T must be a Number or bool"); + + /// Constructor + /// @param t the scalar type + /// @param v the scalar value + Scalar(const core::type::Type* t, T v) : type(t), value(v) { + if constexpr (IsFloatingPoint) { + TINT_ASSERT(std::isfinite(v.value)); + } + } + ~Scalar() override = default; + + /// @copydoc Value::Type() + const core::type::Type* Type() const override { return type; } + + /// @return nullptr, as Scalar does not hold any elements. + const Value* Index(size_t) const override { return nullptr; } + + /// @copydoc Value::NumElements() + size_t NumElements() const override { return 1; } + + /// @copydoc Value::AllZero() + bool AllZero() const override { return IsZero(); } + + /// @copydoc Value::AnyZero() + bool AnyZero() const override { return IsZero(); } + + /// @copydoc Value::Hash() + HashCode Hash() const override { return tint::Hash(type, ValueOf()); } + + /// Clones the constant into the provided context + /// @param ctx the clone context + /// @returns the cloned node + const Scalar* Clone(CloneContext& ctx) const override { + auto* ty = type->Clone(ctx.type_ctx); + return ctx.dst.Get>(ty, value); + } + + /// @returns `value` if `T` is not a Number, otherwise ValueOf returns the inner value of the + /// Number. + inline auto ValueOf() const { + if constexpr (std::is_same_v, T>) { + return value; + } else { + return value.value; + } + } + + /// @returns true if `value` is zero. + /// For floating point -0.0 equals 0.0, according to IEEE 754. + inline bool IsZero() const { + using N = UnwrapNumber; + return Number(value) == Number(0); + } + + /// The scalar type + core::type::Type const* const type; + /// The scalar value + const T value; + + protected: + /// @copydoc Value::InternalValue() + std::variant InternalValue() const override { + if constexpr (IsFloatingPoint>) { + return static_cast(value); + } else { + return static_cast(value); + } + } +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_SCALAR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/splat.cc b/3rdparty/dawn/src/tint/lang/core/constant/splat.cc new file mode 100644 index 000000000..187d4c87c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/splat.cc @@ -0,0 +1,61 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/splat.h" + +#include "src/tint/lang/core/constant/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Splat); + +namespace tint::core::constant { + +namespace { + +/// Asserts that the element type of @p in_type matches the type of @p value, and that the type has +/// at least one element. +/// @returns the number of elements in @p in_type +inline size_t GetCountAndAssertType(const core::type::Type* in_type, const constant::Value* value) { + auto elements = in_type->Elements(); + TINT_ASSERT(!elements.type || elements.type == value->Type()); + TINT_ASSERT(elements.count > 0); + return elements.count; +} + +} // namespace + +Splat::Splat(const core::type::Type* t, const constant::Value* e) + : type(t), el(e), count(GetCountAndAssertType(t, e)) {} + +Splat::~Splat() = default; + +const Splat* Splat::Clone(CloneContext& ctx) const { + auto* ty = type->Clone(ctx.type_ctx); + auto* element = el->Clone(ctx); + return ctx.dst.Splat(ty, element); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/splat.h b/3rdparty/dawn/src/tint/lang/core/constant/splat.h new file mode 100644 index 000000000..def9bfebc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/splat.h @@ -0,0 +1,88 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_SPLAT_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_SPLAT_H_ + +#include "src/tint/lang/core/constant/composite.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// Splat holds a single value, duplicated as all children. +/// +/// Splat is used for zero-initializers, 'splat' initializers, or initializers where each element is +/// identical. Splat may be of a vector, matrix, array or structure type. +class Splat : public Castable { + public: + /// Constructor + /// @param t the splat type + /// @param e the splat element + Splat(const core::type::Type* t, const Value* e); + ~Splat() override; + + /// @returns the type of the splat + const core::type::Type* Type() const override { return type; } + + /// Retrieve item at index @p i + /// @param i the index to retrieve + /// @returns the element, or nullptr if out of bounds + const Value* Index(size_t i) const override { return i < count ? el : nullptr; } + + /// @copydoc Value::NumElements() + size_t NumElements() const override { return count; } + + /// @returns true if the element is zero + bool AllZero() const override { return el->AllZero(); } + /// @returns true if the element is zero + bool AnyZero() const override { return el->AnyZero(); } + + /// @returns the hash for the splat + HashCode Hash() const override { return tint::Hash(type, el->Hash(), count); } + + /// Clones the constant into the provided context + /// @param ctx the clone context + /// @returns the cloned node + const Splat* Clone(CloneContext& ctx) const override; + + /// The type of the splat element + core::type::Type const* const type; + /// The element stored in the splat + const Value* el; + /// The number of items in the splat + const size_t count; + + protected: + /// @returns a monostate variant. + std::variant InternalValue() const override { return {}; } +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_SPLAT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/string.cc b/3rdparty/dawn/src/tint/lang/core/constant/string.cc new file mode 100644 index 000000000..0151678ee --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/string.cc @@ -0,0 +1,39 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/string.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::String); + +namespace tint::core::constant { + +const String* String::Clone(CloneContext& ctx) const { + auto* ty = type->Clone(ctx.type_ctx); + return ctx.dst.Get(ty, value); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/string.h b/3rdparty/dawn/src/tint/lang/core/constant/string.h new file mode 100644 index 000000000..06fd417e7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/string.h @@ -0,0 +1,89 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_STRING_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_STRING_H_ + +#include + +#include "src/tint/lang/core/constant/manager.h" +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/type/string.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// String holds a constant string value. +class String : public Castable { + public: + /// Constructor + /// @param t the scalar type + /// @param v the scalar value + String(const core::type::Type* t, std::string_view v) : type(t), value(v) {} + ~String() override = default; + + /// @copydoc Value::Type() + const core::type::Type* Type() const override { return type; } + + /// @return nullptr, as String does not allow individual character access + const Value* Index(size_t) const override { return nullptr; } + + /// @copydoc Value::NumElements() + size_t NumElements() const override { return 1; } + + /// @copydoc Value::AllZero() + bool AllZero() const override { return false; } + + /// @copydoc Value::AnyZero() + bool AnyZero() const override { return false; } + + /// @copydoc Value::Hash() + HashCode Hash() const override { return tint::Hash(type, Value()); } + + /// Clones the constant into the provided context + /// @param ctx the clone context + /// @returns the cloned node + const String* Clone(CloneContext& ctx) const override; + + /// @returns the string value + inline std::string_view Value() const { return value; } + + /// The string type + core::type::Type const* const type; + /// The string value + const std::string value; + + protected: + /// @copydoc Value::InternalValue() + std::variant InternalValue() const override { return {}; } +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_STRING_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/constant/value.cc b/3rdparty/dawn/src/tint/lang/core/constant/value.cc new file mode 100644 index 000000000..195ee8222 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/value.cc @@ -0,0 +1,114 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/constant/value.h" + +#include "src/tint/lang/core/constant/splat.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/invalid.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/rtti/switch.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Value); + +namespace tint::core::constant { + +Value::Value() = default; + +Value::~Value() = default; + +/// Equal returns true if the constants `a` and `b` are of the same type and value. +bool Value::Equal(const constant::Value* b) const { + if (this == b) { + return true; + } + if (Hash() != b->Hash()) { + return false; + } + if (Type() != b->Type()) { + return false; + } + + auto elements_equal = [&](size_t count) { + if (count == 0) { + return true; + } + + // Avoid per-element comparisons if the constants are splats + bool a_is_splat = Is(); + bool b_is_splat = b->Is(); + if (a_is_splat && b_is_splat) { + return Index(0)->Equal(b->Index(0)); + } + + if (a_is_splat) { + auto* el_a = Index(0); + for (size_t i = 0; i < count; i++) { + if (!el_a->Equal(b->Index(i))) { + return false; + } + } + return true; + } + + if (b_is_splat) { + auto* el_b = b->Index(0); + for (size_t i = 0; i < count; i++) { + if (!Index(i)->Equal(el_b)) { + return false; + } + } + return true; + } + + // Per-element comparison + for (size_t i = 0; i < count; i++) { + if (!Index(i)->Equal(b->Index(i))) { + return false; + } + } + return true; + }; + + return Switch( + Type(), // + [&](const core::type::Vector* vec) { return elements_equal(vec->Width()); }, + [&](const core::type::Matrix* mat) { return elements_equal(mat->Columns()); }, + [&](const core::type::Struct* str) { return elements_equal(str->Members().Length()); }, + [&](const core::type::Array* arr) { + if (auto n = arr->ConstantCount()) { + return elements_equal(*n); + } + return false; + }, + [&](const core::type::Invalid*) { return true; }, + [&](Default) { return InternalValue() == b->InternalValue(); }); +} + +} // namespace tint::core::constant diff --git a/3rdparty/dawn/src/tint/lang/core/constant/value.h b/3rdparty/dawn/src/tint/lang/core/constant/value.h new file mode 100644 index 000000000..c0ce0563a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/constant/value.h @@ -0,0 +1,106 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_CONSTANT_VALUE_H_ +#define SRC_TINT_LANG_CORE_CONSTANT_VALUE_H_ + +#include + +#include "src/tint/lang/core/constant/clone_context.h" +#include "src/tint/lang/core/constant/node.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::constant { + +/// Value is the interface to a compile-time evaluated expression value. +class Value : public Castable { + public: + /// Constructor + Value(); + + /// Destructor + ~Value() override; + + /// @returns the type of the value + virtual const core::type::Type* Type() const = 0; + + /// @param i the index of the element + /// @returns the child element with the given index, or nullptr if there are no children, or + /// the index is out of bounds. + /// + /// For arrays, this returns the i'th element of the array. + /// For vectors, this returns the i'th element of the vector. + /// For matrices, this returns the i'th column vector of the matrix. + /// For structures, this returns the i'th member field of the structure. + virtual const Value* Index(size_t i) const = 0; + + /// @return the number of elements held by this Value + virtual size_t NumElements() const = 0; + + /// @returns true if child elements are positive-zero valued. + virtual bool AllZero() const = 0; + + /// @returns true if any child elements are positive-zero valued. + virtual bool AnyZero() const = 0; + + /// @returns a hash of the value. + virtual HashCode Hash() const = 0; + + /// @returns the value as the given scalar or abstract value. + template + T ValueAs() const { + return std::visit( + [](auto v) { + if constexpr (std::is_same_v) { + return T(0); + } else { + return static_cast(v); + } + }, + InternalValue()); + } + + /// @param b the value to compare too + /// @returns true if this value is equal to @p b + bool Equal(const Value* b) const; + + /// Clones the constant into the provided context + /// @param ctx the clone context + /// @returns the cloned node + virtual const Value* Clone(CloneContext& ctx) const = 0; + + protected: + /// @returns the value, if this is of a scalar value or abstract numeric, otherwise + /// std::monostate. + virtual std::variant InternalValue() const = 0; +}; + +} // namespace tint::core::constant + +#endif // SRC_TINT_LANG_CORE_CONSTANT_VALUE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/enums.cc b/3rdparty/dawn/src/tint/lang/core/enums.cc new file mode 100644 index 000000000..164d7e73e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/enums.cc @@ -0,0 +1,2229 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/core/enums.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include "src/tint/lang/core/enums.h" + +namespace tint::core { + +/// ParseAccess parses a Access from a string. +/// @param str the string to parse +/// @returns the parsed enum, or Access::kUndefined if the string could not be parsed. +Access ParseAccess(std::string_view str) { + if (str == "read") { + return Access::kRead; + } + if (str == "read_write") { + return Access::kReadWrite; + } + if (str == "write") { + return Access::kWrite; + } + return Access::kUndefined; +} +std::string_view ToString(Access value) { + switch (value) { + case Access::kUndefined: + return "undefined"; + case Access::kRead: + return "read"; + case Access::kReadWrite: + return "read_write"; + case Access::kWrite: + return "write"; + } + return ""; +} + +/// ParseAddressSpace parses a AddressSpace from a string. +/// @param str the string to parse +/// @returns the parsed enum, or AddressSpace::kUndefined if the string could not be parsed. +AddressSpace ParseAddressSpace(std::string_view str) { + if (str == "function") { + return AddressSpace::kFunction; + } + if (str == "immediate") { + return AddressSpace::kImmediate; + } + if (str == "pixel_local") { + return AddressSpace::kPixelLocal; + } + if (str == "private") { + return AddressSpace::kPrivate; + } + if (str == "storage") { + return AddressSpace::kStorage; + } + if (str == "uniform") { + return AddressSpace::kUniform; + } + if (str == "workgroup") { + return AddressSpace::kWorkgroup; + } + return AddressSpace::kUndefined; +} +std::string_view ToString(AddressSpace value) { + switch (value) { + case AddressSpace::kUndefined: + return "undefined"; + case AddressSpace::kIn: + return "__in"; + case AddressSpace::kOut: + return "__out"; + case AddressSpace::kFunction: + return "function"; + case AddressSpace::kHandle: + return "handle"; + case AddressSpace::kImmediate: + return "immediate"; + case AddressSpace::kPixelLocal: + return "pixel_local"; + case AddressSpace::kPrivate: + return "private"; + case AddressSpace::kStorage: + return "storage"; + case AddressSpace::kUniform: + return "uniform"; + case AddressSpace::kWorkgroup: + return "workgroup"; + } + return ""; +} + +/// ParseInterpolationSampling parses a InterpolationSampling from a string. +/// @param str the string to parse +/// @returns the parsed enum, or InterpolationSampling::kUndefined if the string could not be parsed. +InterpolationSampling ParseInterpolationSampling(std::string_view str) { + if (str == "center") { + return InterpolationSampling::kCenter; + } + if (str == "centroid") { + return InterpolationSampling::kCentroid; + } + if (str == "either") { + return InterpolationSampling::kEither; + } + if (str == "first") { + return InterpolationSampling::kFirst; + } + if (str == "sample") { + return InterpolationSampling::kSample; + } + return InterpolationSampling::kUndefined; +} +std::string_view ToString(InterpolationSampling value) { + switch (value) { + case InterpolationSampling::kUndefined: + return "undefined"; + case InterpolationSampling::kCenter: + return "center"; + case InterpolationSampling::kCentroid: + return "centroid"; + case InterpolationSampling::kEither: + return "either"; + case InterpolationSampling::kFirst: + return "first"; + case InterpolationSampling::kSample: + return "sample"; + } + return ""; +} + +/// ParseInterpolationType parses a InterpolationType from a string. +/// @param str the string to parse +/// @returns the parsed enum, or InterpolationType::kUndefined if the string could not be parsed. +InterpolationType ParseInterpolationType(std::string_view str) { + if (str == "flat") { + return InterpolationType::kFlat; + } + if (str == "linear") { + return InterpolationType::kLinear; + } + if (str == "perspective") { + return InterpolationType::kPerspective; + } + return InterpolationType::kUndefined; +} +std::string_view ToString(InterpolationType value) { + switch (value) { + case InterpolationType::kUndefined: + return "undefined"; + case InterpolationType::kFlat: + return "flat"; + case InterpolationType::kLinear: + return "linear"; + case InterpolationType::kPerspective: + return "perspective"; + } + return ""; +} + +/// ParseSubgroupMatrixKind parses a SubgroupMatrixKind from a string. +/// @param str the string to parse +/// @returns the parsed enum, or SubgroupMatrixKind::kUndefined if the string could not be parsed. +SubgroupMatrixKind ParseSubgroupMatrixKind(std::string_view str) { + if (str == "left") { + return SubgroupMatrixKind::kLeft; + } + if (str == "result") { + return SubgroupMatrixKind::kResult; + } + if (str == "right") { + return SubgroupMatrixKind::kRight; + } + return SubgroupMatrixKind::kUndefined; +} +std::string_view ToString(SubgroupMatrixKind value) { + switch (value) { + case SubgroupMatrixKind::kUndefined: + return "undefined"; + case SubgroupMatrixKind::kLeft: + return "left"; + case SubgroupMatrixKind::kResult: + return "result"; + case SubgroupMatrixKind::kRight: + return "right"; + } + return ""; +} + +/// ParseTexelFormat parses a TexelFormat from a string. +/// @param str the string to parse +/// @returns the parsed enum, or TexelFormat::kUndefined if the string could not be parsed. +TexelFormat ParseTexelFormat(std::string_view str) { + if (str == "bgra8unorm") { + return TexelFormat::kBgra8Unorm; + } + if (str == "r16float") { + return TexelFormat::kR16Float; + } + if (str == "r16sint") { + return TexelFormat::kR16Sint; + } + if (str == "r16snorm") { + return TexelFormat::kR16Snorm; + } + if (str == "r16uint") { + return TexelFormat::kR16Uint; + } + if (str == "r16unorm") { + return TexelFormat::kR16Unorm; + } + if (str == "r32float") { + return TexelFormat::kR32Float; + } + if (str == "r32sint") { + return TexelFormat::kR32Sint; + } + if (str == "r32uint") { + return TexelFormat::kR32Uint; + } + if (str == "r8sint") { + return TexelFormat::kR8Sint; + } + if (str == "r8snorm") { + return TexelFormat::kR8Snorm; + } + if (str == "r8uint") { + return TexelFormat::kR8Uint; + } + if (str == "r8unorm") { + return TexelFormat::kR8Unorm; + } + if (str == "rg11b10ufloat") { + return TexelFormat::kRg11B10Ufloat; + } + if (str == "rg16float") { + return TexelFormat::kRg16Float; + } + if (str == "rg16sint") { + return TexelFormat::kRg16Sint; + } + if (str == "rg16snorm") { + return TexelFormat::kRg16Snorm; + } + if (str == "rg16uint") { + return TexelFormat::kRg16Uint; + } + if (str == "rg16unorm") { + return TexelFormat::kRg16Unorm; + } + if (str == "rg32float") { + return TexelFormat::kRg32Float; + } + if (str == "rg32sint") { + return TexelFormat::kRg32Sint; + } + if (str == "rg32uint") { + return TexelFormat::kRg32Uint; + } + if (str == "rg8sint") { + return TexelFormat::kRg8Sint; + } + if (str == "rg8snorm") { + return TexelFormat::kRg8Snorm; + } + if (str == "rg8uint") { + return TexelFormat::kRg8Uint; + } + if (str == "rg8unorm") { + return TexelFormat::kRg8Unorm; + } + if (str == "rgb10a2uint") { + return TexelFormat::kRgb10A2Uint; + } + if (str == "rgb10a2unorm") { + return TexelFormat::kRgb10A2Unorm; + } + if (str == "rgba16float") { + return TexelFormat::kRgba16Float; + } + if (str == "rgba16sint") { + return TexelFormat::kRgba16Sint; + } + if (str == "rgba16snorm") { + return TexelFormat::kRgba16Snorm; + } + if (str == "rgba16uint") { + return TexelFormat::kRgba16Uint; + } + if (str == "rgba16unorm") { + return TexelFormat::kRgba16Unorm; + } + if (str == "rgba32float") { + return TexelFormat::kRgba32Float; + } + if (str == "rgba32sint") { + return TexelFormat::kRgba32Sint; + } + if (str == "rgba32uint") { + return TexelFormat::kRgba32Uint; + } + if (str == "rgba8sint") { + return TexelFormat::kRgba8Sint; + } + if (str == "rgba8snorm") { + return TexelFormat::kRgba8Snorm; + } + if (str == "rgba8uint") { + return TexelFormat::kRgba8Uint; + } + if (str == "rgba8unorm") { + return TexelFormat::kRgba8Unorm; + } + return TexelFormat::kUndefined; +} +std::string_view ToString(TexelFormat value) { + switch (value) { + case TexelFormat::kUndefined: + return "undefined"; + case TexelFormat::kBgra8Unorm: + return "bgra8unorm"; + case TexelFormat::kR16Float: + return "r16float"; + case TexelFormat::kR16Sint: + return "r16sint"; + case TexelFormat::kR16Snorm: + return "r16snorm"; + case TexelFormat::kR16Uint: + return "r16uint"; + case TexelFormat::kR16Unorm: + return "r16unorm"; + case TexelFormat::kR32Float: + return "r32float"; + case TexelFormat::kR32Sint: + return "r32sint"; + case TexelFormat::kR32Uint: + return "r32uint"; + case TexelFormat::kR8Sint: + return "r8sint"; + case TexelFormat::kR8Snorm: + return "r8snorm"; + case TexelFormat::kR8Uint: + return "r8uint"; + case TexelFormat::kR8Unorm: + return "r8unorm"; + case TexelFormat::kRg11B10Ufloat: + return "rg11b10ufloat"; + case TexelFormat::kRg16Float: + return "rg16float"; + case TexelFormat::kRg16Sint: + return "rg16sint"; + case TexelFormat::kRg16Snorm: + return "rg16snorm"; + case TexelFormat::kRg16Uint: + return "rg16uint"; + case TexelFormat::kRg16Unorm: + return "rg16unorm"; + case TexelFormat::kRg32Float: + return "rg32float"; + case TexelFormat::kRg32Sint: + return "rg32sint"; + case TexelFormat::kRg32Uint: + return "rg32uint"; + case TexelFormat::kRg8Sint: + return "rg8sint"; + case TexelFormat::kRg8Snorm: + return "rg8snorm"; + case TexelFormat::kRg8Uint: + return "rg8uint"; + case TexelFormat::kRg8Unorm: + return "rg8unorm"; + case TexelFormat::kRgb10A2Uint: + return "rgb10a2uint"; + case TexelFormat::kRgb10A2Unorm: + return "rgb10a2unorm"; + case TexelFormat::kRgba16Float: + return "rgba16float"; + case TexelFormat::kRgba16Sint: + return "rgba16sint"; + case TexelFormat::kRgba16Snorm: + return "rgba16snorm"; + case TexelFormat::kRgba16Uint: + return "rgba16uint"; + case TexelFormat::kRgba16Unorm: + return "rgba16unorm"; + case TexelFormat::kRgba32Float: + return "rgba32float"; + case TexelFormat::kRgba32Sint: + return "rgba32sint"; + case TexelFormat::kRgba32Uint: + return "rgba32uint"; + case TexelFormat::kRgba8Sint: + return "rgba8sint"; + case TexelFormat::kRgba8Snorm: + return "rgba8snorm"; + case TexelFormat::kRgba8Uint: + return "rgba8uint"; + case TexelFormat::kRgba8Unorm: + return "rgba8unorm"; + } + return ""; +} + +/// ParseBuiltinType parses a BuiltinType from a string. +/// @param str the string to parse +/// @returns the parsed enum, or BuiltinType::kUndefined if the string could not be parsed. +BuiltinType ParseBuiltinType(std::string_view str) { + if (str == "__atomic_compare_exchange_result_i32") { + return BuiltinType::kAtomicCompareExchangeResultI32; + } + if (str == "__atomic_compare_exchange_result_u32") { + return BuiltinType::kAtomicCompareExchangeResultU32; + } + if (str == "__frexp_result_abstract") { + return BuiltinType::kFrexpResultAbstract; + } + if (str == "__frexp_result_f16") { + return BuiltinType::kFrexpResultF16; + } + if (str == "__frexp_result_f32") { + return BuiltinType::kFrexpResultF32; + } + if (str == "__frexp_result_vec2_abstract") { + return BuiltinType::kFrexpResultVec2Abstract; + } + if (str == "__frexp_result_vec2_f16") { + return BuiltinType::kFrexpResultVec2F16; + } + if (str == "__frexp_result_vec2_f32") { + return BuiltinType::kFrexpResultVec2F32; + } + if (str == "__frexp_result_vec3_abstract") { + return BuiltinType::kFrexpResultVec3Abstract; + } + if (str == "__frexp_result_vec3_f16") { + return BuiltinType::kFrexpResultVec3F16; + } + if (str == "__frexp_result_vec3_f32") { + return BuiltinType::kFrexpResultVec3F32; + } + if (str == "__frexp_result_vec4_abstract") { + return BuiltinType::kFrexpResultVec4Abstract; + } + if (str == "__frexp_result_vec4_f16") { + return BuiltinType::kFrexpResultVec4F16; + } + if (str == "__frexp_result_vec4_f32") { + return BuiltinType::kFrexpResultVec4F32; + } + if (str == "__modf_result_abstract") { + return BuiltinType::kModfResultAbstract; + } + if (str == "__modf_result_f16") { + return BuiltinType::kModfResultF16; + } + if (str == "__modf_result_f32") { + return BuiltinType::kModfResultF32; + } + if (str == "__modf_result_vec2_abstract") { + return BuiltinType::kModfResultVec2Abstract; + } + if (str == "__modf_result_vec2_f16") { + return BuiltinType::kModfResultVec2F16; + } + if (str == "__modf_result_vec2_f32") { + return BuiltinType::kModfResultVec2F32; + } + if (str == "__modf_result_vec3_abstract") { + return BuiltinType::kModfResultVec3Abstract; + } + if (str == "__modf_result_vec3_f16") { + return BuiltinType::kModfResultVec3F16; + } + if (str == "__modf_result_vec3_f32") { + return BuiltinType::kModfResultVec3F32; + } + if (str == "__modf_result_vec4_abstract") { + return BuiltinType::kModfResultVec4Abstract; + } + if (str == "__modf_result_vec4_f16") { + return BuiltinType::kModfResultVec4F16; + } + if (str == "__modf_result_vec4_f32") { + return BuiltinType::kModfResultVec4F32; + } + if (str == "array") { + return BuiltinType::kArray; + } + if (str == "atomic") { + return BuiltinType::kAtomic; + } + if (str == "binding_array") { + return BuiltinType::kBindingArray; + } + if (str == "bool") { + return BuiltinType::kBool; + } + if (str == "buffer") { + return BuiltinType::kBuffer; + } + if (str == "f16") { + return BuiltinType::kF16; + } + if (str == "f32") { + return BuiltinType::kF32; + } + if (str == "i32") { + return BuiltinType::kI32; + } + if (str == "i8") { + return BuiltinType::kI8; + } + if (str == "input_attachment") { + return BuiltinType::kInputAttachment; + } + if (str == "mat2x2") { + return BuiltinType::kMat2X2; + } + if (str == "mat2x2f") { + return BuiltinType::kMat2X2F; + } + if (str == "mat2x2h") { + return BuiltinType::kMat2X2H; + } + if (str == "mat2x3") { + return BuiltinType::kMat2X3; + } + if (str == "mat2x3f") { + return BuiltinType::kMat2X3F; + } + if (str == "mat2x3h") { + return BuiltinType::kMat2X3H; + } + if (str == "mat2x4") { + return BuiltinType::kMat2X4; + } + if (str == "mat2x4f") { + return BuiltinType::kMat2X4F; + } + if (str == "mat2x4h") { + return BuiltinType::kMat2X4H; + } + if (str == "mat3x2") { + return BuiltinType::kMat3X2; + } + if (str == "mat3x2f") { + return BuiltinType::kMat3X2F; + } + if (str == "mat3x2h") { + return BuiltinType::kMat3X2H; + } + if (str == "mat3x3") { + return BuiltinType::kMat3X3; + } + if (str == "mat3x3f") { + return BuiltinType::kMat3X3F; + } + if (str == "mat3x3h") { + return BuiltinType::kMat3X3H; + } + if (str == "mat3x4") { + return BuiltinType::kMat3X4; + } + if (str == "mat3x4f") { + return BuiltinType::kMat3X4F; + } + if (str == "mat3x4h") { + return BuiltinType::kMat3X4H; + } + if (str == "mat4x2") { + return BuiltinType::kMat4X2; + } + if (str == "mat4x2f") { + return BuiltinType::kMat4X2F; + } + if (str == "mat4x2h") { + return BuiltinType::kMat4X2H; + } + if (str == "mat4x3") { + return BuiltinType::kMat4X3; + } + if (str == "mat4x3f") { + return BuiltinType::kMat4X3F; + } + if (str == "mat4x3h") { + return BuiltinType::kMat4X3H; + } + if (str == "mat4x4") { + return BuiltinType::kMat4X4; + } + if (str == "mat4x4f") { + return BuiltinType::kMat4X4F; + } + if (str == "mat4x4h") { + return BuiltinType::kMat4X4H; + } + if (str == "ptr") { + return BuiltinType::kPtr; + } + if (str == "sampler") { + return BuiltinType::kSampler; + } + if (str == "sampler_comparison") { + return BuiltinType::kSamplerComparison; + } + if (str == "subgroup_matrix_left") { + return BuiltinType::kSubgroupMatrixLeft; + } + if (str == "subgroup_matrix_result") { + return BuiltinType::kSubgroupMatrixResult; + } + if (str == "subgroup_matrix_right") { + return BuiltinType::kSubgroupMatrixRight; + } + if (str == "texel_buffer") { + return BuiltinType::kTexelBuffer; + } + if (str == "texture_1d") { + return BuiltinType::kTexture1D; + } + if (str == "texture_2d") { + return BuiltinType::kTexture2D; + } + if (str == "texture_2d_array") { + return BuiltinType::kTexture2DArray; + } + if (str == "texture_3d") { + return BuiltinType::kTexture3D; + } + if (str == "texture_cube") { + return BuiltinType::kTextureCube; + } + if (str == "texture_cube_array") { + return BuiltinType::kTextureCubeArray; + } + if (str == "texture_depth_2d") { + return BuiltinType::kTextureDepth2D; + } + if (str == "texture_depth_2d_array") { + return BuiltinType::kTextureDepth2DArray; + } + if (str == "texture_depth_cube") { + return BuiltinType::kTextureDepthCube; + } + if (str == "texture_depth_cube_array") { + return BuiltinType::kTextureDepthCubeArray; + } + if (str == "texture_depth_multisampled_2d") { + return BuiltinType::kTextureDepthMultisampled2D; + } + if (str == "texture_external") { + return BuiltinType::kTextureExternal; + } + if (str == "texture_multisampled_2d") { + return BuiltinType::kTextureMultisampled2D; + } + if (str == "texture_storage_1d") { + return BuiltinType::kTextureStorage1D; + } + if (str == "texture_storage_2d") { + return BuiltinType::kTextureStorage2D; + } + if (str == "texture_storage_2d_array") { + return BuiltinType::kTextureStorage2DArray; + } + if (str == "texture_storage_3d") { + return BuiltinType::kTextureStorage3D; + } + if (str == "u32") { + return BuiltinType::kU32; + } + if (str == "u8") { + return BuiltinType::kU8; + } + if (str == "vec2") { + return BuiltinType::kVec2; + } + if (str == "vec2f") { + return BuiltinType::kVec2F; + } + if (str == "vec2h") { + return BuiltinType::kVec2H; + } + if (str == "vec2i") { + return BuiltinType::kVec2I; + } + if (str == "vec2u") { + return BuiltinType::kVec2U; + } + if (str == "vec3") { + return BuiltinType::kVec3; + } + if (str == "vec3f") { + return BuiltinType::kVec3F; + } + if (str == "vec3h") { + return BuiltinType::kVec3H; + } + if (str == "vec3i") { + return BuiltinType::kVec3I; + } + if (str == "vec3u") { + return BuiltinType::kVec3U; + } + if (str == "vec4") { + return BuiltinType::kVec4; + } + if (str == "vec4f") { + return BuiltinType::kVec4F; + } + if (str == "vec4h") { + return BuiltinType::kVec4H; + } + if (str == "vec4i") { + return BuiltinType::kVec4I; + } + if (str == "vec4u") { + return BuiltinType::kVec4U; + } + return BuiltinType::kUndefined; +} +std::string_view ToString(BuiltinType value) { + switch (value) { + case BuiltinType::kUndefined: + return "undefined"; + case BuiltinType::kAtomicCompareExchangeResultI32: + return "__atomic_compare_exchange_result_i32"; + case BuiltinType::kAtomicCompareExchangeResultU32: + return "__atomic_compare_exchange_result_u32"; + case BuiltinType::kFrexpResultAbstract: + return "__frexp_result_abstract"; + case BuiltinType::kFrexpResultF16: + return "__frexp_result_f16"; + case BuiltinType::kFrexpResultF32: + return "__frexp_result_f32"; + case BuiltinType::kFrexpResultVec2Abstract: + return "__frexp_result_vec2_abstract"; + case BuiltinType::kFrexpResultVec2F16: + return "__frexp_result_vec2_f16"; + case BuiltinType::kFrexpResultVec2F32: + return "__frexp_result_vec2_f32"; + case BuiltinType::kFrexpResultVec3Abstract: + return "__frexp_result_vec3_abstract"; + case BuiltinType::kFrexpResultVec3F16: + return "__frexp_result_vec3_f16"; + case BuiltinType::kFrexpResultVec3F32: + return "__frexp_result_vec3_f32"; + case BuiltinType::kFrexpResultVec4Abstract: + return "__frexp_result_vec4_abstract"; + case BuiltinType::kFrexpResultVec4F16: + return "__frexp_result_vec4_f16"; + case BuiltinType::kFrexpResultVec4F32: + return "__frexp_result_vec4_f32"; + case BuiltinType::kModfResultAbstract: + return "__modf_result_abstract"; + case BuiltinType::kModfResultF16: + return "__modf_result_f16"; + case BuiltinType::kModfResultF32: + return "__modf_result_f32"; + case BuiltinType::kModfResultVec2Abstract: + return "__modf_result_vec2_abstract"; + case BuiltinType::kModfResultVec2F16: + return "__modf_result_vec2_f16"; + case BuiltinType::kModfResultVec2F32: + return "__modf_result_vec2_f32"; + case BuiltinType::kModfResultVec3Abstract: + return "__modf_result_vec3_abstract"; + case BuiltinType::kModfResultVec3F16: + return "__modf_result_vec3_f16"; + case BuiltinType::kModfResultVec3F32: + return "__modf_result_vec3_f32"; + case BuiltinType::kModfResultVec4Abstract: + return "__modf_result_vec4_abstract"; + case BuiltinType::kModfResultVec4F16: + return "__modf_result_vec4_f16"; + case BuiltinType::kModfResultVec4F32: + return "__modf_result_vec4_f32"; + case BuiltinType::kArray: + return "array"; + case BuiltinType::kAtomic: + return "atomic"; + case BuiltinType::kBindingArray: + return "binding_array"; + case BuiltinType::kBool: + return "bool"; + case BuiltinType::kBuffer: + return "buffer"; + case BuiltinType::kF16: + return "f16"; + case BuiltinType::kF32: + return "f32"; + case BuiltinType::kI32: + return "i32"; + case BuiltinType::kI8: + return "i8"; + case BuiltinType::kInputAttachment: + return "input_attachment"; + case BuiltinType::kMat2X2: + return "mat2x2"; + case BuiltinType::kMat2X2F: + return "mat2x2f"; + case BuiltinType::kMat2X2H: + return "mat2x2h"; + case BuiltinType::kMat2X3: + return "mat2x3"; + case BuiltinType::kMat2X3F: + return "mat2x3f"; + case BuiltinType::kMat2X3H: + return "mat2x3h"; + case BuiltinType::kMat2X4: + return "mat2x4"; + case BuiltinType::kMat2X4F: + return "mat2x4f"; + case BuiltinType::kMat2X4H: + return "mat2x4h"; + case BuiltinType::kMat3X2: + return "mat3x2"; + case BuiltinType::kMat3X2F: + return "mat3x2f"; + case BuiltinType::kMat3X2H: + return "mat3x2h"; + case BuiltinType::kMat3X3: + return "mat3x3"; + case BuiltinType::kMat3X3F: + return "mat3x3f"; + case BuiltinType::kMat3X3H: + return "mat3x3h"; + case BuiltinType::kMat3X4: + return "mat3x4"; + case BuiltinType::kMat3X4F: + return "mat3x4f"; + case BuiltinType::kMat3X4H: + return "mat3x4h"; + case BuiltinType::kMat4X2: + return "mat4x2"; + case BuiltinType::kMat4X2F: + return "mat4x2f"; + case BuiltinType::kMat4X2H: + return "mat4x2h"; + case BuiltinType::kMat4X3: + return "mat4x3"; + case BuiltinType::kMat4X3F: + return "mat4x3f"; + case BuiltinType::kMat4X3H: + return "mat4x3h"; + case BuiltinType::kMat4X4: + return "mat4x4"; + case BuiltinType::kMat4X4F: + return "mat4x4f"; + case BuiltinType::kMat4X4H: + return "mat4x4h"; + case BuiltinType::kPtr: + return "ptr"; + case BuiltinType::kSampler: + return "sampler"; + case BuiltinType::kSamplerComparison: + return "sampler_comparison"; + case BuiltinType::kSubgroupMatrixLeft: + return "subgroup_matrix_left"; + case BuiltinType::kSubgroupMatrixResult: + return "subgroup_matrix_result"; + case BuiltinType::kSubgroupMatrixRight: + return "subgroup_matrix_right"; + case BuiltinType::kTexelBuffer: + return "texel_buffer"; + case BuiltinType::kTexture1D: + return "texture_1d"; + case BuiltinType::kTexture2D: + return "texture_2d"; + case BuiltinType::kTexture2DArray: + return "texture_2d_array"; + case BuiltinType::kTexture3D: + return "texture_3d"; + case BuiltinType::kTextureCube: + return "texture_cube"; + case BuiltinType::kTextureCubeArray: + return "texture_cube_array"; + case BuiltinType::kTextureDepth2D: + return "texture_depth_2d"; + case BuiltinType::kTextureDepth2DArray: + return "texture_depth_2d_array"; + case BuiltinType::kTextureDepthCube: + return "texture_depth_cube"; + case BuiltinType::kTextureDepthCubeArray: + return "texture_depth_cube_array"; + case BuiltinType::kTextureDepthMultisampled2D: + return "texture_depth_multisampled_2d"; + case BuiltinType::kTextureExternal: + return "texture_external"; + case BuiltinType::kTextureMultisampled2D: + return "texture_multisampled_2d"; + case BuiltinType::kTextureStorage1D: + return "texture_storage_1d"; + case BuiltinType::kTextureStorage2D: + return "texture_storage_2d"; + case BuiltinType::kTextureStorage2DArray: + return "texture_storage_2d_array"; + case BuiltinType::kTextureStorage3D: + return "texture_storage_3d"; + case BuiltinType::kU32: + return "u32"; + case BuiltinType::kU8: + return "u8"; + case BuiltinType::kVec2: + return "vec2"; + case BuiltinType::kVec2F: + return "vec2f"; + case BuiltinType::kVec2H: + return "vec2h"; + case BuiltinType::kVec2I: + return "vec2i"; + case BuiltinType::kVec2U: + return "vec2u"; + case BuiltinType::kVec3: + return "vec3"; + case BuiltinType::kVec3F: + return "vec3f"; + case BuiltinType::kVec3H: + return "vec3h"; + case BuiltinType::kVec3I: + return "vec3i"; + case BuiltinType::kVec3U: + return "vec3u"; + case BuiltinType::kVec4: + return "vec4"; + case BuiltinType::kVec4F: + return "vec4f"; + case BuiltinType::kVec4H: + return "vec4h"; + case BuiltinType::kVec4I: + return "vec4i"; + case BuiltinType::kVec4U: + return "vec4u"; + } + return ""; +} + +/// ParseBuiltinValue parses a BuiltinValue from a string. +/// @param str the string to parse +/// @returns the parsed enum, or BuiltinValue::kUndefined if the string could not be parsed. +BuiltinValue ParseBuiltinValue(std::string_view str) { + if (str == "barycentric_coord") { + return BuiltinValue::kBarycentricCoord; + } + if (str == "clip_distances") { + return BuiltinValue::kClipDistances; + } + if (str == "frag_depth") { + return BuiltinValue::kFragDepth; + } + if (str == "front_facing") { + return BuiltinValue::kFrontFacing; + } + if (str == "global_invocation_id") { + return BuiltinValue::kGlobalInvocationId; + } + if (str == "instance_index") { + return BuiltinValue::kInstanceIndex; + } + if (str == "local_invocation_id") { + return BuiltinValue::kLocalInvocationId; + } + if (str == "local_invocation_index") { + return BuiltinValue::kLocalInvocationIndex; + } + if (str == "num_subgroups") { + return BuiltinValue::kNumSubgroups; + } + if (str == "num_workgroups") { + return BuiltinValue::kNumWorkgroups; + } + if (str == "position") { + return BuiltinValue::kPosition; + } + if (str == "primitive_index") { + return BuiltinValue::kPrimitiveIndex; + } + if (str == "sample_index") { + return BuiltinValue::kSampleIndex; + } + if (str == "sample_mask") { + return BuiltinValue::kSampleMask; + } + if (str == "subgroup_id") { + return BuiltinValue::kSubgroupId; + } + if (str == "subgroup_invocation_id") { + return BuiltinValue::kSubgroupInvocationId; + } + if (str == "subgroup_size") { + return BuiltinValue::kSubgroupSize; + } + if (str == "vertex_index") { + return BuiltinValue::kVertexIndex; + } + if (str == "workgroup_id") { + return BuiltinValue::kWorkgroupId; + } + return BuiltinValue::kUndefined; +} +std::string_view ToString(BuiltinValue value) { + switch (value) { + case BuiltinValue::kUndefined: + return "undefined"; + case BuiltinValue::kCullDistance: + return "__cull_distance"; + case BuiltinValue::kPointSize: + return "__point_size"; + case BuiltinValue::kBarycentricCoord: + return "barycentric_coord"; + case BuiltinValue::kClipDistances: + return "clip_distances"; + case BuiltinValue::kFragDepth: + return "frag_depth"; + case BuiltinValue::kFrontFacing: + return "front_facing"; + case BuiltinValue::kGlobalInvocationId: + return "global_invocation_id"; + case BuiltinValue::kInstanceIndex: + return "instance_index"; + case BuiltinValue::kLocalInvocationId: + return "local_invocation_id"; + case BuiltinValue::kLocalInvocationIndex: + return "local_invocation_index"; + case BuiltinValue::kNumSubgroups: + return "num_subgroups"; + case BuiltinValue::kNumWorkgroups: + return "num_workgroups"; + case BuiltinValue::kPosition: + return "position"; + case BuiltinValue::kPrimitiveIndex: + return "primitive_index"; + case BuiltinValue::kSampleIndex: + return "sample_index"; + case BuiltinValue::kSampleMask: + return "sample_mask"; + case BuiltinValue::kSubgroupId: + return "subgroup_id"; + case BuiltinValue::kSubgroupInvocationId: + return "subgroup_invocation_id"; + case BuiltinValue::kSubgroupSize: + return "subgroup_size"; + case BuiltinValue::kVertexIndex: + return "vertex_index"; + case BuiltinValue::kWorkgroupId: + return "workgroup_id"; + } + return ""; +} + +/// ParseBuiltinDepthMode parses a BuiltinDepthMode from a string. +/// @param str the string to parse +/// @returns the parsed enum, or BuiltinDepthMode::kUndefined if the string could not be parsed. +BuiltinDepthMode ParseBuiltinDepthMode(std::string_view str) { + if (str == "any") { + return BuiltinDepthMode::kAny; + } + if (str == "greater") { + return BuiltinDepthMode::kGreater; + } + if (str == "less") { + return BuiltinDepthMode::kLess; + } + return BuiltinDepthMode::kUndefined; +} +std::string_view ToString(BuiltinDepthMode value) { + switch (value) { + case BuiltinDepthMode::kUndefined: + return "undefined"; + case BuiltinDepthMode::kAny: + return "any"; + case BuiltinDepthMode::kGreater: + return "greater"; + case BuiltinDepthMode::kLess: + return "less"; + } + return ""; +} + +/// ParseAttribute parses a Attribute from a string. +/// @param str the string to parse +/// @returns the parsed enum, or Attribute::kUndefined if the string could not be parsed. +Attribute ParseAttribute(std::string_view str) { + if (str == "align") { + return Attribute::kAlign; + } + if (str == "binding") { + return Attribute::kBinding; + } + if (str == "blend_src") { + return Attribute::kBlendSrc; + } + if (str == "builtin") { + return Attribute::kBuiltin; + } + if (str == "color") { + return Attribute::kColor; + } + if (str == "compute") { + return Attribute::kCompute; + } + if (str == "diagnostic") { + return Attribute::kDiagnostic; + } + if (str == "fragment") { + return Attribute::kFragment; + } + if (str == "group") { + return Attribute::kGroup; + } + if (str == "id") { + return Attribute::kId; + } + if (str == "input_attachment_index") { + return Attribute::kInputAttachmentIndex; + } + if (str == "interpolate") { + return Attribute::kInterpolate; + } + if (str == "invariant") { + return Attribute::kInvariant; + } + if (str == "location") { + return Attribute::kLocation; + } + if (str == "must_use") { + return Attribute::kMustUse; + } + if (str == "size") { + return Attribute::kSize; + } + if (str == "subgroup_size") { + return Attribute::kSubgroupSize; + } + if (str == "vertex") { + return Attribute::kVertex; + } + if (str == "workgroup_size") { + return Attribute::kWorkgroupSize; + } + return Attribute::kUndefined; +} +std::string_view ToString(Attribute value) { + switch (value) { + case Attribute::kUndefined: + return "undefined"; + case Attribute::kAlign: + return "align"; + case Attribute::kBinding: + return "binding"; + case Attribute::kBlendSrc: + return "blend_src"; + case Attribute::kBuiltin: + return "builtin"; + case Attribute::kColor: + return "color"; + case Attribute::kCompute: + return "compute"; + case Attribute::kDiagnostic: + return "diagnostic"; + case Attribute::kFragment: + return "fragment"; + case Attribute::kGroup: + return "group"; + case Attribute::kId: + return "id"; + case Attribute::kInputAttachmentIndex: + return "input_attachment_index"; + case Attribute::kInterpolate: + return "interpolate"; + case Attribute::kInvariant: + return "invariant"; + case Attribute::kLocation: + return "location"; + case Attribute::kMustUse: + return "must_use"; + case Attribute::kSize: + return "size"; + case Attribute::kSubgroupSize: + return "subgroup_size"; + case Attribute::kVertex: + return "vertex"; + case Attribute::kWorkgroupSize: + return "workgroup_size"; + } + return ""; +} + +std::string_view ToString(ParameterUsage usage) { + switch (usage) { + case ParameterUsage::kNone: + return "none"; + case ParameterUsage::kArrayIndex: + return "array_index"; + case ParameterUsage::kBase: + return "base"; + case ParameterUsage::kBias: + return "bias"; + case ParameterUsage::kBits: + return "bits"; + case ParameterUsage::kCompareValue: + return "compare_value"; + case ParameterUsage::kComponent: + return "component"; + case ParameterUsage::kConstOffset: + return "const_offset"; + case ParameterUsage::kCoords: + return "coords"; + case ParameterUsage::kCount: + return "count"; + case ParameterUsage::kDdx: + return "ddx"; + case ParameterUsage::kDdy: + return "ddy"; + case ParameterUsage::kDelta: + return "delta"; + case ParameterUsage::kDepth: + return "depth"; + case ParameterUsage::kDepthRef: + return "depth_ref"; + case ParameterUsage::kDir: + return "dir"; + case ParameterUsage::kDref: + return "dref"; + case ParameterUsage::kE: + return "e"; + case ParameterUsage::kElements: + return "elements"; + case ParameterUsage::kExp: + return "exp"; + case ParameterUsage::kGroupOperation: + return "group_operation"; + case ParameterUsage::kHeight: + return "height"; + case ParameterUsage::kI: + return "i"; + case ParameterUsage::kId: + return "id"; + case ParameterUsage::kImage: + return "image"; + case ParameterUsage::kImageOperands: + return "image_operands"; + case ParameterUsage::kIndex: + return "index"; + case ParameterUsage::kInputAttachment: + return "input_attachment"; + case ParameterUsage::kInsert: + return "insert"; + case ParameterUsage::kLevel: + return "level"; + case ParameterUsage::kLocation: + return "location"; + case ParameterUsage::kLod: + return "lod"; + case ParameterUsage::kM: + return "m"; + case ParameterUsage::kMask: + return "mask"; + case ParameterUsage::kNumLevels: + return "num_levels"; + case ParameterUsage::kOffset: + return "offset"; + case ParameterUsage::kOriginalValue: + return "original_value"; + case ParameterUsage::kRefz: + return "refz"; + case ParameterUsage::kResult: + return "result"; + case ParameterUsage::kS: + return "s"; + case ParameterUsage::kSample: + return "sample"; + case ParameterUsage::kSampleIndex: + return "sample_index"; + case ParameterUsage::kSampler: + return "sampler"; + case ParameterUsage::kSamples: + return "samples"; + case ParameterUsage::kScope: + return "scope"; + case ParameterUsage::kSourceLaneIndex: + return "sourceLaneIndex"; + case ParameterUsage::kTexel: + return "texel"; + case ParameterUsage::kTexture: + return "texture"; + case ParameterUsage::kValue: + return "value"; + case ParameterUsage::kW: + return "w"; + case ParameterUsage::kWidth: + return "width"; + case ParameterUsage::kX: + return "x"; + case ParameterUsage::kXy: + return "xy"; + case ParameterUsage::kXyz: + return "xyz"; + case ParameterUsage::kY: + return "y"; + case ParameterUsage::kYz: + return "yz"; + case ParameterUsage::kZ: + return "z"; + case ParameterUsage::kZw: + return "zw"; + case ParameterUsage::kZyw: + return "zyw"; + } + return ""; +} + +BuiltinFn ParseBuiltinFn(std::string_view name) { + if (name == "abs") { + return BuiltinFn::kAbs; + } + if (name == "acos") { + return BuiltinFn::kAcos; + } + if (name == "acosh") { + return BuiltinFn::kAcosh; + } + if (name == "all") { + return BuiltinFn::kAll; + } + if (name == "any") { + return BuiltinFn::kAny; + } + if (name == "arrayLength") { + return BuiltinFn::kArrayLength; + } + if (name == "asin") { + return BuiltinFn::kAsin; + } + if (name == "asinh") { + return BuiltinFn::kAsinh; + } + if (name == "atan") { + return BuiltinFn::kAtan; + } + if (name == "atan2") { + return BuiltinFn::kAtan2; + } + if (name == "atanh") { + return BuiltinFn::kAtanh; + } + if (name == "ceil") { + return BuiltinFn::kCeil; + } + if (name == "clamp") { + return BuiltinFn::kClamp; + } + if (name == "cos") { + return BuiltinFn::kCos; + } + if (name == "cosh") { + return BuiltinFn::kCosh; + } + if (name == "countLeadingZeros") { + return BuiltinFn::kCountLeadingZeros; + } + if (name == "countOneBits") { + return BuiltinFn::kCountOneBits; + } + if (name == "countTrailingZeros") { + return BuiltinFn::kCountTrailingZeros; + } + if (name == "cross") { + return BuiltinFn::kCross; + } + if (name == "degrees") { + return BuiltinFn::kDegrees; + } + if (name == "determinant") { + return BuiltinFn::kDeterminant; + } + if (name == "distance") { + return BuiltinFn::kDistance; + } + if (name == "dot") { + return BuiltinFn::kDot; + } + if (name == "dot4I8Packed") { + return BuiltinFn::kDot4I8Packed; + } + if (name == "dot4U8Packed") { + return BuiltinFn::kDot4U8Packed; + } + if (name == "dpdx") { + return BuiltinFn::kDpdx; + } + if (name == "dpdxCoarse") { + return BuiltinFn::kDpdxCoarse; + } + if (name == "dpdxFine") { + return BuiltinFn::kDpdxFine; + } + if (name == "dpdy") { + return BuiltinFn::kDpdy; + } + if (name == "dpdyCoarse") { + return BuiltinFn::kDpdyCoarse; + } + if (name == "dpdyFine") { + return BuiltinFn::kDpdyFine; + } + if (name == "exp") { + return BuiltinFn::kExp; + } + if (name == "exp2") { + return BuiltinFn::kExp2; + } + if (name == "extractBits") { + return BuiltinFn::kExtractBits; + } + if (name == "faceForward") { + return BuiltinFn::kFaceForward; + } + if (name == "firstLeadingBit") { + return BuiltinFn::kFirstLeadingBit; + } + if (name == "firstTrailingBit") { + return BuiltinFn::kFirstTrailingBit; + } + if (name == "floor") { + return BuiltinFn::kFloor; + } + if (name == "fma") { + return BuiltinFn::kFma; + } + if (name == "fract") { + return BuiltinFn::kFract; + } + if (name == "frexp") { + return BuiltinFn::kFrexp; + } + if (name == "fwidth") { + return BuiltinFn::kFwidth; + } + if (name == "fwidthCoarse") { + return BuiltinFn::kFwidthCoarse; + } + if (name == "fwidthFine") { + return BuiltinFn::kFwidthFine; + } + if (name == "insertBits") { + return BuiltinFn::kInsertBits; + } + if (name == "inverseSqrt") { + return BuiltinFn::kInverseSqrt; + } + if (name == "ldexp") { + return BuiltinFn::kLdexp; + } + if (name == "length") { + return BuiltinFn::kLength; + } + if (name == "log") { + return BuiltinFn::kLog; + } + if (name == "log2") { + return BuiltinFn::kLog2; + } + if (name == "max") { + return BuiltinFn::kMax; + } + if (name == "min") { + return BuiltinFn::kMin; + } + if (name == "mix") { + return BuiltinFn::kMix; + } + if (name == "modf") { + return BuiltinFn::kModf; + } + if (name == "normalize") { + return BuiltinFn::kNormalize; + } + if (name == "pack2x16float") { + return BuiltinFn::kPack2X16Float; + } + if (name == "pack2x16snorm") { + return BuiltinFn::kPack2X16Snorm; + } + if (name == "pack2x16unorm") { + return BuiltinFn::kPack2X16Unorm; + } + if (name == "pack4x8snorm") { + return BuiltinFn::kPack4X8Snorm; + } + if (name == "pack4x8unorm") { + return BuiltinFn::kPack4X8Unorm; + } + if (name == "pack4xI8") { + return BuiltinFn::kPack4XI8; + } + if (name == "pack4xU8") { + return BuiltinFn::kPack4XU8; + } + if (name == "pack4xI8Clamp") { + return BuiltinFn::kPack4XI8Clamp; + } + if (name == "pack4xU8Clamp") { + return BuiltinFn::kPack4XU8Clamp; + } + if (name == "pow") { + return BuiltinFn::kPow; + } + if (name == "quantizeToF16") { + return BuiltinFn::kQuantizeToF16; + } + if (name == "radians") { + return BuiltinFn::kRadians; + } + if (name == "reflect") { + return BuiltinFn::kReflect; + } + if (name == "refract") { + return BuiltinFn::kRefract; + } + if (name == "reverseBits") { + return BuiltinFn::kReverseBits; + } + if (name == "round") { + return BuiltinFn::kRound; + } + if (name == "saturate") { + return BuiltinFn::kSaturate; + } + if (name == "select") { + return BuiltinFn::kSelect; + } + if (name == "sign") { + return BuiltinFn::kSign; + } + if (name == "sin") { + return BuiltinFn::kSin; + } + if (name == "sinh") { + return BuiltinFn::kSinh; + } + if (name == "smoothstep") { + return BuiltinFn::kSmoothstep; + } + if (name == "sqrt") { + return BuiltinFn::kSqrt; + } + if (name == "step") { + return BuiltinFn::kStep; + } + if (name == "storageBarrier") { + return BuiltinFn::kStorageBarrier; + } + if (name == "tan") { + return BuiltinFn::kTan; + } + if (name == "tanh") { + return BuiltinFn::kTanh; + } + if (name == "transpose") { + return BuiltinFn::kTranspose; + } + if (name == "trunc") { + return BuiltinFn::kTrunc; + } + if (name == "unpack2x16float") { + return BuiltinFn::kUnpack2X16Float; + } + if (name == "unpack2x16snorm") { + return BuiltinFn::kUnpack2X16Snorm; + } + if (name == "unpack2x16unorm") { + return BuiltinFn::kUnpack2X16Unorm; + } + if (name == "unpack4x8snorm") { + return BuiltinFn::kUnpack4X8Snorm; + } + if (name == "unpack4x8unorm") { + return BuiltinFn::kUnpack4X8Unorm; + } + if (name == "unpack4xI8") { + return BuiltinFn::kUnpack4XI8; + } + if (name == "unpack4xU8") { + return BuiltinFn::kUnpack4XU8; + } + if (name == "workgroupBarrier") { + return BuiltinFn::kWorkgroupBarrier; + } + if (name == "textureBarrier") { + return BuiltinFn::kTextureBarrier; + } + if (name == "textureDimensions") { + return BuiltinFn::kTextureDimensions; + } + if (name == "textureGather") { + return BuiltinFn::kTextureGather; + } + if (name == "textureGatherCompare") { + return BuiltinFn::kTextureGatherCompare; + } + if (name == "textureNumLayers") { + return BuiltinFn::kTextureNumLayers; + } + if (name == "textureNumLevels") { + return BuiltinFn::kTextureNumLevels; + } + if (name == "textureNumSamples") { + return BuiltinFn::kTextureNumSamples; + } + if (name == "textureSample") { + return BuiltinFn::kTextureSample; + } + if (name == "textureSampleBias") { + return BuiltinFn::kTextureSampleBias; + } + if (name == "textureSampleCompare") { + return BuiltinFn::kTextureSampleCompare; + } + if (name == "textureSampleCompareLevel") { + return BuiltinFn::kTextureSampleCompareLevel; + } + if (name == "textureSampleGrad") { + return BuiltinFn::kTextureSampleGrad; + } + if (name == "textureSampleLevel") { + return BuiltinFn::kTextureSampleLevel; + } + if (name == "textureSampleBaseClampToEdge") { + return BuiltinFn::kTextureSampleBaseClampToEdge; + } + if (name == "textureStore") { + return BuiltinFn::kTextureStore; + } + if (name == "textureLoad") { + return BuiltinFn::kTextureLoad; + } + if (name == "inputAttachmentLoad") { + return BuiltinFn::kInputAttachmentLoad; + } + if (name == "atomicLoad") { + return BuiltinFn::kAtomicLoad; + } + if (name == "atomicStore") { + return BuiltinFn::kAtomicStore; + } + if (name == "atomicAdd") { + return BuiltinFn::kAtomicAdd; + } + if (name == "atomicSub") { + return BuiltinFn::kAtomicSub; + } + if (name == "atomicMax") { + return BuiltinFn::kAtomicMax; + } + if (name == "atomicMin") { + return BuiltinFn::kAtomicMin; + } + if (name == "atomicAnd") { + return BuiltinFn::kAtomicAnd; + } + if (name == "atomicOr") { + return BuiltinFn::kAtomicOr; + } + if (name == "atomicXor") { + return BuiltinFn::kAtomicXor; + } + if (name == "atomicExchange") { + return BuiltinFn::kAtomicExchange; + } + if (name == "atomicCompareExchangeWeak") { + return BuiltinFn::kAtomicCompareExchangeWeak; + } + if (name == "subgroupBallot") { + return BuiltinFn::kSubgroupBallot; + } + if (name == "subgroupElect") { + return BuiltinFn::kSubgroupElect; + } + if (name == "subgroupBroadcast") { + return BuiltinFn::kSubgroupBroadcast; + } + if (name == "subgroupBroadcastFirst") { + return BuiltinFn::kSubgroupBroadcastFirst; + } + if (name == "subgroupShuffle") { + return BuiltinFn::kSubgroupShuffle; + } + if (name == "subgroupShuffleXor") { + return BuiltinFn::kSubgroupShuffleXor; + } + if (name == "subgroupShuffleUp") { + return BuiltinFn::kSubgroupShuffleUp; + } + if (name == "subgroupShuffleDown") { + return BuiltinFn::kSubgroupShuffleDown; + } + if (name == "subgroupAdd") { + return BuiltinFn::kSubgroupAdd; + } + if (name == "subgroupInclusiveAdd") { + return BuiltinFn::kSubgroupInclusiveAdd; + } + if (name == "subgroupExclusiveAdd") { + return BuiltinFn::kSubgroupExclusiveAdd; + } + if (name == "subgroupMul") { + return BuiltinFn::kSubgroupMul; + } + if (name == "subgroupInclusiveMul") { + return BuiltinFn::kSubgroupInclusiveMul; + } + if (name == "subgroupExclusiveMul") { + return BuiltinFn::kSubgroupExclusiveMul; + } + if (name == "subgroupAnd") { + return BuiltinFn::kSubgroupAnd; + } + if (name == "subgroupOr") { + return BuiltinFn::kSubgroupOr; + } + if (name == "subgroupXor") { + return BuiltinFn::kSubgroupXor; + } + if (name == "subgroupMin") { + return BuiltinFn::kSubgroupMin; + } + if (name == "subgroupMax") { + return BuiltinFn::kSubgroupMax; + } + if (name == "subgroupAll") { + return BuiltinFn::kSubgroupAll; + } + if (name == "subgroupAny") { + return BuiltinFn::kSubgroupAny; + } + if (name == "quadBroadcast") { + return BuiltinFn::kQuadBroadcast; + } + if (name == "quadSwapX") { + return BuiltinFn::kQuadSwapX; + } + if (name == "quadSwapY") { + return BuiltinFn::kQuadSwapY; + } + if (name == "quadSwapDiagonal") { + return BuiltinFn::kQuadSwapDiagonal; + } + if (name == "subgroupMatrixLoad") { + return BuiltinFn::kSubgroupMatrixLoad; + } + if (name == "subgroupMatrixStore") { + return BuiltinFn::kSubgroupMatrixStore; + } + if (name == "subgroupMatrixMultiply") { + return BuiltinFn::kSubgroupMatrixMultiply; + } + if (name == "subgroupMatrixMultiplyAccumulate") { + return BuiltinFn::kSubgroupMatrixMultiplyAccumulate; + } + if (name == "subgroupMatrixScalarAdd") { + return BuiltinFn::kSubgroupMatrixScalarAdd; + } + if (name == "subgroupMatrixScalarSubtract") { + return BuiltinFn::kSubgroupMatrixScalarSubtract; + } + if (name == "subgroupMatrixScalarMultiply") { + return BuiltinFn::kSubgroupMatrixScalarMultiply; + } + if (name == "bufferView") { + return BuiltinFn::kBufferView; + } + if (name == "bufferLength") { + return BuiltinFn::kBufferLength; + } + if (name == "print") { + return BuiltinFn::kPrint; + } + if (name == "hasResource") { + return BuiltinFn::kHasResource; + } + if (name == "getResource") { + return BuiltinFn::kGetResource; + } + return BuiltinFn::kNone; +} + +const char* str(BuiltinFn i) { + switch (i) { + case BuiltinFn::kNone: + return ""; + case BuiltinFn::kAbs: + return "abs"; + case BuiltinFn::kAcos: + return "acos"; + case BuiltinFn::kAcosh: + return "acosh"; + case BuiltinFn::kAll: + return "all"; + case BuiltinFn::kAny: + return "any"; + case BuiltinFn::kArrayLength: + return "arrayLength"; + case BuiltinFn::kAsin: + return "asin"; + case BuiltinFn::kAsinh: + return "asinh"; + case BuiltinFn::kAtan: + return "atan"; + case BuiltinFn::kAtan2: + return "atan2"; + case BuiltinFn::kAtanh: + return "atanh"; + case BuiltinFn::kCeil: + return "ceil"; + case BuiltinFn::kClamp: + return "clamp"; + case BuiltinFn::kCos: + return "cos"; + case BuiltinFn::kCosh: + return "cosh"; + case BuiltinFn::kCountLeadingZeros: + return "countLeadingZeros"; + case BuiltinFn::kCountOneBits: + return "countOneBits"; + case BuiltinFn::kCountTrailingZeros: + return "countTrailingZeros"; + case BuiltinFn::kCross: + return "cross"; + case BuiltinFn::kDegrees: + return "degrees"; + case BuiltinFn::kDeterminant: + return "determinant"; + case BuiltinFn::kDistance: + return "distance"; + case BuiltinFn::kDot: + return "dot"; + case BuiltinFn::kDot4I8Packed: + return "dot4I8Packed"; + case BuiltinFn::kDot4U8Packed: + return "dot4U8Packed"; + case BuiltinFn::kDpdx: + return "dpdx"; + case BuiltinFn::kDpdxCoarse: + return "dpdxCoarse"; + case BuiltinFn::kDpdxFine: + return "dpdxFine"; + case BuiltinFn::kDpdy: + return "dpdy"; + case BuiltinFn::kDpdyCoarse: + return "dpdyCoarse"; + case BuiltinFn::kDpdyFine: + return "dpdyFine"; + case BuiltinFn::kExp: + return "exp"; + case BuiltinFn::kExp2: + return "exp2"; + case BuiltinFn::kExtractBits: + return "extractBits"; + case BuiltinFn::kFaceForward: + return "faceForward"; + case BuiltinFn::kFirstLeadingBit: + return "firstLeadingBit"; + case BuiltinFn::kFirstTrailingBit: + return "firstTrailingBit"; + case BuiltinFn::kFloor: + return "floor"; + case BuiltinFn::kFma: + return "fma"; + case BuiltinFn::kFract: + return "fract"; + case BuiltinFn::kFrexp: + return "frexp"; + case BuiltinFn::kFwidth: + return "fwidth"; + case BuiltinFn::kFwidthCoarse: + return "fwidthCoarse"; + case BuiltinFn::kFwidthFine: + return "fwidthFine"; + case BuiltinFn::kInsertBits: + return "insertBits"; + case BuiltinFn::kInverseSqrt: + return "inverseSqrt"; + case BuiltinFn::kLdexp: + return "ldexp"; + case BuiltinFn::kLength: + return "length"; + case BuiltinFn::kLog: + return "log"; + case BuiltinFn::kLog2: + return "log2"; + case BuiltinFn::kMax: + return "max"; + case BuiltinFn::kMin: + return "min"; + case BuiltinFn::kMix: + return "mix"; + case BuiltinFn::kModf: + return "modf"; + case BuiltinFn::kNormalize: + return "normalize"; + case BuiltinFn::kPack2X16Float: + return "pack2x16float"; + case BuiltinFn::kPack2X16Snorm: + return "pack2x16snorm"; + case BuiltinFn::kPack2X16Unorm: + return "pack2x16unorm"; + case BuiltinFn::kPack4X8Snorm: + return "pack4x8snorm"; + case BuiltinFn::kPack4X8Unorm: + return "pack4x8unorm"; + case BuiltinFn::kPack4XI8: + return "pack4xI8"; + case BuiltinFn::kPack4XU8: + return "pack4xU8"; + case BuiltinFn::kPack4XI8Clamp: + return "pack4xI8Clamp"; + case BuiltinFn::kPack4XU8Clamp: + return "pack4xU8Clamp"; + case BuiltinFn::kPow: + return "pow"; + case BuiltinFn::kQuantizeToF16: + return "quantizeToF16"; + case BuiltinFn::kRadians: + return "radians"; + case BuiltinFn::kReflect: + return "reflect"; + case BuiltinFn::kRefract: + return "refract"; + case BuiltinFn::kReverseBits: + return "reverseBits"; + case BuiltinFn::kRound: + return "round"; + case BuiltinFn::kSaturate: + return "saturate"; + case BuiltinFn::kSelect: + return "select"; + case BuiltinFn::kSign: + return "sign"; + case BuiltinFn::kSin: + return "sin"; + case BuiltinFn::kSinh: + return "sinh"; + case BuiltinFn::kSmoothstep: + return "smoothstep"; + case BuiltinFn::kSqrt: + return "sqrt"; + case BuiltinFn::kStep: + return "step"; + case BuiltinFn::kStorageBarrier: + return "storageBarrier"; + case BuiltinFn::kTan: + return "tan"; + case BuiltinFn::kTanh: + return "tanh"; + case BuiltinFn::kTranspose: + return "transpose"; + case BuiltinFn::kTrunc: + return "trunc"; + case BuiltinFn::kUnpack2X16Float: + return "unpack2x16float"; + case BuiltinFn::kUnpack2X16Snorm: + return "unpack2x16snorm"; + case BuiltinFn::kUnpack2X16Unorm: + return "unpack2x16unorm"; + case BuiltinFn::kUnpack4X8Snorm: + return "unpack4x8snorm"; + case BuiltinFn::kUnpack4X8Unorm: + return "unpack4x8unorm"; + case BuiltinFn::kUnpack4XI8: + return "unpack4xI8"; + case BuiltinFn::kUnpack4XU8: + return "unpack4xU8"; + case BuiltinFn::kWorkgroupBarrier: + return "workgroupBarrier"; + case BuiltinFn::kTextureBarrier: + return "textureBarrier"; + case BuiltinFn::kTextureDimensions: + return "textureDimensions"; + case BuiltinFn::kTextureGather: + return "textureGather"; + case BuiltinFn::kTextureGatherCompare: + return "textureGatherCompare"; + case BuiltinFn::kTextureNumLayers: + return "textureNumLayers"; + case BuiltinFn::kTextureNumLevels: + return "textureNumLevels"; + case BuiltinFn::kTextureNumSamples: + return "textureNumSamples"; + case BuiltinFn::kTextureSample: + return "textureSample"; + case BuiltinFn::kTextureSampleBias: + return "textureSampleBias"; + case BuiltinFn::kTextureSampleCompare: + return "textureSampleCompare"; + case BuiltinFn::kTextureSampleCompareLevel: + return "textureSampleCompareLevel"; + case BuiltinFn::kTextureSampleGrad: + return "textureSampleGrad"; + case BuiltinFn::kTextureSampleLevel: + return "textureSampleLevel"; + case BuiltinFn::kTextureSampleBaseClampToEdge: + return "textureSampleBaseClampToEdge"; + case BuiltinFn::kTextureStore: + return "textureStore"; + case BuiltinFn::kTextureLoad: + return "textureLoad"; + case BuiltinFn::kInputAttachmentLoad: + return "inputAttachmentLoad"; + case BuiltinFn::kAtomicLoad: + return "atomicLoad"; + case BuiltinFn::kAtomicStore: + return "atomicStore"; + case BuiltinFn::kAtomicAdd: + return "atomicAdd"; + case BuiltinFn::kAtomicSub: + return "atomicSub"; + case BuiltinFn::kAtomicMax: + return "atomicMax"; + case BuiltinFn::kAtomicMin: + return "atomicMin"; + case BuiltinFn::kAtomicAnd: + return "atomicAnd"; + case BuiltinFn::kAtomicOr: + return "atomicOr"; + case BuiltinFn::kAtomicXor: + return "atomicXor"; + case BuiltinFn::kAtomicExchange: + return "atomicExchange"; + case BuiltinFn::kAtomicCompareExchangeWeak: + return "atomicCompareExchangeWeak"; + case BuiltinFn::kSubgroupBallot: + return "subgroupBallot"; + case BuiltinFn::kSubgroupElect: + return "subgroupElect"; + case BuiltinFn::kSubgroupBroadcast: + return "subgroupBroadcast"; + case BuiltinFn::kSubgroupBroadcastFirst: + return "subgroupBroadcastFirst"; + case BuiltinFn::kSubgroupShuffle: + return "subgroupShuffle"; + case BuiltinFn::kSubgroupShuffleXor: + return "subgroupShuffleXor"; + case BuiltinFn::kSubgroupShuffleUp: + return "subgroupShuffleUp"; + case BuiltinFn::kSubgroupShuffleDown: + return "subgroupShuffleDown"; + case BuiltinFn::kSubgroupAdd: + return "subgroupAdd"; + case BuiltinFn::kSubgroupInclusiveAdd: + return "subgroupInclusiveAdd"; + case BuiltinFn::kSubgroupExclusiveAdd: + return "subgroupExclusiveAdd"; + case BuiltinFn::kSubgroupMul: + return "subgroupMul"; + case BuiltinFn::kSubgroupInclusiveMul: + return "subgroupInclusiveMul"; + case BuiltinFn::kSubgroupExclusiveMul: + return "subgroupExclusiveMul"; + case BuiltinFn::kSubgroupAnd: + return "subgroupAnd"; + case BuiltinFn::kSubgroupOr: + return "subgroupOr"; + case BuiltinFn::kSubgroupXor: + return "subgroupXor"; + case BuiltinFn::kSubgroupMin: + return "subgroupMin"; + case BuiltinFn::kSubgroupMax: + return "subgroupMax"; + case BuiltinFn::kSubgroupAll: + return "subgroupAll"; + case BuiltinFn::kSubgroupAny: + return "subgroupAny"; + case BuiltinFn::kQuadBroadcast: + return "quadBroadcast"; + case BuiltinFn::kQuadSwapX: + return "quadSwapX"; + case BuiltinFn::kQuadSwapY: + return "quadSwapY"; + case BuiltinFn::kQuadSwapDiagonal: + return "quadSwapDiagonal"; + case BuiltinFn::kSubgroupMatrixLoad: + return "subgroupMatrixLoad"; + case BuiltinFn::kSubgroupMatrixStore: + return "subgroupMatrixStore"; + case BuiltinFn::kSubgroupMatrixMultiply: + return "subgroupMatrixMultiply"; + case BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + return "subgroupMatrixMultiplyAccumulate"; + case BuiltinFn::kSubgroupMatrixScalarAdd: + return "subgroupMatrixScalarAdd"; + case BuiltinFn::kSubgroupMatrixScalarSubtract: + return "subgroupMatrixScalarSubtract"; + case BuiltinFn::kSubgroupMatrixScalarMultiply: + return "subgroupMatrixScalarMultiply"; + case BuiltinFn::kBufferView: + return "bufferView"; + case BuiltinFn::kBufferLength: + return "bufferLength"; + case BuiltinFn::kPrint: + return "print"; + case BuiltinFn::kHasResource: + return "hasResource"; + case BuiltinFn::kGetResource: + return "getResource"; + } + return ""; +} + +bool IsTexture(BuiltinFn f) { + return IsImageQuery(f) || // + f == BuiltinFn::kTextureGather || // + f == BuiltinFn::kTextureGatherCompare || // + f == BuiltinFn::kTextureLoad || // + f == BuiltinFn::kTextureSample || // + f == BuiltinFn::kTextureSampleBaseClampToEdge || // + f == BuiltinFn::kTextureSampleBias || // + f == BuiltinFn::kTextureSampleCompare || // + f == BuiltinFn::kTextureSampleCompareLevel || // + f == BuiltinFn::kTextureSampleGrad || // + f == BuiltinFn::kTextureSampleLevel || // + f == BuiltinFn::kTextureStore || f == BuiltinFn::kInputAttachmentLoad; +} + +bool IsImageQuery(BuiltinFn f) { + return f == BuiltinFn::kTextureDimensions || + f == BuiltinFn::kTextureNumLayers || f == BuiltinFn::kTextureNumLevels || + f == BuiltinFn::kTextureNumSamples; +} + +bool IsAtomic(BuiltinFn f) { + return f == BuiltinFn::kAtomicLoad || f == BuiltinFn::kAtomicStore || + f == BuiltinFn::kAtomicAdd || f == BuiltinFn::kAtomicSub || + f == BuiltinFn::kAtomicMax || f == BuiltinFn::kAtomicMin || + f == BuiltinFn::kAtomicAnd || f == BuiltinFn::kAtomicOr || + f == BuiltinFn::kAtomicXor || f == BuiltinFn::kAtomicExchange || + f == BuiltinFn::kAtomicCompareExchangeWeak; +} + +bool IsSubgroup(BuiltinFn f) { + switch (f) { + case BuiltinFn::kSubgroupBallot: + case BuiltinFn::kSubgroupElect: + case BuiltinFn::kSubgroupBroadcast: + case BuiltinFn::kSubgroupBroadcastFirst: + case BuiltinFn::kSubgroupShuffle: + case BuiltinFn::kSubgroupShuffleXor: + case BuiltinFn::kSubgroupShuffleUp: + case BuiltinFn::kSubgroupShuffleDown: + case BuiltinFn::kSubgroupAdd: + case BuiltinFn::kSubgroupInclusiveAdd: + case BuiltinFn::kSubgroupExclusiveAdd: + case BuiltinFn::kSubgroupMul: + case BuiltinFn::kSubgroupInclusiveMul: + case BuiltinFn::kSubgroupExclusiveMul: + case BuiltinFn::kSubgroupAnd: + case BuiltinFn::kSubgroupOr: + case BuiltinFn::kSubgroupXor: + case BuiltinFn::kSubgroupMin: + case BuiltinFn::kSubgroupMax: + case BuiltinFn::kSubgroupAll: + case BuiltinFn::kSubgroupAny: + case BuiltinFn::kQuadBroadcast: + case BuiltinFn::kQuadSwapX: + case BuiltinFn::kQuadSwapY: + case BuiltinFn::kQuadSwapDiagonal: + return true; + default: + return false; + } +} + +bool HasSideEffects(BuiltinFn f) { + switch (f) { + case BuiltinFn::kAtomicAdd: + case BuiltinFn::kAtomicAnd: + case BuiltinFn::kAtomicCompareExchangeWeak: + case BuiltinFn::kAtomicExchange: + case BuiltinFn::kAtomicMax: + case BuiltinFn::kAtomicMin: + case BuiltinFn::kAtomicOr: + case BuiltinFn::kAtomicStore: + case BuiltinFn::kAtomicSub: + case BuiltinFn::kAtomicXor: + case BuiltinFn::kTextureStore: + return true; + default: + break; + } + return false; +} + +} // namespace tint::core + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/core/enums.h b/3rdparty/dawn/src/tint/lang/core/enums.h new file mode 100644 index 000000000..06e31c5a7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/enums.h @@ -0,0 +1,1389 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/core/enums.h.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SRC_TINT_LANG_CORE_ENUMS_H_ +#define SRC_TINT_LANG_CORE_ENUMS_H_ + +// clang-format off + +#include + +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint::core { + +/// Access of a given pointer. +enum class Access : uint8_t { + kUndefined, + kRead, + kReadWrite, + kWrite, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(Access value); + +/// @param out the stream to write to +/// @param value the Access +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Access value) { + return out << ToString(value); +} + +/// ParseAccess parses a Access from a string. +/// @param str the string to parse +/// @returns the parsed enum, or Access::kUndefined if the string could not be parsed. +Access ParseAccess(std::string_view str); + +constexpr std::string_view kAccessStrings[] = { + "read", + "read_write", + "write", +}; + +/// Address space of a given pointer. +enum class AddressSpace : uint8_t { + kUndefined, + kIn, // Tint-internal enum entry - not parsed + kOut, // Tint-internal enum entry - not parsed + kFunction, + kHandle, // Tint-internal enum entry - not parsed + kImmediate, + kPixelLocal, + kPrivate, + kStorage, + kUniform, + kWorkgroup, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(AddressSpace value); + +/// @param out the stream to write to +/// @param value the AddressSpace +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, AddressSpace value) { + return out << ToString(value); +} + +/// ParseAddressSpace parses a AddressSpace from a string. +/// @param str the string to parse +/// @returns the parsed enum, or AddressSpace::kUndefined if the string could not be parsed. +AddressSpace ParseAddressSpace(std::string_view str); + +constexpr std::string_view kAddressSpaceStrings[] = { + "function", + "immediate", + "pixel_local", + "private", + "storage", + "uniform", + "workgroup", +}; + +/// @returns true if the AddressSpace is host-shareable +/// @param address_space the AddressSpace +/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable +inline bool IsHostShareable(AddressSpace address_space) { + return address_space == AddressSpace::kUniform || + address_space == AddressSpace::kStorage || + address_space == AddressSpace::kImmediate; +} + +/// The interpolation sampling. +enum class InterpolationSampling : uint8_t { + kUndefined, + kCenter, + kCentroid, + kEither, + kFirst, + kSample, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(InterpolationSampling value); + +/// @param out the stream to write to +/// @param value the InterpolationSampling +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, InterpolationSampling value) { + return out << ToString(value); +} + +/// ParseInterpolationSampling parses a InterpolationSampling from a string. +/// @param str the string to parse +/// @returns the parsed enum, or InterpolationSampling::kUndefined if the string could not be parsed. +InterpolationSampling ParseInterpolationSampling(std::string_view str); + +constexpr std::string_view kInterpolationSamplingStrings[] = { + "center", + "centroid", + "either", + "first", + "sample", +}; + +/// The interpolation type. +enum class InterpolationType : uint8_t { + kUndefined, + kFlat, + kLinear, + kPerspective, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(InterpolationType value); + +/// @param out the stream to write to +/// @param value the InterpolationType +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, InterpolationType value) { + return out << ToString(value); +} + +/// ParseInterpolationType parses a InterpolationType from a string. +/// @param str the string to parse +/// @returns the parsed enum, or InterpolationType::kUndefined if the string could not be parsed. +InterpolationType ParseInterpolationType(std::string_view str); + +constexpr std::string_view kInterpolationTypeStrings[] = { + "flat", + "linear", + "perspective", +}; + +/// Address space of a given pointer. +enum class SubgroupMatrixKind : uint8_t { + kUndefined, + kLeft, + kResult, + kRight, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(SubgroupMatrixKind value); + +/// @param out the stream to write to +/// @param value the SubgroupMatrixKind +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, SubgroupMatrixKind value) { + return out << ToString(value); +} + +/// ParseSubgroupMatrixKind parses a SubgroupMatrixKind from a string. +/// @param str the string to parse +/// @returns the parsed enum, or SubgroupMatrixKind::kUndefined if the string could not be parsed. +SubgroupMatrixKind ParseSubgroupMatrixKind(std::string_view str); + +constexpr std::string_view kSubgroupMatrixKindStrings[] = { + "left", + "result", + "right", +}; + +/// Enumerator of texel formats +enum class TexelFormat : uint8_t { + kUndefined, + kBgra8Unorm, + kR16Float, + kR16Sint, + kR16Snorm, + kR16Uint, + kR16Unorm, + kR32Float, + kR32Sint, + kR32Uint, + kR8Sint, + kR8Snorm, + kR8Uint, + kR8Unorm, + kRg11B10Ufloat, + kRg16Float, + kRg16Sint, + kRg16Snorm, + kRg16Uint, + kRg16Unorm, + kRg32Float, + kRg32Sint, + kRg32Uint, + kRg8Sint, + kRg8Snorm, + kRg8Uint, + kRg8Unorm, + kRgb10A2Uint, + kRgb10A2Unorm, + kRgba16Float, + kRgba16Sint, + kRgba16Snorm, + kRgba16Uint, + kRgba16Unorm, + kRgba32Float, + kRgba32Sint, + kRgba32Uint, + kRgba8Sint, + kRgba8Snorm, + kRgba8Uint, + kRgba8Unorm, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(TexelFormat value); + +/// @param out the stream to write to +/// @param value the TexelFormat +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, TexelFormat value) { + return out << ToString(value); +} + +/// ParseTexelFormat parses a TexelFormat from a string. +/// @param str the string to parse +/// @returns the parsed enum, or TexelFormat::kUndefined if the string could not be parsed. +TexelFormat ParseTexelFormat(std::string_view str); + +constexpr std::string_view kTexelFormatStrings[] = { + "bgra8unorm", + "r16float", + "r16sint", + "r16snorm", + "r16uint", + "r16unorm", + "r32float", + "r32sint", + "r32uint", + "r8sint", + "r8snorm", + "r8uint", + "r8unorm", + "rg11b10ufloat", + "rg16float", + "rg16sint", + "rg16snorm", + "rg16uint", + "rg16unorm", + "rg32float", + "rg32sint", + "rg32uint", + "rg8sint", + "rg8snorm", + "rg8uint", + "rg8unorm", + "rgb10a2uint", + "rgb10a2unorm", + "rgba16float", + "rgba16sint", + "rgba16snorm", + "rgba16uint", + "rgba16unorm", + "rgba32float", + "rgba32sint", + "rgba32uint", + "rgba8sint", + "rgba8snorm", + "rgba8uint", + "rgba8unorm", +}; + +/// An enumerator of builtin types. +enum class BuiltinType : uint8_t { + kUndefined, + kAtomicCompareExchangeResultI32, + kAtomicCompareExchangeResultU32, + kFrexpResultAbstract, + kFrexpResultF16, + kFrexpResultF32, + kFrexpResultVec2Abstract, + kFrexpResultVec2F16, + kFrexpResultVec2F32, + kFrexpResultVec3Abstract, + kFrexpResultVec3F16, + kFrexpResultVec3F32, + kFrexpResultVec4Abstract, + kFrexpResultVec4F16, + kFrexpResultVec4F32, + kModfResultAbstract, + kModfResultF16, + kModfResultF32, + kModfResultVec2Abstract, + kModfResultVec2F16, + kModfResultVec2F32, + kModfResultVec3Abstract, + kModfResultVec3F16, + kModfResultVec3F32, + kModfResultVec4Abstract, + kModfResultVec4F16, + kModfResultVec4F32, + kArray, + kAtomic, + kBindingArray, + kBool, + kBuffer, + kF16, + kF32, + kI32, + kI8, + kInputAttachment, + kMat2X2, + kMat2X2F, + kMat2X2H, + kMat2X3, + kMat2X3F, + kMat2X3H, + kMat2X4, + kMat2X4F, + kMat2X4H, + kMat3X2, + kMat3X2F, + kMat3X2H, + kMat3X3, + kMat3X3F, + kMat3X3H, + kMat3X4, + kMat3X4F, + kMat3X4H, + kMat4X2, + kMat4X2F, + kMat4X2H, + kMat4X3, + kMat4X3F, + kMat4X3H, + kMat4X4, + kMat4X4F, + kMat4X4H, + kPtr, + kSampler, + kSamplerComparison, + kSubgroupMatrixLeft, + kSubgroupMatrixResult, + kSubgroupMatrixRight, + kTexelBuffer, + kTexture1D, + kTexture2D, + kTexture2DArray, + kTexture3D, + kTextureCube, + kTextureCubeArray, + kTextureDepth2D, + kTextureDepth2DArray, + kTextureDepthCube, + kTextureDepthCubeArray, + kTextureDepthMultisampled2D, + kTextureExternal, + kTextureMultisampled2D, + kTextureStorage1D, + kTextureStorage2D, + kTextureStorage2DArray, + kTextureStorage3D, + kU32, + kU8, + kVec2, + kVec2F, + kVec2H, + kVec2I, + kVec2U, + kVec3, + kVec3F, + kVec3H, + kVec3I, + kVec3U, + kVec4, + kVec4F, + kVec4H, + kVec4I, + kVec4U, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(BuiltinType value); + +/// @param out the stream to write to +/// @param value the BuiltinType +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, BuiltinType value) { + return out << ToString(value); +} + +/// ParseBuiltinType parses a BuiltinType from a string. +/// @param str the string to parse +/// @returns the parsed enum, or BuiltinType::kUndefined if the string could not be parsed. +BuiltinType ParseBuiltinType(std::string_view str); + +constexpr std::string_view kBuiltinTypeStrings[] = { + "__atomic_compare_exchange_result_i32", + "__atomic_compare_exchange_result_u32", + "__frexp_result_abstract", + "__frexp_result_f16", + "__frexp_result_f32", + "__frexp_result_vec2_abstract", + "__frexp_result_vec2_f16", + "__frexp_result_vec2_f32", + "__frexp_result_vec3_abstract", + "__frexp_result_vec3_f16", + "__frexp_result_vec3_f32", + "__frexp_result_vec4_abstract", + "__frexp_result_vec4_f16", + "__frexp_result_vec4_f32", + "__modf_result_abstract", + "__modf_result_f16", + "__modf_result_f32", + "__modf_result_vec2_abstract", + "__modf_result_vec2_f16", + "__modf_result_vec2_f32", + "__modf_result_vec3_abstract", + "__modf_result_vec3_f16", + "__modf_result_vec3_f32", + "__modf_result_vec4_abstract", + "__modf_result_vec4_f16", + "__modf_result_vec4_f32", + "array", + "atomic", + "binding_array", + "bool", + "buffer", + "f16", + "f32", + "i32", + "i8", + "input_attachment", + "mat2x2", + "mat2x2f", + "mat2x2h", + "mat2x3", + "mat2x3f", + "mat2x3h", + "mat2x4", + "mat2x4f", + "mat2x4h", + "mat3x2", + "mat3x2f", + "mat3x2h", + "mat3x3", + "mat3x3f", + "mat3x3h", + "mat3x4", + "mat3x4f", + "mat3x4h", + "mat4x2", + "mat4x2f", + "mat4x2h", + "mat4x3", + "mat4x3f", + "mat4x3h", + "mat4x4", + "mat4x4f", + "mat4x4h", + "ptr", + "sampler", + "sampler_comparison", + "subgroup_matrix_left", + "subgroup_matrix_result", + "subgroup_matrix_right", + "texel_buffer", + "texture_1d", + "texture_2d", + "texture_2d_array", + "texture_3d", + "texture_cube", + "texture_cube_array", + "texture_depth_2d", + "texture_depth_2d_array", + "texture_depth_cube", + "texture_depth_cube_array", + "texture_depth_multisampled_2d", + "texture_external", + "texture_multisampled_2d", + "texture_storage_1d", + "texture_storage_2d", + "texture_storage_2d_array", + "texture_storage_3d", + "u32", + "u8", + "vec2", + "vec2f", + "vec2h", + "vec2i", + "vec2u", + "vec3", + "vec3f", + "vec3h", + "vec3i", + "vec3u", + "vec4", + "vec4f", + "vec4h", + "vec4i", + "vec4u", +}; + +/// Builtin value defined with `@builtin()`. +enum class BuiltinValue : uint8_t { + kUndefined, + kCullDistance, // Tint-internal enum entry - not parsed + kPointSize, // Tint-internal enum entry - not parsed + kBarycentricCoord, + kClipDistances, + kFragDepth, + kFrontFacing, + kGlobalInvocationId, + kInstanceIndex, + kLocalInvocationId, + kLocalInvocationIndex, + kNumSubgroups, + kNumWorkgroups, + kPosition, + kPrimitiveIndex, + kSampleIndex, + kSampleMask, + kSubgroupId, + kSubgroupInvocationId, + kSubgroupSize, + kVertexIndex, + kWorkgroupId, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(BuiltinValue value); + +/// @param out the stream to write to +/// @param value the BuiltinValue +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, BuiltinValue value) { + return out << ToString(value); +} + +/// ParseBuiltinValue parses a BuiltinValue from a string. +/// @param str the string to parse +/// @returns the parsed enum, or BuiltinValue::kUndefined if the string could not be parsed. +BuiltinValue ParseBuiltinValue(std::string_view str); + +constexpr std::string_view kBuiltinValueStrings[] = { + "barycentric_coord", + "clip_distances", + "frag_depth", + "front_facing", + "global_invocation_id", + "instance_index", + "local_invocation_id", + "local_invocation_index", + "num_subgroups", + "num_workgroups", + "position", + "primitive_index", + "sample_index", + "sample_mask", + "subgroup_id", + "subgroup_invocation_id", + "subgroup_size", + "vertex_index", + "workgroup_id", +}; + +/// Builtin depth mode defined with `@builtin(, )`. +enum class BuiltinDepthMode : uint8_t { + kUndefined, + kAny, + kGreater, + kLess, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(BuiltinDepthMode value); + +/// @param out the stream to write to +/// @param value the BuiltinDepthMode +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, BuiltinDepthMode value) { + return out << ToString(value); +} + +/// ParseBuiltinDepthMode parses a BuiltinDepthMode from a string. +/// @param str the string to parse +/// @returns the parsed enum, or BuiltinDepthMode::kUndefined if the string could not be parsed. +BuiltinDepthMode ParseBuiltinDepthMode(std::string_view str); + +constexpr std::string_view kBuiltinDepthModeStrings[] = { + "any", + "greater", + "less", +}; + +/// Address space of a given pointer. +enum class Attribute : uint8_t { + kUndefined, + kAlign, + kBinding, + kBlendSrc, + kBuiltin, + kColor, + kCompute, + kDiagnostic, + kFragment, + kGroup, + kId, + kInputAttachmentIndex, + kInterpolate, + kInvariant, + kLocation, + kMustUse, + kSize, + kSubgroupSize, + kVertex, + kWorkgroupSize, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(Attribute value); + +/// @param out the stream to write to +/// @param value the Attribute +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Attribute value) { + return out << ToString(value); +} + +/// ParseAttribute parses a Attribute from a string. +/// @param str the string to parse +/// @returns the parsed enum, or Attribute::kUndefined if the string could not be parsed. +Attribute ParseAttribute(std::string_view str); + +constexpr std::string_view kAttributeStrings[] = { + "align", + "binding", + "blend_src", + "builtin", + "color", + "compute", + "diagnostic", + "fragment", + "group", + "id", + "input_attachment_index", + "interpolate", + "invariant", + "location", + "must_use", + "size", + "subgroup_size", + "vertex", + "workgroup_size", +}; + +/// ParameterUsage is extra metadata for identifying a parameter based on its +/// overload position +enum class ParameterUsage : uint8_t { + kArrayIndex, + kBase, + kBias, + kBits, + kCompareValue, + kComponent, + kConstOffset, + kCoords, + kCount, + kDdx, + kDdy, + kDelta, + kDepth, + kDepthRef, + kDir, + kDref, + kE, + kElements, + kExp, + kGroupOperation, + kHeight, + kI, + kId, + kImage, + kImageOperands, + kIndex, + kInputAttachment, + kInsert, + kLevel, + kLocation, + kLod, + kM, + kMask, + kNumLevels, + kOffset, + kOriginalValue, + kRefz, + kResult, + kS, + kSample, + kSampleIndex, + kSampler, + kSamples, + kScope, + kSourceLaneIndex, + kTexel, + kTexture, + kValue, + kW, + kWidth, + kX, + kXy, + kXyz, + kY, + kYz, + kZ, + kZw, + kZyw, + kNone, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(ParameterUsage value); + +/// @param out the stream to write to +/// @param value the ParameterUsage +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, ParameterUsage value) { + return out << ToString(value); +} + +/// Enumerator of all builtin functions +enum class BuiltinFn : uint8_t { + kAbs, + kAcos, + kAcosh, + kAll, + kAny, + kArrayLength, + kAsin, + kAsinh, + kAtan, + kAtan2, + kAtanh, + kCeil, + kClamp, + kCos, + kCosh, + kCountLeadingZeros, + kCountOneBits, + kCountTrailingZeros, + kCross, + kDegrees, + kDeterminant, + kDistance, + kDot, + kDot4I8Packed, + kDot4U8Packed, + kDpdx, + kDpdxCoarse, + kDpdxFine, + kDpdy, + kDpdyCoarse, + kDpdyFine, + kExp, + kExp2, + kExtractBits, + kFaceForward, + kFirstLeadingBit, + kFirstTrailingBit, + kFloor, + kFma, + kFract, + kFrexp, + kFwidth, + kFwidthCoarse, + kFwidthFine, + kInsertBits, + kInverseSqrt, + kLdexp, + kLength, + kLog, + kLog2, + kMax, + kMin, + kMix, + kModf, + kNormalize, + kPack2X16Float, + kPack2X16Snorm, + kPack2X16Unorm, + kPack4X8Snorm, + kPack4X8Unorm, + kPack4XI8, + kPack4XU8, + kPack4XI8Clamp, + kPack4XU8Clamp, + kPow, + kQuantizeToF16, + kRadians, + kReflect, + kRefract, + kReverseBits, + kRound, + kSaturate, + kSelect, + kSign, + kSin, + kSinh, + kSmoothstep, + kSqrt, + kStep, + kStorageBarrier, + kTan, + kTanh, + kTranspose, + kTrunc, + kUnpack2X16Float, + kUnpack2X16Snorm, + kUnpack2X16Unorm, + kUnpack4X8Snorm, + kUnpack4X8Unorm, + kUnpack4XI8, + kUnpack4XU8, + kWorkgroupBarrier, + kTextureBarrier, + kTextureDimensions, + kTextureGather, + kTextureGatherCompare, + kTextureNumLayers, + kTextureNumLevels, + kTextureNumSamples, + kTextureSample, + kTextureSampleBias, + kTextureSampleCompare, + kTextureSampleCompareLevel, + kTextureSampleGrad, + kTextureSampleLevel, + kTextureSampleBaseClampToEdge, + kTextureStore, + kTextureLoad, + kInputAttachmentLoad, + kAtomicLoad, + kAtomicStore, + kAtomicAdd, + kAtomicSub, + kAtomicMax, + kAtomicMin, + kAtomicAnd, + kAtomicOr, + kAtomicXor, + kAtomicExchange, + kAtomicCompareExchangeWeak, + kSubgroupBallot, + kSubgroupElect, + kSubgroupBroadcast, + kSubgroupBroadcastFirst, + kSubgroupShuffle, + kSubgroupShuffleXor, + kSubgroupShuffleUp, + kSubgroupShuffleDown, + kSubgroupAdd, + kSubgroupInclusiveAdd, + kSubgroupExclusiveAdd, + kSubgroupMul, + kSubgroupInclusiveMul, + kSubgroupExclusiveMul, + kSubgroupAnd, + kSubgroupOr, + kSubgroupXor, + kSubgroupMin, + kSubgroupMax, + kSubgroupAll, + kSubgroupAny, + kQuadBroadcast, + kQuadSwapX, + kQuadSwapY, + kQuadSwapDiagonal, + kSubgroupMatrixLoad, + kSubgroupMatrixStore, + kSubgroupMatrixMultiply, + kSubgroupMatrixMultiplyAccumulate, + kSubgroupMatrixScalarAdd, + kSubgroupMatrixScalarSubtract, + kSubgroupMatrixScalarMultiply, + kBufferView, + kBufferLength, + kPrint, + kHasResource, + kGetResource, + kNone, +}; + +/// Matches the BuiltinFn by name +/// @param name the builtin name to parse +/// @returns the parsed BuiltinFn, or BuiltinFn::kNone if `name` did not +/// match any builtin function. +BuiltinFn ParseBuiltinFn(std::string_view name); + +/// @returns the name of the builtin function type. The spelling, including +/// case, matches the name in the WGSL spec. +const char* str(BuiltinFn i); + +/// Emits the name of the builtin function type. The spelling, including case, +/// matches the name in the WGSL spec. +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, BuiltinFn i) { + return o << str(i); +} + +/// All builtin functions +constexpr BuiltinFn kBuiltinFns[] = { + BuiltinFn::kAbs, + BuiltinFn::kAcos, + BuiltinFn::kAcosh, + BuiltinFn::kAll, + BuiltinFn::kAny, + BuiltinFn::kArrayLength, + BuiltinFn::kAsin, + BuiltinFn::kAsinh, + BuiltinFn::kAtan, + BuiltinFn::kAtan2, + BuiltinFn::kAtanh, + BuiltinFn::kCeil, + BuiltinFn::kClamp, + BuiltinFn::kCos, + BuiltinFn::kCosh, + BuiltinFn::kCountLeadingZeros, + BuiltinFn::kCountOneBits, + BuiltinFn::kCountTrailingZeros, + BuiltinFn::kCross, + BuiltinFn::kDegrees, + BuiltinFn::kDeterminant, + BuiltinFn::kDistance, + BuiltinFn::kDot, + BuiltinFn::kDot4I8Packed, + BuiltinFn::kDot4U8Packed, + BuiltinFn::kDpdx, + BuiltinFn::kDpdxCoarse, + BuiltinFn::kDpdxFine, + BuiltinFn::kDpdy, + BuiltinFn::kDpdyCoarse, + BuiltinFn::kDpdyFine, + BuiltinFn::kExp, + BuiltinFn::kExp2, + BuiltinFn::kExtractBits, + BuiltinFn::kFaceForward, + BuiltinFn::kFirstLeadingBit, + BuiltinFn::kFirstTrailingBit, + BuiltinFn::kFloor, + BuiltinFn::kFma, + BuiltinFn::kFract, + BuiltinFn::kFrexp, + BuiltinFn::kFwidth, + BuiltinFn::kFwidthCoarse, + BuiltinFn::kFwidthFine, + BuiltinFn::kInsertBits, + BuiltinFn::kInverseSqrt, + BuiltinFn::kLdexp, + BuiltinFn::kLength, + BuiltinFn::kLog, + BuiltinFn::kLog2, + BuiltinFn::kMax, + BuiltinFn::kMin, + BuiltinFn::kMix, + BuiltinFn::kModf, + BuiltinFn::kNormalize, + BuiltinFn::kPack2X16Float, + BuiltinFn::kPack2X16Snorm, + BuiltinFn::kPack2X16Unorm, + BuiltinFn::kPack4X8Snorm, + BuiltinFn::kPack4X8Unorm, + BuiltinFn::kPack4XI8, + BuiltinFn::kPack4XU8, + BuiltinFn::kPack4XI8Clamp, + BuiltinFn::kPack4XU8Clamp, + BuiltinFn::kPow, + BuiltinFn::kQuantizeToF16, + BuiltinFn::kRadians, + BuiltinFn::kReflect, + BuiltinFn::kRefract, + BuiltinFn::kReverseBits, + BuiltinFn::kRound, + BuiltinFn::kSaturate, + BuiltinFn::kSelect, + BuiltinFn::kSign, + BuiltinFn::kSin, + BuiltinFn::kSinh, + BuiltinFn::kSmoothstep, + BuiltinFn::kSqrt, + BuiltinFn::kStep, + BuiltinFn::kStorageBarrier, + BuiltinFn::kTan, + BuiltinFn::kTanh, + BuiltinFn::kTranspose, + BuiltinFn::kTrunc, + BuiltinFn::kUnpack2X16Float, + BuiltinFn::kUnpack2X16Snorm, + BuiltinFn::kUnpack2X16Unorm, + BuiltinFn::kUnpack4X8Snorm, + BuiltinFn::kUnpack4X8Unorm, + BuiltinFn::kUnpack4XI8, + BuiltinFn::kUnpack4XU8, + BuiltinFn::kWorkgroupBarrier, + BuiltinFn::kTextureBarrier, + BuiltinFn::kTextureDimensions, + BuiltinFn::kTextureGather, + BuiltinFn::kTextureGatherCompare, + BuiltinFn::kTextureNumLayers, + BuiltinFn::kTextureNumLevels, + BuiltinFn::kTextureNumSamples, + BuiltinFn::kTextureSample, + BuiltinFn::kTextureSampleBias, + BuiltinFn::kTextureSampleCompare, + BuiltinFn::kTextureSampleCompareLevel, + BuiltinFn::kTextureSampleGrad, + BuiltinFn::kTextureSampleLevel, + BuiltinFn::kTextureSampleBaseClampToEdge, + BuiltinFn::kTextureStore, + BuiltinFn::kTextureLoad, + BuiltinFn::kInputAttachmentLoad, + BuiltinFn::kAtomicLoad, + BuiltinFn::kAtomicStore, + BuiltinFn::kAtomicAdd, + BuiltinFn::kAtomicSub, + BuiltinFn::kAtomicMax, + BuiltinFn::kAtomicMin, + BuiltinFn::kAtomicAnd, + BuiltinFn::kAtomicOr, + BuiltinFn::kAtomicXor, + BuiltinFn::kAtomicExchange, + BuiltinFn::kAtomicCompareExchangeWeak, + BuiltinFn::kSubgroupBallot, + BuiltinFn::kSubgroupElect, + BuiltinFn::kSubgroupBroadcast, + BuiltinFn::kSubgroupBroadcastFirst, + BuiltinFn::kSubgroupShuffle, + BuiltinFn::kSubgroupShuffleXor, + BuiltinFn::kSubgroupShuffleUp, + BuiltinFn::kSubgroupShuffleDown, + BuiltinFn::kSubgroupAdd, + BuiltinFn::kSubgroupInclusiveAdd, + BuiltinFn::kSubgroupExclusiveAdd, + BuiltinFn::kSubgroupMul, + BuiltinFn::kSubgroupInclusiveMul, + BuiltinFn::kSubgroupExclusiveMul, + BuiltinFn::kSubgroupAnd, + BuiltinFn::kSubgroupOr, + BuiltinFn::kSubgroupXor, + BuiltinFn::kSubgroupMin, + BuiltinFn::kSubgroupMax, + BuiltinFn::kSubgroupAll, + BuiltinFn::kSubgroupAny, + BuiltinFn::kQuadBroadcast, + BuiltinFn::kQuadSwapX, + BuiltinFn::kQuadSwapY, + BuiltinFn::kQuadSwapDiagonal, + BuiltinFn::kSubgroupMatrixLoad, + BuiltinFn::kSubgroupMatrixStore, + BuiltinFn::kSubgroupMatrixMultiply, + BuiltinFn::kSubgroupMatrixMultiplyAccumulate, + BuiltinFn::kSubgroupMatrixScalarAdd, + BuiltinFn::kSubgroupMatrixScalarSubtract, + BuiltinFn::kSubgroupMatrixScalarMultiply, + BuiltinFn::kBufferView, + BuiltinFn::kBufferLength, + BuiltinFn::kPrint, + BuiltinFn::kHasResource, + BuiltinFn::kGetResource, +}; + +/// All builtin function names +constexpr const char* kBuiltinFnStrings[] = { + "abs", + "acos", + "acosh", + "all", + "any", + "arrayLength", + "asin", + "asinh", + "atan", + "atan2", + "atanh", + "ceil", + "clamp", + "cos", + "cosh", + "countLeadingZeros", + "countOneBits", + "countTrailingZeros", + "cross", + "degrees", + "determinant", + "distance", + "dot", + "dot4I8Packed", + "dot4U8Packed", + "dpdx", + "dpdxCoarse", + "dpdxFine", + "dpdy", + "dpdyCoarse", + "dpdyFine", + "exp", + "exp2", + "extractBits", + "faceForward", + "firstLeadingBit", + "firstTrailingBit", + "floor", + "fma", + "fract", + "frexp", + "fwidth", + "fwidthCoarse", + "fwidthFine", + "insertBits", + "inverseSqrt", + "ldexp", + "length", + "log", + "log2", + "max", + "min", + "mix", + "modf", + "normalize", + "pack2x16float", + "pack2x16snorm", + "pack2x16unorm", + "pack4x8snorm", + "pack4x8unorm", + "pack4xI8", + "pack4xU8", + "pack4xI8Clamp", + "pack4xU8Clamp", + "pow", + "quantizeToF16", + "radians", + "reflect", + "refract", + "reverseBits", + "round", + "saturate", + "select", + "sign", + "sin", + "sinh", + "smoothstep", + "sqrt", + "step", + "storageBarrier", + "tan", + "tanh", + "transpose", + "trunc", + "unpack2x16float", + "unpack2x16snorm", + "unpack2x16unorm", + "unpack4x8snorm", + "unpack4x8unorm", + "unpack4xI8", + "unpack4xU8", + "workgroupBarrier", + "textureBarrier", + "textureDimensions", + "textureGather", + "textureGatherCompare", + "textureNumLayers", + "textureNumLevels", + "textureNumSamples", + "textureSample", + "textureSampleBias", + "textureSampleCompare", + "textureSampleCompareLevel", + "textureSampleGrad", + "textureSampleLevel", + "textureSampleBaseClampToEdge", + "textureStore", + "textureLoad", + "inputAttachmentLoad", + "atomicLoad", + "atomicStore", + "atomicAdd", + "atomicSub", + "atomicMax", + "atomicMin", + "atomicAnd", + "atomicOr", + "atomicXor", + "atomicExchange", + "atomicCompareExchangeWeak", + "subgroupBallot", + "subgroupElect", + "subgroupBroadcast", + "subgroupBroadcastFirst", + "subgroupShuffle", + "subgroupShuffleXor", + "subgroupShuffleUp", + "subgroupShuffleDown", + "subgroupAdd", + "subgroupInclusiveAdd", + "subgroupExclusiveAdd", + "subgroupMul", + "subgroupInclusiveMul", + "subgroupExclusiveMul", + "subgroupAnd", + "subgroupOr", + "subgroupXor", + "subgroupMin", + "subgroupMax", + "subgroupAll", + "subgroupAny", + "quadBroadcast", + "quadSwapX", + "quadSwapY", + "quadSwapDiagonal", + "subgroupMatrixLoad", + "subgroupMatrixStore", + "subgroupMatrixMultiply", + "subgroupMatrixMultiplyAccumulate", + "subgroupMatrixScalarAdd", + "subgroupMatrixScalarSubtract", + "subgroupMatrixScalarMultiply", + "bufferView", + "bufferLength", + "print", + "hasResource", + "getResource", +}; + +/// Determines if the given `f` is a coarse derivative. +/// @param f the builtin type +/// @returns true if the given derivative is coarse. +bool IsCoarseDerivative(BuiltinFn f); + +/// Determines if the given `f` is a fine derivative. +/// @param f the builtin type +/// @returns true if the given derivative is fine. +bool IsFineDerivative(BuiltinFn f); + +/// Determine if the given `f` is a derivative builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a derivative builtin +bool IsDerivative(BuiltinFn f); + +/// Determines if the given `f` is a texture operation builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a texture operation builtin +bool IsTexture(BuiltinFn f); + +/// Determines if the given `f` is an image query builtin. +/// @param f the builtin type +/// @returns true if the given `f` is an image query builtin +bool IsImageQuery(BuiltinFn f); + +/// Determines if the given `f` is a data packing builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a data packing builtin +bool IsDataPacking(BuiltinFn f); + +/// Determines if the given `f` is a data unpacking builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a data unpacking builtin +bool IsDataUnpacking(BuiltinFn f); + +/// Determines if the given `f` is a barrier builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a barrier builtin +bool IsBarrier(BuiltinFn f); + +/// Determines if the given `f` is an atomic builtin. +/// @param f the builtin type +/// @returns true if the given `f` is an atomic builtin +bool IsAtomic(BuiltinFn f); + +/// Determines if the given `f` is a builtin defined in the language extension +/// `packed_4x8_integer_dot_product`. +/// @param f the builtin type +/// @returns true if the given `f` is a builtin defined in the language extension +/// `packed_4x8_integer_dot_product`. +bool IsPacked4x8IntegerDotProductBuiltin(BuiltinFn f); + +/// Determines if the given `f` is a subgroup builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a subgroup builtin +bool IsSubgroup(BuiltinFn f); + +/// Determines if the given `f` may have side-effects (i.e. writes to at least one of its inputs) +/// @returns true if intrinsic may have side-effects +bool HasSideEffects(BuiltinFn f); + +} // namespace tint::core + +namespace tint { + +/// Access reflection information +TINT_REFLECT_ENUM_RANGE(core::Access, kUndefined, kWrite); + +/// SubgroupMatrixType reflection information +TINT_REFLECT_ENUM_RANGE(core::SubgroupMatrixKind, kUndefined, kRight); + +} // namespace tint + +// clang-format on + +#endif // SRC_TINT_LANG_CORE_ENUMS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/evaluation_stage.h b/3rdparty/dawn/src/tint/lang/core/evaluation_stage.h new file mode 100644 index 000000000..3ecae0103 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/evaluation_stage.h @@ -0,0 +1,75 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_EVALUATION_STAGE_H_ +#define SRC_TINT_LANG_CORE_EVALUATION_STAGE_H_ + +#include +#include + +namespace tint::core { + +/// The earliest point in time that an expression can be evaluated +enum class EvaluationStage { + /// Expression will not be evaluated + kNotEvaluated, + /// Expression can be evaluated at shader creation time + kConstant, + /// Expression can be evaluated at pipeline creation time + kOverride, + /// Expression can be evaluated at runtime + kRuntime, +}; + +/// @returns true if stage `a` comes earlier than stage `b` +inline bool operator<(EvaluationStage a, EvaluationStage b) { + return static_cast(a) < static_cast(b); +} + +/// @returns true if stage `a` comes later than stage `b` +inline bool operator>(EvaluationStage a, EvaluationStage b) { + return static_cast(a) > static_cast(b); +} + +/// @param stages a list of EvaluationStage. +/// @returns the earliest stage supported by all the provided stages +inline EvaluationStage EarliestStage(std::initializer_list stages) { + auto earliest = EvaluationStage::kNotEvaluated; + for (auto stage : stages) { + earliest = std::max(stage, earliest); + } + return static_cast(earliest); +} + +template +inline EvaluationStage EarliestStage(ARGS... args) { + return EarliestStage({args...}); +} + +} // namespace tint::core + +#endif // SRC_TINT_LANG_CORE_EVALUATION_STAGE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/fluent_types.h b/3rdparty/dawn/src/tint/lang/core/fluent_types.h new file mode 100644 index 000000000..de6ab77fe --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/fluent_types.h @@ -0,0 +1,294 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_FLUENT_TYPES_H_ +#define SRC_TINT_LANG_CORE_FLUENT_TYPES_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/number.h" + +namespace tint::core::fluent_types { + +using f16 = tint::core::f16; +using f32 = tint::core::f32; +using i32 = tint::core::i32; +using i8 = tint::core::i8; +using u32 = tint::core::u32; +using u64 = tint::core::u64; +using u8 = tint::core::u8; +using AFloat = tint::core::AFloat; +using AInt = tint::core::AInt; + +// 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 +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 +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 +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 +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; +}; + +/// 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 +struct ptr { + /// the pointer address space + static constexpr core::AddressSpace address = ADDRESS; + /// the pointer storage type + using type = T; + /// the pointer access control + static constexpr core::Access access = ACCESS; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Aliases +// +// Shorthand aliases for the types declared above +//////////////////////////////////////////////////////////////////////////////// + +//! @cond Doxygen_Suppress +template +using mat2x2 = mat<2, 2, T>; + +template +using mat2x3 = mat<2, 3, T>; + +template +using mat2x4 = mat<2, 4, T>; + +template +using mat3x2 = mat<3, 2, T>; + +template +using mat3x3 = mat<3, 3, T>; + +template +using mat3x4 = mat<3, 4, T>; + +template +using mat4x2 = mat<4, 2, T>; + +template +using mat4x3 = mat<4, 3, T>; + +template +using mat4x4 = mat<4, 4, T>; + +template +using vec2 = vec<2, T>; + +template +using vec3 = vec<3, T>; + +template +using vec4 = vec<4, T>; + +using mat2x2f = mat<2, 2, f32>; +using mat2x3f = mat<2, 3, f32>; +using mat2x4f = mat<2, 4, f32>; +using mat3x2f = mat<3, 2, f32>; +using mat3x3f = mat<3, 3, f32>; +using mat3x4f = mat<3, 4, f32>; +using mat4x2f = mat<4, 2, f32>; +using mat4x3f = mat<4, 3, f32>; +using mat4x4f = mat<4, 4, f32>; + +using mat2x2h = mat<2, 2, f16>; +using mat2x3h = mat<2, 3, f16>; +using mat2x4h = mat<2, 4, f16>; +using mat3x2h = mat<3, 2, f16>; +using mat3x3h = mat<3, 3, f16>; +using mat3x4h = mat<3, 4, f16>; +using mat4x2h = mat<4, 2, f16>; +using mat4x3h = mat<4, 3, f16>; +using mat4x4h = mat<4, 4, f16>; + +using vec2f = vec<2, f32>; +using vec3f = vec<3, f32>; +using vec4f = vec<4, f32>; + +using vec2h = vec<2, f16>; +using vec3h = vec<3, f16>; +using vec4h = vec<4, f16>; + +using vec2i = vec<2, i32>; +using vec3i = vec<3, i32>; +using vec4i = vec<4, i32>; + +using vec2u = vec<2, u32>; +using vec3u = vec<3, u32>; +using vec4u = vec<4, u32>; + +//! @endcond + +//////////////////////////////////////////////////////////////////////////////// +// Address space aliases +//////////////////////////////////////////////////////////////////////////////// +static constexpr core::AddressSpace function = core::AddressSpace::kFunction; +static constexpr core::AddressSpace handle = core::AddressSpace::kHandle; +static constexpr core::AddressSpace private_ = core::AddressSpace::kPrivate; +static constexpr core::AddressSpace immediate = core::AddressSpace::kImmediate; +static constexpr core::AddressSpace storage = core::AddressSpace::kStorage; +static constexpr core::AddressSpace uniform = core::AddressSpace::kUniform; +static constexpr core::AddressSpace workgroup = core::AddressSpace::kWorkgroup; + +//////////////////////////////////////////////////////////////////////////////// +// Access control aliases +//////////////////////////////////////////////////////////////////////////////// +static constexpr core::Access read = core::Access::kRead; +static constexpr core::Access read_write = core::Access::kReadWrite; +static constexpr core::Access write = core::Access::kWrite; + +//////////////////////////////////////////////////////////////////////////////// +// Traits +//////////////////////////////////////////////////////////////////////////////// +namespace detail { + +//! @cond Doxygen_Suppress +template +struct IsArray { + static constexpr bool value = false; +}; + +template +struct IsArray> { + static constexpr bool value = true; +}; + +template +struct IsAtomic { + static constexpr bool value = false; +}; + +template +struct IsAtomic> { + static constexpr bool value = true; +}; + +template +struct IsMatrix { + static constexpr bool value = false; +}; + +template +struct IsMatrix> { + static constexpr bool value = true; +}; + +template +struct IsVector { + static constexpr bool value = false; +}; + +template +struct IsVector> { + static constexpr bool value = true; +}; + +template +struct IsPointer { + static constexpr bool value = false; +}; + +template +struct IsPointer> { + static constexpr bool value = true; +}; +//! @endcond + +} // namespace detail + +/// Evaluates to true if `T` is a array +template +static constexpr bool IsArray = fluent_types::detail::IsArray::value; + +/// Evaluates to true if `T` is a atomic +template +static constexpr bool IsAtomic = fluent_types::detail::IsAtomic::value; + +/// Evaluates to true if `T` is a mat +template +static constexpr bool IsMatrix = fluent_types::detail::IsMatrix::value; + +/// Evaluates to true if `T` is a vec +template +static constexpr bool IsVector = fluent_types::detail::IsVector::value; + +/// Evaluates to true if `T` is a ptr +template +static constexpr bool IsPointer = fluent_types::detail::IsPointer::value; + +} // namespace tint::core::fluent_types + +#endif // SRC_TINT_LANG_CORE_FLUENT_TYPES_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/interpolation.h b/3rdparty/dawn/src/tint/lang/core/interpolation.h new file mode 100644 index 000000000..46dfdfd18 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/interpolation.h @@ -0,0 +1,45 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_INTERPOLATION_H_ +#define SRC_TINT_LANG_CORE_INTERPOLATION_H_ + +#include "src/tint/lang/core/enums.h" + +namespace tint::core { + +/// The values of an `@interpolate` attribute +struct Interpolation { + /// The first argument of a `@interpolate` attribute + core::InterpolationType type = core::InterpolationType::kUndefined; + /// The second argument of a `@interpolate` attribute + core::InterpolationSampling sampling = core::InterpolationSampling::kUndefined; +}; + +} // namespace tint::core + +#endif // SRC_TINT_LANG_CORE_INTERPOLATION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.cc b/3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.cc new file mode 100644 index 000000000..6d7975a1a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.cc @@ -0,0 +1,93 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/core/intrinsic/ctor_conv.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include "src/tint/lang/core/intrinsic/ctor_conv.h" + +namespace tint::core::intrinsic { + +const char* str(CtorConv i) { + switch (i) { + case CtorConv::kNone: + return ""; + case CtorConv::kI32: + return "i32"; + case CtorConv::kU32: + return "u32"; + case CtorConv::kF32: + return "f32"; + case CtorConv::kF16: + return "f16"; + case CtorConv::kBool: + return "bool"; + case CtorConv::kVec2: + return "vec2"; + case CtorConv::kVec3: + return "vec3"; + case CtorConv::kVec4: + return "vec4"; + case CtorConv::kMat2x2: + return "mat2x2"; + case CtorConv::kMat2x3: + return "mat2x3"; + case CtorConv::kMat2x4: + return "mat2x4"; + case CtorConv::kMat3x2: + return "mat3x2"; + case CtorConv::kMat3x3: + return "mat3x3"; + case CtorConv::kMat3x4: + return "mat3x4"; + case CtorConv::kMat4x2: + return "mat4x2"; + case CtorConv::kMat4x3: + return "mat4x3"; + case CtorConv::kMat4x4: + return "mat4x4"; + case CtorConv::kSubgroup_matrix_left: + return "subgroup_matrix_left"; + case CtorConv::kSubgroup_matrix_right: + return "subgroup_matrix_right"; + case CtorConv::kSubgroup_matrix_result: + return "subgroup_matrix_result"; + } + return ""; +} + +} // namespace tint::core::intrinsic + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.h b/3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.h new file mode 100644 index 000000000..2416dd6d1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/ctor_conv.h @@ -0,0 +1,133 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/core/intrinsic/ctor_conv.h.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SRC_TINT_LANG_CORE_INTRINSIC_CTOR_CONV_H_ +#define SRC_TINT_LANG_CORE_INTRINSIC_CTOR_CONV_H_ + +// clang-format off + +#include + +#include "src/tint/utils/rtti/traits.h" + +namespace tint::core::intrinsic { + +/// CtorConv is an enumerator of types that have a constructor or converter overload +/// declared in the intrinsic table. +enum class CtorConv : uint8_t { + kI32, + kU32, + kF32, + kF16, + kBool, + kVec2, + kVec3, + kVec4, + kMat2x2, + kMat2x3, + kMat2x4, + kMat3x2, + kMat3x3, + kMat3x4, + kMat4x2, + kMat4x3, + kMat4x4, + kSubgroup_matrix_left, + kSubgroup_matrix_right, + kSubgroup_matrix_result, + kNone, +}; + +/// @returns the name of the enumerator +/// @param i the CtorConv enumerator +const char* str(CtorConv i); + +/// Prints the CtorConv @p c to @p o +/// @param o the stream to write to +/// @param c the CtorConv +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, CtorConv c) { + return o << str(c); +} + +/// @param n the width of the vector +/// @return the CtorConv for a vector of width `n` +inline CtorConv VectorCtorConv(uint32_t n) { + switch (n) { + case 2: + return CtorConv::kVec2; + case 3: + return CtorConv::kVec3; + case 4: + return CtorConv::kVec4; + } + return CtorConv::kNone; +} + +/// @param c the number of columns in the matrix +/// @param r the number of rows in the matrix +/// @return the CtorConv for a matrix with `c` columns and `r` rows +inline CtorConv MatrixCtorConv(uint32_t c, uint32_t r) { + switch ((c - 2) * 3 + (r - 2)) { + case 0: + return CtorConv::kMat2x2; + case 1: + return CtorConv::kMat2x3; + case 2: + return CtorConv::kMat2x4; + case 3: + return CtorConv::kMat3x2; + case 4: + return CtorConv::kMat3x3; + case 5: + return CtorConv::kMat3x4; + case 6: + return CtorConv::kMat4x2; + case 7: + return CtorConv::kMat4x3; + case 8: + return CtorConv::kMat4x4; + } + return CtorConv::kNone; +} + +} // namespace tint::core::intrinsic + +// clang-format on + +#endif // SRC_TINT_LANG_CORE_INTRINSIC_CTOR_CONV_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/data.cc b/3rdparty/dawn/src/tint/lang/core/intrinsic/data.cc new file mode 100644 index 000000000..af7cbdb66 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/data.cc @@ -0,0 +1,13850 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/core/intrinsic/data.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include +#include + +#include "src/tint/lang/core/intrinsic/dialect.h" +#include "src/tint/lang/core/intrinsic/type_matchers.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::core::intrinsic { + +namespace { + +using ConstEvalFunctionIndex = tint::core::intrinsic::ConstEvalFunctionIndex; +using IntrinsicInfo = tint::core::intrinsic::IntrinsicInfo; +using MatcherIndicesIndex = tint::core::intrinsic::MatcherIndicesIndex; +using MatchState = tint::core::intrinsic::MatchState; +using Number = tint::core::intrinsic::Number; +using NumberMatcher = tint::core::intrinsic::NumberMatcher; +using NumberMatcherIndex = tint::core::intrinsic::NumberMatcherIndex; +using OverloadFlag = tint::core::intrinsic::OverloadFlag; +using OverloadFlags = tint::core::intrinsic::OverloadFlags; +using OverloadIndex = tint::core::intrinsic::OverloadIndex; +using OverloadInfo = tint::core::intrinsic::OverloadInfo; +using ParameterIndex = tint::core::intrinsic::ParameterIndex; +using ParameterInfo = tint::core::intrinsic::ParameterInfo; +using StringStream = tint::StringStream; +using TemplateIndex = tint::core::intrinsic::TemplateIndex; +using Type = tint::core::type::Type; +using TypeMatcher = tint::core::intrinsic::TypeMatcher; +using TypeMatcherIndex = tint::core::intrinsic::TypeMatcherIndex; + +template +using TemplateNumberMatcher = tint::core::intrinsic::TemplateNumberMatcher; + +template +using TemplateTypeMatcher = tint::core::intrinsic::TemplateTypeMatcher; + +/// TypeMatcher for 'type bool' +constexpr TypeMatcher kBoolMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchBool(state, ty)) { + return nullptr; + } + return BuildBool(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("bool"); + } +}; + + +/// TypeMatcher for 'type i8' +constexpr TypeMatcher kI8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchI8(state, ty)) { + return nullptr; + } + return BuildI8(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("i8"); + } +}; + + +/// TypeMatcher for 'type u8' +constexpr TypeMatcher kU8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchU8(state, ty)) { + return nullptr; + } + return BuildU8(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("u8"); + } +}; + + +/// TypeMatcher for 'type i32' +constexpr TypeMatcher kI32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchI32(state, ty)) { + return nullptr; + } + return BuildI32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("i32"); + } +}; + + +/// TypeMatcher for 'type u32' +constexpr TypeMatcher kU32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchU32(state, ty)) { + return nullptr; + } + return BuildU32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("u32"); + } +}; + + +/// TypeMatcher for 'type f32' +constexpr TypeMatcher kF32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchF32(state, ty)) { + return nullptr; + } + return BuildF32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("f32"); + } +}; + + +/// TypeMatcher for 'type f16' +constexpr TypeMatcher kF16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchF16(state, ty)) { + return nullptr; + } + return BuildF16(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("f16"); + } +}; + + +/// TypeMatcher for 'type vec2' +constexpr TypeMatcher kVec2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec3' +constexpr TypeMatcher kVec3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec4' +constexpr TypeMatcher kVec4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x2' +constexpr TypeMatcher kMat2X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x3' +constexpr TypeMatcher kMat2X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x4' +constexpr TypeMatcher kMat2X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x2' +constexpr TypeMatcher kMat3X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x3' +constexpr TypeMatcher kMat3X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x4' +constexpr TypeMatcher kMat3X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x2' +constexpr TypeMatcher kMat4X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x3' +constexpr TypeMatcher kMat4X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x4' +constexpr TypeMatcher kMat4X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec' +constexpr TypeMatcher kVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("vec", N, "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat' +constexpr TypeMatcher kMatMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + Number M = Number::invalid; + const Type* T = nullptr; + if (!MatchMat(state, ty, N, M, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + M = state.Num(M); + if (!M.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat(state, ty, N, M, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText M; + state->PrintNum(M);StyledText T; + state->PrintType(T); + out << style::Type("mat", N, "x", M, "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type ptr' +constexpr TypeMatcher kPtrMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number A = Number::invalid; + if (!MatchPtr(state, ty, S, T, A)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildPtr(state, ty, S, T, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText A; + state->PrintNum(A); + out << style::Type("ptr", "<", S, ", ", T, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type atomic' +constexpr TypeMatcher kAtomicMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchAtomic(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildAtomic(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("atomic", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type runtime_array' +constexpr TypeMatcher kRuntimeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchRuntimeArray(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildRuntimeArray(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("array<", T, ">"); + } +}; + + +/// TypeMatcher for 'type array' +constexpr TypeMatcher kArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + Number N = Number::invalid; + if (!MatchArray(state, ty, T, N)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + return BuildArray(state, ty, T, N); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T);StyledText N; + state->PrintNum(N); + out << style::Type("array", "<", T, ", ", N, ">"); + } +}; + + +/// TypeMatcher for 'type binding_array' +constexpr TypeMatcher kBindingArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + Number N = Number::invalid; + if (!MatchBindingArray(state, ty, T, N)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + return BuildBindingArray(state, ty, T, N); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T);StyledText N; + state->PrintNum(N); + out << style::Type("binding_array", "<", T, ", ", N, ">"); + } +}; + + +/// TypeMatcher for 'type sampler' +constexpr TypeMatcher kSamplerMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchSampler(state, ty)) { + return nullptr; + } + return BuildSampler(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("sampler"); + } +}; + + +/// TypeMatcher for 'type sampler_comparison' +constexpr TypeMatcher kSamplerComparisonMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchSamplerComparison(state, ty)) { + return nullptr; + } + return BuildSamplerComparison(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("sampler_comparison"); + } +}; + + +/// TypeMatcher for 'type texture_1d' +constexpr TypeMatcher kTexture1DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture1D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture1D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_1d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_2d' +constexpr TypeMatcher kTexture2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture2D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture2D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_2d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_2d_array' +constexpr TypeMatcher kTexture2DArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture2DArray(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture2DArray(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_2d_array", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_3d' +constexpr TypeMatcher kTexture3DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture3D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture3D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_3d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_cube' +constexpr TypeMatcher kTextureCubeMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTextureCube(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTextureCube(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_cube", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_cube_array' +constexpr TypeMatcher kTextureCubeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTextureCubeArray(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTextureCubeArray(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_cube_array", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_multisampled_2d' +constexpr TypeMatcher kTextureMultisampled2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTextureMultisampled2D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTextureMultisampled2D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_multisampled_2d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_depth_2d' +constexpr TypeMatcher kTextureDepth2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepth2D(state, ty)) { + return nullptr; + } + return BuildTextureDepth2D(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_2d"); + } +}; + + +/// TypeMatcher for 'type texture_depth_2d_array' +constexpr TypeMatcher kTextureDepth2DArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepth2DArray(state, ty)) { + return nullptr; + } + return BuildTextureDepth2DArray(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_2d_array"); + } +}; + + +/// TypeMatcher for 'type texture_depth_cube' +constexpr TypeMatcher kTextureDepthCubeMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepthCube(state, ty)) { + return nullptr; + } + return BuildTextureDepthCube(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_cube"); + } +}; + + +/// TypeMatcher for 'type texture_depth_cube_array' +constexpr TypeMatcher kTextureDepthCubeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepthCubeArray(state, ty)) { + return nullptr; + } + return BuildTextureDepthCubeArray(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_cube_array"); + } +}; + + +/// TypeMatcher for 'type texture_depth_multisampled_2d' +constexpr TypeMatcher kTextureDepthMultisampled2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepthMultisampled2D(state, ty)) { + return nullptr; + } + return BuildTextureDepthMultisampled2D(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_multisampled_2d"); + } +}; + + +/// TypeMatcher for 'type texture_storage_1d' +constexpr TypeMatcher kTextureStorage1DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage1D(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage1D(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_1d", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_storage_2d' +constexpr TypeMatcher kTextureStorage2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage2D(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage2D(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_2d", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_storage_2d_array' +constexpr TypeMatcher kTextureStorage2DArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage2DArray(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage2DArray(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_2d_array", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_storage_3d' +constexpr TypeMatcher kTextureStorage3DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage3D(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage3D(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_3d", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_external' +constexpr TypeMatcher kTextureExternalMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureExternal(state, ty)) { + return nullptr; + } + return BuildTextureExternal(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_external"); + } +}; + + +/// TypeMatcher for 'type texel_buffer' +constexpr TypeMatcher kTexelBufferMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTexelBuffer(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTexelBuffer(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texel_buffer", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type input_attachment' +constexpr TypeMatcher kInputAttachmentMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchInputAttachment(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildInputAttachment(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("input_attachment", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type __modf_result' +constexpr TypeMatcher kModfResultMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchModfResult(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildModfResult(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("__modf_result_", T); + } +}; + + +/// TypeMatcher for 'type __modf_result_vec' +constexpr TypeMatcher kModfResultVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchModfResultVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildModfResultVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("__modf_result_vec", N, "_", T); + } +}; + + +/// TypeMatcher for 'type __frexp_result' +constexpr TypeMatcher kFrexpResultMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchFrexpResult(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildFrexpResult(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("__frexp_result_", T); + } +}; + + +/// TypeMatcher for 'type __frexp_result_vec' +constexpr TypeMatcher kFrexpResultVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchFrexpResultVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildFrexpResultVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("__frexp_result_vec", N, "_", T); + } +}; + + +/// TypeMatcher for 'type __atomic_compare_exchange_result' +constexpr TypeMatcher kAtomicCompareExchangeResultMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchAtomicCompareExchangeResult(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildAtomicCompareExchangeResult(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("__atomic_compare_exchange_result", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type subgroup_matrix' +constexpr TypeMatcher kSubgroupMatrixMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number C = Number::invalid; + Number R = Number::invalid; + if (!MatchSubgroupMatrix(state, ty, S, T, C, R)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + C = state.Num(C); + if (!C.IsValid()) { + return nullptr; + } + R = state.Num(R); + if (!R.IsValid()) { + return nullptr; + } + return BuildSubgroupMatrix(state, ty, S, T, C, R); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText C; + state->PrintNum(C);StyledText R; + state->PrintNum(R); + out << style::Type("subgroup_matrix", "<", S, ", ", T, ", ", C, ", ", R, ">"); + } +}; + + +/// TypeMatcher for 'type unsized_buffer' +constexpr TypeMatcher kUnsizedBufferMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchUnsizedBuffer(state, ty)) { + return nullptr; + } + return BuildUnsizedBuffer(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("buffer"); + } +}; + + +/// TypeMatcher for 'type buffer' +constexpr TypeMatcher kBufferMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + if (!MatchBuffer(state, ty, N)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + return BuildBuffer(state, ty, N); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N); + out << style::Type("buffer", "<", N, ">"); + } +}; + + +/// TypeMatcher for 'match scalar' +constexpr TypeMatcher kScalarMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_f32' +constexpr TypeMatcher kScalarNoF32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_f16' +constexpr TypeMatcher kScalarNoF16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_i32' +constexpr TypeMatcher kScalarNoI32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_u32' +constexpr TypeMatcher kScalarNoU32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_bool' +constexpr TypeMatcher kScalarNoBoolMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fiu32_f16' +constexpr TypeMatcher kFiu32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fiu32' +constexpr TypeMatcher kFiu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fi32_f16' +constexpr TypeMatcher kFi32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fi32' +constexpr TypeMatcher kFi32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(" or "); kI32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match f32_f16' +constexpr TypeMatcher kF32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu32' +constexpr TypeMatcher kIu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu32_iu8' +constexpr TypeMatcher kIu32Iu8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(", "); kI8Matcher.print(nullptr, out); out << style::Plain(" or "); kU8Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu8' +constexpr TypeMatcher kIu8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI8Matcher.print(nullptr, out); out << style::Plain(" or "); kU8Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match subgroup_matrix_elements' +constexpr TypeMatcher kSubgroupMatrixElementsMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU8Matcher.print(nullptr, out); out << style::Plain(" or "); kI8Matcher.print(nullptr, out);} +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_left' +constexpr NumberMatcher kSubgroupMatrixKindLeftMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kLeft)) { + return Number(static_cast(core::SubgroupMatrixKind::kLeft)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("left"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_right' +constexpr NumberMatcher kSubgroupMatrixKindRightMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kRight)) { + return Number(static_cast(core::SubgroupMatrixKind::kRight)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("right"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_result' +constexpr NumberMatcher kSubgroupMatrixKindResultMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kResult)) { + return Number(static_cast(core::SubgroupMatrixKind::kResult)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("result"); + } +}; + +/// EnumMatcher for 'match f32_texel_format' +constexpr NumberMatcher kF32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Unorm: + case core::TexelFormat::kR8Snorm: + case core::TexelFormat::kRg8Unorm: + case core::TexelFormat::kRg8Snorm: + case core::TexelFormat::kBgra8Unorm: + case core::TexelFormat::kRgba8Unorm: + case core::TexelFormat::kRgba8Snorm: + case core::TexelFormat::kR16Unorm: + case core::TexelFormat::kR16Snorm: + case core::TexelFormat::kRg16Unorm: + case core::TexelFormat::kRg16Snorm: + case core::TexelFormat::kRgba16Unorm: + case core::TexelFormat::kRgba16Snorm: + case core::TexelFormat::kR16Float: + case core::TexelFormat::kRg16Float: + case core::TexelFormat::kRgba16Float: + case core::TexelFormat::kR32Float: + case core::TexelFormat::kRg32Float: + case core::TexelFormat::kRgba32Float: + case core::TexelFormat::kRgb10A2Unorm: + case core::TexelFormat::kRg11B10Ufloat: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8unorm")<< style::Plain(", ") << style::Enum("r8snorm")<< style::Plain(", ") << style::Enum("rg8unorm")<< style::Plain(", ") << style::Enum("rg8snorm")<< style::Plain(", ") << style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("r16unorm")<< style::Plain(", ") << style::Enum("r16snorm")<< style::Plain(", ") << style::Enum("rg16unorm")<< style::Plain(", ") << style::Enum("rg16snorm")<< style::Plain(", ") << style::Enum("rgba16unorm")<< style::Plain(", ") << style::Enum("rgba16snorm")<< style::Plain(", ") << style::Enum("r16float")<< style::Plain(", ") << style::Enum("rg16float")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(", ") << style::Enum("rgba32float")<< style::Plain(", ") << style::Enum("rgb10a2unorm")<< style::Plain(" or ") << style::Enum("rg11b10ufloat"); + } +}; + +/// EnumMatcher for 'match i32_texel_format' +constexpr NumberMatcher kI32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Sint: + case core::TexelFormat::kRg8Sint: + case core::TexelFormat::kRgba8Sint: + case core::TexelFormat::kR16Sint: + case core::TexelFormat::kRg16Sint: + case core::TexelFormat::kRgba16Sint: + case core::TexelFormat::kR32Sint: + case core::TexelFormat::kRg32Sint: + case core::TexelFormat::kRgba32Sint: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8sint")<< style::Plain(", ") << style::Enum("rg8sint")<< style::Plain(", ") << style::Enum("rgba8sint")<< style::Plain(", ") << style::Enum("r16sint")<< style::Plain(", ") << style::Enum("rg16sint")<< style::Plain(", ") << style::Enum("rgba16sint")<< style::Plain(", ") << style::Enum("r32sint")<< style::Plain(", ") << style::Enum("rg32sint")<< style::Plain(" or ") << style::Enum("rgba32sint"); + } +}; + +/// EnumMatcher for 'match u32_texel_format' +constexpr NumberMatcher kU32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Uint: + case core::TexelFormat::kRg8Uint: + case core::TexelFormat::kR16Uint: + case core::TexelFormat::kRg16Uint: + case core::TexelFormat::kRgba8Uint: + case core::TexelFormat::kRgba16Uint: + case core::TexelFormat::kR32Uint: + case core::TexelFormat::kRg32Uint: + case core::TexelFormat::kRgba32Uint: + case core::TexelFormat::kRgb10A2Uint: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8uint")<< style::Plain(", ") << style::Enum("rg8uint")<< style::Plain(", ") << style::Enum("r16uint")<< style::Plain(", ") << style::Enum("rg16uint")<< style::Plain(", ") << style::Enum("rgba8uint")<< style::Plain(", ") << style::Enum("rgba16uint")<< style::Plain(", ") << style::Enum("r32uint")<< style::Plain(", ") << style::Enum("rg32uint")<< style::Plain(", ") << style::Enum("rgba32uint")<< style::Plain(" or ") << style::Enum("rgb10a2uint"); + } +}; + +/// EnumMatcher for 'match read' +constexpr NumberMatcher kReadMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kRead)) { + return Number(static_cast(core::Access::kRead)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read"); + } +}; + +/// EnumMatcher for 'match write' +constexpr NumberMatcher kWriteMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kWrite)) { + return Number(static_cast(core::Access::kWrite)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("write"); + } +}; + +/// EnumMatcher for 'match read_write' +constexpr NumberMatcher kReadWriteMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kReadWrite)) { + return Number(static_cast(core::Access::kReadWrite)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match readable' +constexpr NumberMatcher kReadableMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::Access::kRead: + case core::Access::kReadWrite: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read")<< style::Plain(" or ") << style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match writable' +constexpr NumberMatcher kWritableMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::Access::kWrite: + case core::Access::kReadWrite: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("write")<< style::Plain(" or ") << style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match function_private_workgroup' +constexpr NumberMatcher kFunctionPrivateWorkgroupMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kFunction: + case core::AddressSpace::kPrivate: + case core::AddressSpace::kWorkgroup: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("function")<< style::Plain(", ") << style::Enum("private")<< style::Plain(" or ") << style::Enum("workgroup"); + } +}; + +/// EnumMatcher for 'match workgroup_or_storage' +constexpr NumberMatcher kWorkgroupOrStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kWorkgroup: + case core::AddressSpace::kStorage: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("workgroup")<< style::Plain(" or ") << style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match uniform_or_storage' +constexpr NumberMatcher kUniformOrStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kUniform: + case core::AddressSpace::kStorage: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("uniform")<< style::Plain(" or ") << style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match storage' +constexpr NumberMatcher kStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::AddressSpace::kStorage)) { + return Number(static_cast(core::AddressSpace::kStorage)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match workgroup' +constexpr NumberMatcher kWorkgroupMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::AddressSpace::kWorkgroup)) { + return Number(static_cast(core::AddressSpace::kWorkgroup)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("workgroup"); + } +}; + +/// Type and number matchers + +/// The template types, types, and type matchers +constexpr TypeMatcher kTypeMatchers[] = { + /* [0] */ TemplateTypeMatcher<0>::matcher, + /* [1] */ TemplateTypeMatcher<1>::matcher, + /* [2] */ TemplateTypeMatcher<2>::matcher, + /* [3] */ TemplateTypeMatcher<3>::matcher, + /* [4] */ TemplateTypeMatcher<4>::matcher, + /* [5] */ TemplateTypeMatcher<5>::matcher, + /* [6] */ kBoolMatcher, + /* [7] */ kI8Matcher, + /* [8] */ kU8Matcher, + /* [9] */ kI32Matcher, + /* [10] */ kU32Matcher, + /* [11] */ kF32Matcher, + /* [12] */ kF16Matcher, + /* [13] */ kVec2Matcher, + /* [14] */ kVec3Matcher, + /* [15] */ kVec4Matcher, + /* [16] */ kMat2X2Matcher, + /* [17] */ kMat2X3Matcher, + /* [18] */ kMat2X4Matcher, + /* [19] */ kMat3X2Matcher, + /* [20] */ kMat3X3Matcher, + /* [21] */ kMat3X4Matcher, + /* [22] */ kMat4X2Matcher, + /* [23] */ kMat4X3Matcher, + /* [24] */ kMat4X4Matcher, + /* [25] */ kVecMatcher, + /* [26] */ kMatMatcher, + /* [27] */ kPtrMatcher, + /* [28] */ kAtomicMatcher, + /* [29] */ kRuntimeArrayMatcher, + /* [30] */ kArrayMatcher, + /* [31] */ kBindingArrayMatcher, + /* [32] */ kSamplerMatcher, + /* [33] */ kSamplerComparisonMatcher, + /* [34] */ kTexture1DMatcher, + /* [35] */ kTexture2DMatcher, + /* [36] */ kTexture2DArrayMatcher, + /* [37] */ kTexture3DMatcher, + /* [38] */ kTextureCubeMatcher, + /* [39] */ kTextureCubeArrayMatcher, + /* [40] */ kTextureMultisampled2DMatcher, + /* [41] */ kTextureDepth2DMatcher, + /* [42] */ kTextureDepth2DArrayMatcher, + /* [43] */ kTextureDepthCubeMatcher, + /* [44] */ kTextureDepthCubeArrayMatcher, + /* [45] */ kTextureDepthMultisampled2DMatcher, + /* [46] */ kTextureStorage1DMatcher, + /* [47] */ kTextureStorage2DMatcher, + /* [48] */ kTextureStorage2DArrayMatcher, + /* [49] */ kTextureStorage3DMatcher, + /* [50] */ kTextureExternalMatcher, + /* [51] */ kTexelBufferMatcher, + /* [52] */ kInputAttachmentMatcher, + /* [53] */ kModfResultMatcher, + /* [54] */ kModfResultVecMatcher, + /* [55] */ kFrexpResultMatcher, + /* [56] */ kFrexpResultVecMatcher, + /* [57] */ kAtomicCompareExchangeResultMatcher, + /* [58] */ kSubgroupMatrixMatcher, + /* [59] */ kUnsizedBufferMatcher, + /* [60] */ kBufferMatcher, + /* [61] */ kScalarMatcher, + /* [62] */ kScalarNoF32Matcher, + /* [63] */ kScalarNoF16Matcher, + /* [64] */ kScalarNoI32Matcher, + /* [65] */ kScalarNoU32Matcher, + /* [66] */ kScalarNoBoolMatcher, + /* [67] */ kFiu32F16Matcher, + /* [68] */ kFiu32Matcher, + /* [69] */ kFi32F16Matcher, + /* [70] */ kFi32Matcher, + /* [71] */ kF32F16Matcher, + /* [72] */ kIu32Matcher, + /* [73] */ kIu32Iu8Matcher, + /* [74] */ kIu8Matcher, + /* [75] */ kSubgroupMatrixElementsMatcher, +}; + +/// The template numbers, and number matchers +constexpr NumberMatcher kNumberMatchers[] = { + /* [0] */ TemplateNumberMatcher<0>::matcher, + /* [1] */ TemplateNumberMatcher<1>::matcher, + /* [2] */ TemplateNumberMatcher<2>::matcher, + /* [3] */ TemplateNumberMatcher<3>::matcher, + /* [4] */ TemplateNumberMatcher<4>::matcher, + /* [5] */ TemplateNumberMatcher<5>::matcher, + /* [6] */ kSubgroupMatrixKindLeftMatcher, + /* [7] */ kSubgroupMatrixKindRightMatcher, + /* [8] */ kSubgroupMatrixKindResultMatcher, + /* [9] */ kF32TexelFormatMatcher, + /* [10] */ kI32TexelFormatMatcher, + /* [11] */ kU32TexelFormatMatcher, + /* [12] */ kReadMatcher, + /* [13] */ kWriteMatcher, + /* [14] */ kReadWriteMatcher, + /* [15] */ kReadableMatcher, + /* [16] */ kWritableMatcher, + /* [17] */ kFunctionPrivateWorkgroupMatcher, + /* [18] */ kWorkgroupOrStorageMatcher, + /* [19] */ kUniformOrStorageMatcher, + /* [20] */ kStorageMatcher, + /* [21] */ kWorkgroupMatcher, +}; + +constexpr MatcherIndex kMatcherIndices[] = { + /* [0] */ MatcherIndex(27), + /* [1] */ MatcherIndex(18), + /* [2] */ MatcherIndex(30), + /* [3] */ MatcherIndex(2), + /* [4] */ MatcherIndex(5), + /* [5] */ MatcherIndex(15), + /* [6] */ MatcherIndex(11), + /* [7] */ MatcherIndex(27), + /* [8] */ MatcherIndex(18), + /* [9] */ MatcherIndex(30), + /* [10] */ MatcherIndex(9), + /* [11] */ MatcherIndex(5), + /* [12] */ MatcherIndex(15), + /* [13] */ MatcherIndex(9), + /* [14] */ MatcherIndex(27), + /* [15] */ MatcherIndex(18), + /* [16] */ MatcherIndex(30), + /* [17] */ MatcherIndex(10), + /* [18] */ MatcherIndex(5), + /* [19] */ MatcherIndex(15), + /* [20] */ MatcherIndex(10), + /* [21] */ MatcherIndex(27), + /* [22] */ MatcherIndex(18), + /* [23] */ MatcherIndex(30), + /* [24] */ MatcherIndex(1), + /* [25] */ MatcherIndex(4), + /* [26] */ MatcherIndex(16), + /* [27] */ MatcherIndex(0), + /* [28] */ MatcherIndex(27), + /* [29] */ MatcherIndex(18), + /* [30] */ MatcherIndex(30), + /* [31] */ MatcherIndex(9), + /* [32] */ MatcherIndex(4), + /* [33] */ MatcherIndex(16), + /* [34] */ MatcherIndex(11), + /* [35] */ MatcherIndex(27), + /* [36] */ MatcherIndex(18), + /* [37] */ MatcherIndex(30), + /* [38] */ MatcherIndex(10), + /* [39] */ MatcherIndex(4), + /* [40] */ MatcherIndex(16), + /* [41] */ MatcherIndex(12), + /* [42] */ MatcherIndex(27), + /* [43] */ MatcherIndex(20), + /* [44] */ MatcherIndex(29), + /* [45] */ MatcherIndex(0), + /* [46] */ MatcherIndex(1), + /* [47] */ MatcherIndex(27), + /* [48] */ MatcherIndex(1), + /* [49] */ MatcherIndex(28), + /* [50] */ MatcherIndex(0), + /* [51] */ MatcherIndex(14), + /* [52] */ MatcherIndex(0), + /* [53] */ MatcherIndex(58), + /* [54] */ MatcherIndex(1), + /* [55] */ MatcherIndex(2), + /* [56] */ MatcherIndex(3), + /* [57] */ MatcherIndex(4), + /* [58] */ MatcherIndex(27), + /* [59] */ MatcherIndex(20), + /* [60] */ MatcherIndex(29), + /* [61] */ MatcherIndex(2), + /* [62] */ MatcherIndex(15), + /* [63] */ MatcherIndex(0), + /* [64] */ MatcherIndex(27), + /* [65] */ MatcherIndex(20), + /* [66] */ MatcherIndex(29), + /* [67] */ MatcherIndex(9), + /* [68] */ MatcherIndex(15), + /* [69] */ MatcherIndex(1), + /* [70] */ MatcherIndex(27), + /* [71] */ MatcherIndex(20), + /* [72] */ MatcherIndex(29), + /* [73] */ MatcherIndex(10), + /* [74] */ MatcherIndex(15), + /* [75] */ MatcherIndex(27), + /* [76] */ MatcherIndex(20), + /* [77] */ MatcherIndex(29), + /* [78] */ MatcherIndex(1), + /* [79] */ MatcherIndex(16), + /* [80] */ MatcherIndex(58), + /* [81] */ MatcherIndex(0), + /* [82] */ MatcherIndex(1), + /* [83] */ MatcherIndex(2), + /* [84] */ MatcherIndex(3), + /* [85] */ MatcherIndex(27), + /* [86] */ MatcherIndex(20), + /* [87] */ MatcherIndex(29), + /* [88] */ MatcherIndex(9), + /* [89] */ MatcherIndex(16), + /* [90] */ MatcherIndex(27), + /* [91] */ MatcherIndex(20), + /* [92] */ MatcherIndex(29), + /* [93] */ MatcherIndex(10), + /* [94] */ MatcherIndex(16), + /* [95] */ MatcherIndex(58), + /* [96] */ MatcherIndex(8), + /* [97] */ MatcherIndex(0), + /* [98] */ MatcherIndex(2), + /* [99] */ MatcherIndex(3), + /* [100] */ MatcherIndex(58), + /* [101] */ MatcherIndex(6), + /* [102] */ MatcherIndex(1), + /* [103] */ MatcherIndex(4), + /* [104] */ MatcherIndex(3), + /* [105] */ MatcherIndex(58), + /* [106] */ MatcherIndex(7), + /* [107] */ MatcherIndex(1), + /* [108] */ MatcherIndex(2), + /* [109] */ MatcherIndex(4), + /* [110] */ MatcherIndex(58), + /* [111] */ MatcherIndex(8), + /* [112] */ MatcherIndex(1), + /* [113] */ MatcherIndex(2), + /* [114] */ MatcherIndex(3), + /* [115] */ MatcherIndex(58), + /* [116] */ MatcherIndex(6), + /* [117] */ MatcherIndex(0), + /* [118] */ MatcherIndex(4), + /* [119] */ MatcherIndex(3), + /* [120] */ MatcherIndex(58), + /* [121] */ MatcherIndex(7), + /* [122] */ MatcherIndex(0), + /* [123] */ MatcherIndex(2), + /* [124] */ MatcherIndex(4), + /* [125] */ MatcherIndex(58), + /* [126] */ MatcherIndex(0), + /* [127] */ MatcherIndex(7), + /* [128] */ MatcherIndex(1), + /* [129] */ MatcherIndex(2), + /* [130] */ MatcherIndex(58), + /* [131] */ MatcherIndex(0), + /* [132] */ MatcherIndex(8), + /* [133] */ MatcherIndex(1), + /* [134] */ MatcherIndex(2), + /* [135] */ MatcherIndex(27), + /* [136] */ MatcherIndex(2), + /* [137] */ MatcherIndex(60), + /* [138] */ MatcherIndex(4), + /* [139] */ MatcherIndex(1), + /* [140] */ MatcherIndex(27), + /* [141] */ MatcherIndex(1), + /* [142] */ MatcherIndex(60), + /* [143] */ MatcherIndex(2), + /* [144] */ MatcherIndex(0), + /* [145] */ MatcherIndex(58), + /* [146] */ MatcherIndex(6), + /* [147] */ MatcherIndex(0), + /* [148] */ MatcherIndex(1), + /* [149] */ MatcherIndex(2), + /* [150] */ MatcherIndex(58), + /* [151] */ MatcherIndex(7), + /* [152] */ MatcherIndex(0), + /* [153] */ MatcherIndex(1), + /* [154] */ MatcherIndex(2), + /* [155] */ MatcherIndex(58), + /* [156] */ MatcherIndex(8), + /* [157] */ MatcherIndex(0), + /* [158] */ MatcherIndex(1), + /* [159] */ MatcherIndex(2), + /* [160] */ MatcherIndex(26), + /* [161] */ MatcherIndex(0), + /* [162] */ MatcherIndex(0), + /* [163] */ MatcherIndex(1), + /* [164] */ MatcherIndex(26), + /* [165] */ MatcherIndex(1), + /* [166] */ MatcherIndex(0), + /* [167] */ MatcherIndex(2), + /* [168] */ MatcherIndex(26), + /* [169] */ MatcherIndex(0), + /* [170] */ MatcherIndex(1), + /* [171] */ MatcherIndex(2), + /* [172] */ MatcherIndex(27), + /* [173] */ MatcherIndex(2), + /* [174] */ MatcherIndex(0), + /* [175] */ MatcherIndex(1), + /* [176] */ MatcherIndex(27), + /* [177] */ MatcherIndex(2), + /* [178] */ MatcherIndex(59), + /* [179] */ MatcherIndex(1), + /* [180] */ MatcherIndex(27), + /* [181] */ MatcherIndex(1), + /* [182] */ MatcherIndex(59), + /* [183] */ MatcherIndex(0), + /* [184] */ MatcherIndex(26), + /* [185] */ MatcherIndex(1), + /* [186] */ MatcherIndex(2), + /* [187] */ MatcherIndex(0), + /* [188] */ MatcherIndex(26), + /* [189] */ MatcherIndex(2), + /* [190] */ MatcherIndex(3), + /* [191] */ MatcherIndex(0), + /* [192] */ MatcherIndex(26), + /* [193] */ MatcherIndex(1), + /* [194] */ MatcherIndex(3), + /* [195] */ MatcherIndex(0), + /* [196] */ MatcherIndex(26), + /* [197] */ MatcherIndex(2), + /* [198] */ MatcherIndex(1), + /* [199] */ MatcherIndex(0), + /* [200] */ MatcherIndex(25), + /* [201] */ MatcherIndex(0), + /* [202] */ MatcherIndex(1), + /* [203] */ MatcherIndex(25), + /* [204] */ MatcherIndex(0), + /* [205] */ MatcherIndex(6), + /* [206] */ MatcherIndex(25), + /* [207] */ MatcherIndex(1), + /* [208] */ MatcherIndex(0), + /* [209] */ MatcherIndex(25), + /* [210] */ MatcherIndex(0), + /* [211] */ MatcherIndex(11), + /* [212] */ MatcherIndex(56), + /* [213] */ MatcherIndex(0), + /* [214] */ MatcherIndex(1), + /* [215] */ MatcherIndex(25), + /* [216] */ MatcherIndex(0), + /* [217] */ MatcherIndex(2), + /* [218] */ MatcherIndex(54), + /* [219] */ MatcherIndex(0), + /* [220] */ MatcherIndex(1), + /* [221] */ MatcherIndex(46), + /* [222] */ MatcherIndex(0), + /* [223] */ MatcherIndex(1), + /* [224] */ MatcherIndex(47), + /* [225] */ MatcherIndex(0), + /* [226] */ MatcherIndex(1), + /* [227] */ MatcherIndex(48), + /* [228] */ MatcherIndex(0), + /* [229] */ MatcherIndex(1), + /* [230] */ MatcherIndex(49), + /* [231] */ MatcherIndex(0), + /* [232] */ MatcherIndex(1), + /* [233] */ MatcherIndex(51), + /* [234] */ MatcherIndex(0), + /* [235] */ MatcherIndex(1), + /* [236] */ MatcherIndex(46), + /* [237] */ MatcherIndex(9), + /* [238] */ MatcherIndex(16), + /* [239] */ MatcherIndex(47), + /* [240] */ MatcherIndex(9), + /* [241] */ MatcherIndex(16), + /* [242] */ MatcherIndex(48), + /* [243] */ MatcherIndex(9), + /* [244] */ MatcherIndex(16), + /* [245] */ MatcherIndex(49), + /* [246] */ MatcherIndex(9), + /* [247] */ MatcherIndex(16), + /* [248] */ MatcherIndex(51), + /* [249] */ MatcherIndex(9), + /* [250] */ MatcherIndex(14), + /* [251] */ MatcherIndex(10), + /* [252] */ MatcherIndex(46), + /* [253] */ MatcherIndex(10), + /* [254] */ MatcherIndex(16), + /* [255] */ MatcherIndex(47), + /* [256] */ MatcherIndex(10), + /* [257] */ MatcherIndex(16), + /* [258] */ MatcherIndex(48), + /* [259] */ MatcherIndex(10), + /* [260] */ MatcherIndex(16), + /* [261] */ MatcherIndex(49), + /* [262] */ MatcherIndex(10), + /* [263] */ MatcherIndex(16), + /* [264] */ MatcherIndex(51), + /* [265] */ MatcherIndex(10), + /* [266] */ MatcherIndex(14), + /* [267] */ MatcherIndex(11), + /* [268] */ MatcherIndex(46), + /* [269] */ MatcherIndex(11), + /* [270] */ MatcherIndex(16), + /* [271] */ MatcherIndex(47), + /* [272] */ MatcherIndex(11), + /* [273] */ MatcherIndex(16), + /* [274] */ MatcherIndex(48), + /* [275] */ MatcherIndex(11), + /* [276] */ MatcherIndex(16), + /* [277] */ MatcherIndex(49), + /* [278] */ MatcherIndex(11), + /* [279] */ MatcherIndex(16), + /* [280] */ MatcherIndex(51), + /* [281] */ MatcherIndex(11), + /* [282] */ MatcherIndex(14), + /* [283] */ MatcherIndex(9), + /* [284] */ MatcherIndex(46), + /* [285] */ MatcherIndex(9), + /* [286] */ MatcherIndex(15), + /* [287] */ MatcherIndex(46), + /* [288] */ MatcherIndex(10), + /* [289] */ MatcherIndex(15), + /* [290] */ MatcherIndex(46), + /* [291] */ MatcherIndex(11), + /* [292] */ MatcherIndex(15), + /* [293] */ MatcherIndex(47), + /* [294] */ MatcherIndex(9), + /* [295] */ MatcherIndex(15), + /* [296] */ MatcherIndex(47), + /* [297] */ MatcherIndex(10), + /* [298] */ MatcherIndex(15), + /* [299] */ MatcherIndex(47), + /* [300] */ MatcherIndex(11), + /* [301] */ MatcherIndex(15), + /* [302] */ MatcherIndex(48), + /* [303] */ MatcherIndex(9), + /* [304] */ MatcherIndex(15), + /* [305] */ MatcherIndex(48), + /* [306] */ MatcherIndex(10), + /* [307] */ MatcherIndex(15), + /* [308] */ MatcherIndex(48), + /* [309] */ MatcherIndex(11), + /* [310] */ MatcherIndex(15), + /* [311] */ MatcherIndex(49), + /* [312] */ MatcherIndex(9), + /* [313] */ MatcherIndex(15), + /* [314] */ MatcherIndex(49), + /* [315] */ MatcherIndex(10), + /* [316] */ MatcherIndex(15), + /* [317] */ MatcherIndex(49), + /* [318] */ MatcherIndex(11), + /* [319] */ MatcherIndex(15), + /* [320] */ MatcherIndex(51), + /* [321] */ MatcherIndex(9), + /* [322] */ MatcherIndex(15), + /* [323] */ MatcherIndex(51), + /* [324] */ MatcherIndex(10), + /* [325] */ MatcherIndex(15), + /* [326] */ MatcherIndex(51), + /* [327] */ MatcherIndex(11), + /* [328] */ MatcherIndex(15), + /* [329] */ MatcherIndex(25), + /* [330] */ MatcherIndex(2), + /* [331] */ MatcherIndex(0), + /* [332] */ MatcherIndex(25), + /* [333] */ MatcherIndex(1), + /* [334] */ MatcherIndex(6), + /* [335] */ MatcherIndex(25), + /* [336] */ MatcherIndex(1), + /* [337] */ MatcherIndex(10), + /* [338] */ MatcherIndex(55), + /* [339] */ MatcherIndex(0), + /* [340] */ MatcherIndex(53), + /* [341] */ MatcherIndex(0), + /* [342] */ MatcherIndex(13), + /* [343] */ MatcherIndex(11), + /* [344] */ MatcherIndex(34), + /* [345] */ MatcherIndex(0), + /* [346] */ MatcherIndex(13), + /* [347] */ MatcherIndex(10), + /* [348] */ MatcherIndex(35), + /* [349] */ MatcherIndex(0), + /* [350] */ MatcherIndex(36), + /* [351] */ MatcherIndex(0), + /* [352] */ MatcherIndex(37), + /* [353] */ MatcherIndex(0), + /* [354] */ MatcherIndex(38), + /* [355] */ MatcherIndex(0), + /* [356] */ MatcherIndex(39), + /* [357] */ MatcherIndex(0), + /* [358] */ MatcherIndex(40), + /* [359] */ MatcherIndex(0), + /* [360] */ MatcherIndex(13), + /* [361] */ MatcherIndex(9), + /* [362] */ MatcherIndex(34), + /* [363] */ MatcherIndex(11), + /* [364] */ MatcherIndex(35), + /* [365] */ MatcherIndex(11), + /* [366] */ MatcherIndex(36), + /* [367] */ MatcherIndex(11), + /* [368] */ MatcherIndex(37), + /* [369] */ MatcherIndex(11), + /* [370] */ MatcherIndex(38), + /* [371] */ MatcherIndex(11), + /* [372] */ MatcherIndex(39), + /* [373] */ MatcherIndex(11), + /* [374] */ MatcherIndex(13), + /* [375] */ MatcherIndex(0), + /* [376] */ MatcherIndex(13), + /* [377] */ MatcherIndex(1), + /* [378] */ MatcherIndex(14), + /* [379] */ MatcherIndex(1), + /* [380] */ MatcherIndex(52), + /* [381] */ MatcherIndex(0), + /* [382] */ MatcherIndex(57), + /* [383] */ MatcherIndex(0), + /* [384] */ MatcherIndex(34), + /* [385] */ MatcherIndex(1), + /* [386] */ MatcherIndex(35), + /* [387] */ MatcherIndex(1), + /* [388] */ MatcherIndex(36), + /* [389] */ MatcherIndex(1), + /* [390] */ MatcherIndex(37), + /* [391] */ MatcherIndex(1), + /* [392] */ MatcherIndex(38), + /* [393] */ MatcherIndex(1), + /* [394] */ MatcherIndex(39), + /* [395] */ MatcherIndex(1), + /* [396] */ MatcherIndex(40), + /* [397] */ MatcherIndex(1), + /* [398] */ MatcherIndex(17), + /* [399] */ MatcherIndex(0), + /* [400] */ MatcherIndex(17), + /* [401] */ MatcherIndex(11), + /* [402] */ MatcherIndex(17), + /* [403] */ MatcherIndex(12), + /* [404] */ MatcherIndex(18), + /* [405] */ MatcherIndex(0), + /* [406] */ MatcherIndex(18), + /* [407] */ MatcherIndex(11), + /* [408] */ MatcherIndex(18), + /* [409] */ MatcherIndex(12), + /* [410] */ MatcherIndex(19), + /* [411] */ MatcherIndex(0), + /* [412] */ MatcherIndex(19), + /* [413] */ MatcherIndex(11), + /* [414] */ MatcherIndex(19), + /* [415] */ MatcherIndex(12), + /* [416] */ MatcherIndex(20), + /* [417] */ MatcherIndex(0), + /* [418] */ MatcherIndex(20), + /* [419] */ MatcherIndex(11), + /* [420] */ MatcherIndex(20), + /* [421] */ MatcherIndex(12), + /* [422] */ MatcherIndex(21), + /* [423] */ MatcherIndex(0), + /* [424] */ MatcherIndex(21), + /* [425] */ MatcherIndex(11), + /* [426] */ MatcherIndex(21), + /* [427] */ MatcherIndex(12), + /* [428] */ MatcherIndex(22), + /* [429] */ MatcherIndex(0), + /* [430] */ MatcherIndex(22), + /* [431] */ MatcherIndex(11), + /* [432] */ MatcherIndex(22), + /* [433] */ MatcherIndex(12), + /* [434] */ MatcherIndex(23), + /* [435] */ MatcherIndex(0), + /* [436] */ MatcherIndex(23), + /* [437] */ MatcherIndex(11), + /* [438] */ MatcherIndex(23), + /* [439] */ MatcherIndex(12), + /* [440] */ MatcherIndex(24), + /* [441] */ MatcherIndex(0), + /* [442] */ MatcherIndex(24), + /* [443] */ MatcherIndex(11), + /* [444] */ MatcherIndex(24), + /* [445] */ MatcherIndex(12), + /* [446] */ MatcherIndex(67), + /* [447] */ MatcherIndex(71), + /* [448] */ MatcherIndex(72), + /* [449] */ MatcherIndex(61), + /* [450] */ MatcherIndex(69), + /* [451] */ MatcherIndex(68), + /* [452] */ MatcherIndex(41), + /* [453] */ MatcherIndex(42), + /* [454] */ MatcherIndex(43), + /* [455] */ MatcherIndex(44), + /* [456] */ MatcherIndex(45), + /* [457] */ MatcherIndex(50), + /* [458] */ MatcherIndex(32), + /* [459] */ MatcherIndex(33), + /* [460] */ MatcherIndex(73), + /* [461] */ MatcherIndex(74), + /* [462] */ MatcherIndex(64), + /* [463] */ MatcherIndex(65), + /* [464] */ MatcherIndex(62), + /* [465] */ MatcherIndex(63), + /* [466] */ MatcherIndex(66), + /* [467] */ MatcherIndex(75), +}; + +static_assert(MatcherIndicesIndex::CanIndex(kMatcherIndices), + "MatcherIndicesIndex is not large enough to index kMatcherIndices"); + +constexpr ParameterInfo kParameters[] = { + { + /* [0] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(47), + }, + { + /* [1] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [2] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [3] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [4] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [5] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [6] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [7] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [8] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [9] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [10] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [11] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [12] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [13] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [14] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [15] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [16] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [17] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [18] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [19] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(366), + }, + { + /* [20] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [21] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [22] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [23] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [24] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [25] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [26] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [27] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(350), + }, + { + /* [28] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [29] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [30] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [31] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [32] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(453), + }, + { + /* [33] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(459), + }, + { + /* [34] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [35] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [36] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [37] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [38] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(366), + }, + { + /* [39] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [40] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [41] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [42] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [43] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [44] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(364), + }, + { + /* [45] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [46] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [47] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [48] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [49] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [50] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(368), + }, + { + /* [51] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [52] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [53] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [54] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [55] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(282), + }, + { + /* [56] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(372), + }, + { + /* [57] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [58] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [59] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [60] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [61] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [62] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(366), + }, + { + /* [63] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [64] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [65] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [66] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [67] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [68] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(453), + }, + { + /* [69] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [70] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [71] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [72] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [73] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [74] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [75] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(348), + }, + { + /* [76] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [77] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [78] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [79] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [80] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(356), + }, + { + /* [81] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [82] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [83] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [84] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(453), + }, + { + /* [85] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [86] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [87] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [88] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [89] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(452), + }, + { + /* [90] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(459), + }, + { + /* [91] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [92] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [93] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [94] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(455), + }, + { + /* [95] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(459), + }, + { + /* [96] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [97] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [98] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [99] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(366), + }, + { + /* [100] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [101] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [102] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [103] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [104] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(364), + }, + { + /* [105] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [106] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [107] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [108] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [109] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(368), + }, + { + /* [110] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [111] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [112] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [113] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(282), + }, + { + /* [114] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(372), + }, + { + /* [115] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [116] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [117] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [118] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [119] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(370), + }, + { + /* [120] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [121] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [122] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [123] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [124] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(364), + }, + { + /* [125] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [126] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [127] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [128] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [129] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(368), + }, + { + /* [130] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [131] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [132] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [133] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(282), + }, + { + /* [134] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(372), + }, + { + /* [135] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [136] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [137] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [138] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [139] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(452), + }, + { + /* [140] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [141] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [142] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [143] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [144] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(455), + }, + { + /* [145] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [146] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [147] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [148] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [149] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(75), + }, + { + /* [150] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [151] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [152] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [153] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [154] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [155] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [156] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [157] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [158] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [159] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(85), + }, + { + /* [160] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [161] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [162] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [163] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [164] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(90), + }, + { + /* [165] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [166] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [167] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [168] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [169] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(28), + }, + { + /* [170] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [171] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [172] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [173] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [174] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(35), + }, + { + /* [175] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [176] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [177] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [178] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [179] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [180] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [181] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [182] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [183] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [184] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(354), + }, + { + /* [185] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [186] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [187] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(452), + }, + { + /* [188] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [189] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [190] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [191] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(454), + }, + { + /* [192] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(459), + }, + { + /* [193] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [194] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [195] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(364), + }, + { + /* [196] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [197] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [198] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(360), + }, + { + /* [199] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(368), + }, + { + /* [200] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [201] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [202] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(282), + }, + { + /* [203] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(370), + }, + { + /* [204] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [205] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [206] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [207] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(362), + }, + { + /* [208] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [209] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [210] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [211] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(370), + }, + { + /* [212] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [213] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [214] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [215] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(454), + }, + { + /* [216] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [217] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(266), + }, + { + /* [218] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [219] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(242), + }, + { + /* [220] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [221] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [222] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [223] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(258), + }, + { + /* [224] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [225] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [226] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(12), + }, + { + /* [227] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [228] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [229] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [230] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [231] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(350), + }, + { + /* [232] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(376), + }, + { + /* [233] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [234] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(56), + }, + { + /* [235] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(453), + }, + { + /* [236] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [237] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [238] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [239] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(58), + }, + { + /* [240] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [241] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [242] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [243] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(0), + }, + { + /* [244] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [245] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [246] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [247] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [248] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [249] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [250] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [251] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(70), + }, + { + /* [252] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [253] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [254] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [255] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(7), + }, + { + /* [256] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [257] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [258] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [259] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(14), + }, + { + /* [260] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [261] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [262] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [263] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [264] */ + /* usage */ core::ParameterUsage::kY, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [265] */ + /* usage */ core::ParameterUsage::kZ, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [266] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [267] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [268] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [269] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [270] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [271] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [272] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [273] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [274] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [275] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(62), + }, + { + /* [276] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(62), + }, + { + /* [277] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(62), + }, + { + /* [278] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(62), + }, + { + /* [279] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(206), + }, + { + /* [280] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(206), + }, + { + /* [281] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(206), + }, + { + /* [282] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [283] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [284] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [285] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [286] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [287] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [288] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [289] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [290] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(101), + }, + { + /* [291] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [292] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [293] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(203), + }, + { + /* [294] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(203), + }, + { + /* [295] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(457), + }, + { + /* [296] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(458), + }, + { + /* [297] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [298] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(236), + }, + { + /* [299] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [300] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [301] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(239), + }, + { + /* [302] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [303] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [304] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(245), + }, + { + /* [305] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [306] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [307] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(248), + }, + { + /* [308] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [309] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [310] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(252), + }, + { + /* [311] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [312] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(12), + }, + { + /* [313] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(255), + }, + { + /* [314] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [315] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(12), + }, + { + /* [316] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(261), + }, + { + /* [317] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [318] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(12), + }, + { + /* [319] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(264), + }, + { + /* [320] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [321] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(12), + }, + { + /* [322] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(268), + }, + { + /* [323] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [324] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [325] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(271), + }, + { + /* [326] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [327] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [328] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(277), + }, + { + /* [329] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [330] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [331] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(280), + }, + { + /* [332] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [333] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [334] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(344), + }, + { + /* [335] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [336] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [337] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(348), + }, + { + /* [338] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(376), + }, + { + /* [339] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [340] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(352), + }, + { + /* [341] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(378), + }, + { + /* [342] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [343] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(358), + }, + { + /* [344] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(376), + }, + { + /* [345] */ + /* usage */ core::ParameterUsage::kSampleIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [346] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(452), + }, + { + /* [347] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [348] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [349] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(456), + }, + { + /* [350] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [351] */ + /* usage */ core::ParameterUsage::kSampleIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [352] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(302), + }, + { + /* [353] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [354] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [355] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(305), + }, + { + /* [356] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [357] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [358] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(308), + }, + { + /* [359] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [360] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [361] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(115), + }, + { + /* [362] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(120), + }, + { + /* [363] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(110), + }, + { + /* [364] */ + /* usage */ core::ParameterUsage::kXy, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [365] */ + /* usage */ core::ParameterUsage::kZ, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [366] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [367] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [368] */ + /* usage */ core::ParameterUsage::kYz, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [369] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [370] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [371] */ + /* usage */ core::ParameterUsage::kY, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [372] */ + /* usage */ core::ParameterUsage::kZw, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [373] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [374] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [375] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [376] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(215), + }, + { + /* [377] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(344), + }, + { + /* [378] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [379] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(348), + }, + { + /* [380] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [381] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(350), + }, + { + /* [382] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [383] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(352), + }, + { + /* [384] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [385] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(354), + }, + { + /* [386] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [387] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(356), + }, + { + /* [388] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [389] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(452), + }, + { + /* [390] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [391] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(453), + }, + { + /* [392] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [393] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(454), + }, + { + /* [394] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [395] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(455), + }, + { + /* [396] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [397] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(457), + }, + { + /* [398] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [399] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(284), + }, + { + /* [400] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [401] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [402] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [403] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(290), + }, + { + /* [404] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [405] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(293), + }, + { + /* [406] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [407] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(296), + }, + { + /* [408] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [409] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(299), + }, + { + /* [410] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [411] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(311), + }, + { + /* [412] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [413] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(314), + }, + { + /* [414] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [415] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [416] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [417] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(320), + }, + { + /* [418] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [419] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(323), + }, + { + /* [420] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [421] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(326), + }, + { + /* [422] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [423] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [424] */ + /* usage */ core::ParameterUsage::kSourceLaneIndex, + /* matcher_indices */ MatcherIndicesIndex(448), + }, + { + /* [425] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [426] */ + /* usage */ core::ParameterUsage::kSourceLaneIndex, + /* matcher_indices */ MatcherIndicesIndex(448), + }, + { + /* [427] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [428] */ + /* usage */ core::ParameterUsage::kMask, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [429] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [430] */ + /* usage */ core::ParameterUsage::kMask, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [431] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [432] */ + /* usage */ core::ParameterUsage::kDelta, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [433] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [434] */ + /* usage */ core::ParameterUsage::kDelta, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [435] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [436] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(448), + }, + { + /* [437] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(200), + }, + { + /* [438] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(448), + }, + { + /* [439] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(100), + }, + { + /* [440] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(105), + }, + { + /* [441] */ + /* usage */ core::ParameterUsage::kM, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [442] */ + /* usage */ core::ParameterUsage::kS, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [443] */ + /* usage */ core::ParameterUsage::kM, + /* matcher_indices */ MatcherIndicesIndex(125), + }, + { + /* [444] */ + /* usage */ core::ParameterUsage::kS, + /* matcher_indices */ MatcherIndicesIndex(10), + }, + { + /* [445] */ + /* usage */ core::ParameterUsage::kM, + /* matcher_indices */ MatcherIndicesIndex(130), + }, + { + /* [446] */ + /* usage */ core::ParameterUsage::kS, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [447] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(176), + }, + { + /* [448] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(56), + }, + { + /* [449] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(135), + }, + { + /* [450] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(56), + }, + { + /* [451] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(206), + }, + { + /* [452] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [453] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(206), + }, + { + /* [454] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(335), + }, + { + /* [455] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [456] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [457] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [458] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [459] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(206), + }, + { + /* [460] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(329), + }, + { + /* [461] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [462] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(192), + }, + { + /* [463] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(196), + }, + { + /* [464] */ + /* usage */ core::ParameterUsage::kXy, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [465] */ + /* usage */ core::ParameterUsage::kZw, + /* matcher_indices */ MatcherIndicesIndex(374), + }, + { + /* [466] */ + /* usage */ core::ParameterUsage::kXyz, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [467] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [468] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [469] */ + /* usage */ core::ParameterUsage::kZyw, + /* matcher_indices */ MatcherIndicesIndex(51), + }, + { + /* [470] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [471] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(160), + }, + { + /* [472] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [473] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(209), + }, + { + /* [474] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(342), + }, + { + /* [475] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [476] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(12), + }, + { + /* [477] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [478] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(168), + }, + { + /* [479] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(221), + }, + { + /* [480] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(224), + }, + { + /* [481] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(227), + }, + { + /* [482] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(230), + }, + { + /* [483] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(233), + }, + { + /* [484] */ + /* usage */ core::ParameterUsage::kInputAttachment, + /* matcher_indices */ MatcherIndicesIndex(380), + }, + { + /* [485] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(180), + }, + { + /* [486] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(140), + }, + { + /* [487] */ + /* usage */ core::ParameterUsage::kIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [488] */ + /* usage */ core::ParameterUsage::kIndex, + /* matcher_indices */ MatcherIndicesIndex(24), + }, + { + /* [489] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(10), + }, + { + /* [490] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [491] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(376), + }, + { + /* [492] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(378), + }, + { + /* [493] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(68), + }, + { + /* [494] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [495] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(33), + }, + { + /* [496] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [497] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(398), + }, + { + /* [498] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(400), + }, + { + /* [499] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [500] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(404), + }, + { + /* [501] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(406), + }, + { + /* [502] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [503] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(410), + }, + { + /* [504] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(412), + }, + { + /* [505] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(414), + }, + { + /* [506] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(416), + }, + { + /* [507] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(418), + }, + { + /* [508] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(420), + }, + { + /* [509] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(422), + }, + { + /* [510] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(424), + }, + { + /* [511] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(426), + }, + { + /* [512] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(428), + }, + { + /* [513] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(430), + }, + { + /* [514] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(432), + }, + { + /* [515] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(434), + }, + { + /* [516] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(436), + }, + { + /* [517] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(438), + }, + { + /* [518] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(440), + }, + { + /* [519] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(442), + }, + { + /* [520] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(444), + }, +}; + +static_assert(ParameterIndex::CanIndex(kParameters), + "ParameterIndex is not large enough to index kParameters"); + +constexpr TemplateInfo kTemplates[] = { + { + /* [0] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(53), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [1] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [2] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(446), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [3] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [4] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [5] */ + /* name */ "AC", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [6] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(53), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [7] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [8] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(106), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [9] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [10] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [11] */ + /* name */ "AC", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [12] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(53), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [13] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [14] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(96), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [15] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [16] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [17] */ + /* name */ "AC", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [18] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(447), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [19] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [20] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [21] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [22] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [23] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(446), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [24] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [25] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [26] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [27] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [28] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [29] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [30] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [31] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [32] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [33] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(460), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [34] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(461), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [35] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [36] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [37] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [38] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [39] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [40] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [41] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [42] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [43] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [44] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(447), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [45] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [46] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [47] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [48] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [49] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [50] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [51] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [52] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [53] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(461), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [54] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(460), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [55] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [56] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [57] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [58] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [59] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [60] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [61] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [62] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [63] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [64] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [65] */ + /* name */ "AS", + /* matcher_indices */ MatcherIndicesIndex(410), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [66] */ + /* name */ "O", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [67] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [68] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(447), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [69] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(10), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [70] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [71] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(51), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [72] */ + /* name */ "AS", + /* matcher_indices */ MatcherIndicesIndex(1), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [73] */ + /* name */ "O", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [74] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [75] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(446), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [76] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [77] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [78] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [79] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [80] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [81] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [82] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [83] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(447), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [84] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [85] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [86] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [87] */ + /* name */ "M", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [88] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [89] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(447), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [90] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [91] */ + /* name */ "M", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [92] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [93] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [94] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [95] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [96] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [97] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [98] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [99] */ + /* name */ "AS", + /* matcher_indices */ MatcherIndicesIndex(410), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [100] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [101] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(449), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [102] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [103] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(450), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [104] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [105] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(51), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [106] */ + /* name */ "AS", + /* matcher_indices */ MatcherIndicesIndex(1), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [107] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [108] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(384), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [109] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [110] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [111] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(386), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [112] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [113] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [114] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(388), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [115] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [116] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [117] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(390), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [118] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [119] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [120] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(392), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [121] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [122] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [123] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(394), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [124] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [125] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [126] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(396), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [127] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [128] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [129] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(447), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [130] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [131] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [132] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(467), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [133] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [134] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [135] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(467), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [136] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [137] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [138] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(467), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [139] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [140] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [141] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [142] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [143] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(451), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [144] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [145] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [146] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [147] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(452), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [148] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [149] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(453), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [150] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [151] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(454), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [152] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [153] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(455), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [154] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [155] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(456), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [156] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [157] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(448), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [158] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [159] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [160] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(464), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [161] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [162] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(465), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [163] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(10), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [164] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(462), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [165] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [166] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(463), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [167] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(101), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [168] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(466), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [169] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(462), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [170] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(463), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [171] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(464), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [172] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(465), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [173] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(466), + /* kind */ TemplateInfo::Kind::kType, + }, +}; + +static_assert(TemplateIndex::CanIndex(kTemplates), + "TemplateIndex is not large enough to index kTemplates"); + +constexpr core::constant::Eval::Function kConstEvalFunctions[] = { + /* [0] */ &core::constant::Eval::abs, + /* [1] */ &core::constant::Eval::acos, + /* [2] */ &core::constant::Eval::acosh, + /* [3] */ &core::constant::Eval::all, + /* [4] */ &core::constant::Eval::any, + /* [5] */ &core::constant::Eval::asin, + /* [6] */ &core::constant::Eval::asinh, + /* [7] */ &core::constant::Eval::atan, + /* [8] */ &core::constant::Eval::atan2, + /* [9] */ &core::constant::Eval::atanh, + /* [10] */ &core::constant::Eval::ceil, + /* [11] */ &core::constant::Eval::clamp, + /* [12] */ &core::constant::Eval::cos, + /* [13] */ &core::constant::Eval::cosh, + /* [14] */ &core::constant::Eval::countLeadingZeros, + /* [15] */ &core::constant::Eval::countOneBits, + /* [16] */ &core::constant::Eval::countTrailingZeros, + /* [17] */ &core::constant::Eval::cross, + /* [18] */ &core::constant::Eval::degrees, + /* [19] */ &core::constant::Eval::determinant, + /* [20] */ &core::constant::Eval::distance, + /* [21] */ &core::constant::Eval::dot, + /* [22] */ &core::constant::Eval::dot4I8Packed, + /* [23] */ &core::constant::Eval::dot4U8Packed, + /* [24] */ &core::constant::Eval::exp, + /* [25] */ &core::constant::Eval::exp2, + /* [26] */ &core::constant::Eval::extractBits, + /* [27] */ &core::constant::Eval::faceForward, + /* [28] */ &core::constant::Eval::firstLeadingBit, + /* [29] */ &core::constant::Eval::firstTrailingBit, + /* [30] */ &core::constant::Eval::floor, + /* [31] */ &core::constant::Eval::fma, + /* [32] */ &core::constant::Eval::fract, + /* [33] */ &core::constant::Eval::frexp, + /* [34] */ &core::constant::Eval::insertBits, + /* [35] */ &core::constant::Eval::inverseSqrt, + /* [36] */ &core::constant::Eval::ldexp, + /* [37] */ &core::constant::Eval::length, + /* [38] */ &core::constant::Eval::log, + /* [39] */ &core::constant::Eval::log2, + /* [40] */ &core::constant::Eval::max, + /* [41] */ &core::constant::Eval::min, + /* [42] */ &core::constant::Eval::mix, + /* [43] */ &core::constant::Eval::modf, + /* [44] */ &core::constant::Eval::normalize, + /* [45] */ &core::constant::Eval::pack2x16float, + /* [46] */ &core::constant::Eval::pack2x16snorm, + /* [47] */ &core::constant::Eval::pack2x16unorm, + /* [48] */ &core::constant::Eval::pack4x8snorm, + /* [49] */ &core::constant::Eval::pack4x8unorm, + /* [50] */ &core::constant::Eval::pack4xI8, + /* [51] */ &core::constant::Eval::pack4xU8, + /* [52] */ &core::constant::Eval::pack4xI8Clamp, + /* [53] */ &core::constant::Eval::pack4xU8Clamp, + /* [54] */ &core::constant::Eval::pow, + /* [55] */ &core::constant::Eval::quantizeToF16, + /* [56] */ &core::constant::Eval::radians, + /* [57] */ &core::constant::Eval::reflect, + /* [58] */ &core::constant::Eval::refract, + /* [59] */ &core::constant::Eval::reverseBits, + /* [60] */ &core::constant::Eval::round, + /* [61] */ &core::constant::Eval::saturate, + /* [62] */ &core::constant::Eval::select_bool, + /* [63] */ &core::constant::Eval::select_boolvec, + /* [64] */ &core::constant::Eval::sign, + /* [65] */ &core::constant::Eval::sin, + /* [66] */ &core::constant::Eval::sinh, + /* [67] */ &core::constant::Eval::smoothstep, + /* [68] */ &core::constant::Eval::sqrt, + /* [69] */ &core::constant::Eval::step, + /* [70] */ &core::constant::Eval::tan, + /* [71] */ &core::constant::Eval::tanh, + /* [72] */ &core::constant::Eval::transpose, + /* [73] */ &core::constant::Eval::trunc, + /* [74] */ &core::constant::Eval::unpack2x16float, + /* [75] */ &core::constant::Eval::unpack2x16snorm, + /* [76] */ &core::constant::Eval::unpack2x16unorm, + /* [77] */ &core::constant::Eval::unpack4x8snorm, + /* [78] */ &core::constant::Eval::unpack4x8unorm, + /* [79] */ &core::constant::Eval::unpack4xI8, + /* [80] */ &core::constant::Eval::unpack4xU8, + /* [81] */ &core::constant::Eval::Not, + /* [82] */ &core::constant::Eval::Complement, + /* [83] */ &core::constant::Eval::UnaryMinus, + /* [84] */ &core::constant::Eval::Plus, + /* [85] */ &core::constant::Eval::Minus, + /* [86] */ &core::constant::Eval::Multiply, + /* [87] */ &core::constant::Eval::MultiplyMatVec, + /* [88] */ &core::constant::Eval::MultiplyVecMat, + /* [89] */ &core::constant::Eval::MultiplyMatMat, + /* [90] */ &core::constant::Eval::Divide, + /* [91] */ &core::constant::Eval::Modulo, + /* [92] */ &core::constant::Eval::Xor, + /* [93] */ &core::constant::Eval::And, + /* [94] */ &core::constant::Eval::Or, + /* [95] */ &core::constant::Eval::LogicalAnd, + /* [96] */ &core::constant::Eval::LogicalOr, + /* [97] */ &core::constant::Eval::Equal, + /* [98] */ &core::constant::Eval::NotEqual, + /* [99] */ &core::constant::Eval::LessThan, + /* [100] */ &core::constant::Eval::GreaterThan, + /* [101] */ &core::constant::Eval::LessThanEqual, + /* [102] */ &core::constant::Eval::GreaterThanEqual, + /* [103] */ &core::constant::Eval::ShiftLeft, + /* [104] */ &core::constant::Eval::ShiftRight, + /* [105] */ &core::constant::Eval::Zero, + /* [106] */ &core::constant::Eval::Identity, + /* [107] */ &core::constant::Eval::Conv, + /* [108] */ &core::constant::Eval::VecSplat, + /* [109] */ &core::constant::Eval::VecInitS, + /* [110] */ &core::constant::Eval::VecInitM, + /* [111] */ &core::constant::Eval::MatInitS, + /* [112] */ &core::constant::Eval::MatInitV, +}; + +static_assert(ConstEvalFunctionIndex::CanIndex(kConstEvalFunctions), + "ConstEvalFunctionIndex is not large enough to index kConstEvalFunctions"); + +constexpr OverloadInfo kOverloads[] = { + { + /* [0] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [1] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(143), + /* parameters */ ParameterIndex(377), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [2] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(75), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [3] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(143), + /* parameters */ ParameterIndex(379), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [4] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(27), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [5] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(143), + /* parameters */ ParameterIndex(381), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [6] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(340), + /* return_matcher_indices */ MatcherIndicesIndex(250), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [7] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(143), + /* parameters */ ParameterIndex(383), + /* return_matcher_indices */ MatcherIndicesIndex(250), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [8] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(184), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [9] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(143), + /* parameters */ ParameterIndex(385), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [10] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(80), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [11] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(143), + /* parameters */ ParameterIndex(387), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [12] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(343), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [13] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [14] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(389), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [15] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [16] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(391), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [17] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [18] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(393), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [19] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [20] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(395), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [21] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(349), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [22] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(479), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [23] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(480), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [24] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(481), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [25] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(482), + /* return_matcher_indices */ MatcherIndicesIndex(250), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [26] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(483), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [27] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(295), + /* return_matcher_indices */ MatcherIndicesIndex(346), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [28] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [29] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(337), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [30] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(231), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [31] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(340), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [32] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(95), + /* parameters */ ParameterIndex(343), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [33] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(346), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [34] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(235), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [35] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(349), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [36] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(397), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [37] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(399), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [38] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(401), + /* return_matcher_indices */ MatcherIndicesIndex(12), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [39] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(403), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [40] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(405), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [41] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(407), + /* return_matcher_indices */ MatcherIndicesIndex(12), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [42] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(409), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [43] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(352), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [44] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(355), + /* return_matcher_indices */ MatcherIndicesIndex(12), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [45] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(358), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [46] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(411), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [47] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(413), + /* return_matcher_indices */ MatcherIndicesIndex(12), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [48] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(415), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [49] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(417), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [50] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(419), + /* return_matcher_indices */ MatcherIndicesIndex(12), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [51] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(421), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [52] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(207), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [53] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [54] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(195), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [55] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(19), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [56] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(99), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [57] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(50), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [58] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(199), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [59] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(119), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [60] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(56), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [61] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [62] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(187), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [63] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [64] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(84), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [65] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(215), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [66] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [67] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(207), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [68] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(124), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [69] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(124), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [70] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(62), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [71] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(62), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [72] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(129), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [73] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(129), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [74] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(211), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [75] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(134), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [76] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [77] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [78] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [79] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [80] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(215), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [81] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [82] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [83] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [84] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [85] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [86] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [87] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(310), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [88] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(313), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [89] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(223), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [90] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(316), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [91] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(319), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [92] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(322), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [93] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(325), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [94] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(227), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [95] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(328), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [96] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(331), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [97] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [98] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [99] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [100] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [101] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(364), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [102] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(367), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [103] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(370), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [104] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(464), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [105] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(466), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [106] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [107] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(159), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [108] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(161), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [109] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(163), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [110] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [111] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(167), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [112] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(74), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [113] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(74), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [114] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(26), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [115] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(26), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [116] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(183), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [117] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(79), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [118] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [119] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(187), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [120] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [121] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(84), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [122] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(215), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [123] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [124] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [125] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(111), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [126] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [127] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(117), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [128] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(120), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [129] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(123), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [130] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(126), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [131] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(147), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [132] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(149), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [133] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(151), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [134] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(153), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [135] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(155), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [136] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [137] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(111), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [138] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [139] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(117), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [140] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(120), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [141] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(123), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [142] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(126), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [143] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(147), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [144] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(149), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [145] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(151), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [146] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(153), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [147] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(155), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [148] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [149] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [150] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [151] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [152] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(364), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [153] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(367), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [154] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(159), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [155] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(161), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [156] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(163), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [157] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [158] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(167), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [159] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [160] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(75), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [161] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(27), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [162] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(340), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [163] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(184), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [164] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(80), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [165] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [166] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [167] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [168] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [169] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [170] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [171] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [172] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [173] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(457), + /* return_matcher_indices */ MatcherIndicesIndex(184), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [174] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(456), + /* return_matcher_indices */ MatcherIndicesIndex(184), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [175] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(458), + /* return_matcher_indices */ MatcherIndicesIndex(329), + /* const_eval_fn */ ConstEvalFunctionIndex(87), + }, + { + /* [176] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(460), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [177] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(83), + /* parameters */ ParameterIndex(462), + /* return_matcher_indices */ MatcherIndicesIndex(188), + /* const_eval_fn */ ConstEvalFunctionIndex(89), + }, + { + /* [178] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [179] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [180] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [181] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [182] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(159), + /* parameters */ ParameterIndex(491), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [183] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(161), + /* parameters */ ParameterIndex(491), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [184] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(163), + /* parameters */ ParameterIndex(491), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [185] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(491), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [186] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(167), + /* parameters */ ParameterIndex(491), + /* return_matcher_indices */ MatcherIndicesIndex(374), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [187] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(104), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [188] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(104), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [189] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(38), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [190] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(38), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [191] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(109), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [192] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(109), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [193] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(203), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [194] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(114), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [195] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [196] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [197] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(19), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [198] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 7, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(19), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [199] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(50), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [200] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(50), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [201] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(119), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [202] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(56), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [203] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [204] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [205] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [206] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [207] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [208] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [209] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [210] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [211] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [212] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [213] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [214] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [215] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [216] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [217] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [218] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [219] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [220] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [221] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(0), + /* parameters */ ParameterIndex(239), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [222] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(0), + /* parameters */ ParameterIndex(243), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [223] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(6), + /* parameters */ ParameterIndex(247), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [224] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(251), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [225] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(6), + /* parameters */ ParameterIndex(255), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [226] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(259), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [227] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(1), + /* parameters */ ParameterIndex(149), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [228] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(1), + /* parameters */ ParameterIndex(154), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [229] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(159), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [230] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(13), + /* parameters */ ParameterIndex(164), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [231] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(169), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [232] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(13), + /* parameters */ ParameterIndex(174), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [233] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [234] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(494), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [235] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [236] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [237] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(495), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [238] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(496), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [239] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(398), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [240] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(497), + /* return_matcher_indices */ MatcherIndicesIndex(398), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [241] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(398), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [242] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(398), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [243] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(498), + /* return_matcher_indices */ MatcherIndicesIndex(398), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [244] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(499), + /* return_matcher_indices */ MatcherIndicesIndex(398), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [245] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(404), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [246] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(500), + /* return_matcher_indices */ MatcherIndicesIndex(404), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [247] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 8, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(404), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [248] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(404), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [249] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(501), + /* return_matcher_indices */ MatcherIndicesIndex(404), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [250] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(502), + /* return_matcher_indices */ MatcherIndicesIndex(404), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [251] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(410), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [252] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(503), + /* return_matcher_indices */ MatcherIndicesIndex(410), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [253] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(410), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [254] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(410), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [255] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(504), + /* return_matcher_indices */ MatcherIndicesIndex(410), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [256] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(505), + /* return_matcher_indices */ MatcherIndicesIndex(410), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [257] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(416), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [258] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(506), + /* return_matcher_indices */ MatcherIndicesIndex(416), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [259] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 9, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(416), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [260] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(416), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [261] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(507), + /* return_matcher_indices */ MatcherIndicesIndex(416), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [262] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(508), + /* return_matcher_indices */ MatcherIndicesIndex(416), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [263] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(422), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [264] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(509), + /* return_matcher_indices */ MatcherIndicesIndex(422), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [265] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 12, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(422), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [266] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(422), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [267] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(510), + /* return_matcher_indices */ MatcherIndicesIndex(422), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [268] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(511), + /* return_matcher_indices */ MatcherIndicesIndex(422), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [269] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(428), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [270] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(512), + /* return_matcher_indices */ MatcherIndicesIndex(428), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [271] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 8, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(428), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [272] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(428), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [273] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(513), + /* return_matcher_indices */ MatcherIndicesIndex(428), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [274] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(514), + /* return_matcher_indices */ MatcherIndicesIndex(428), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [275] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(434), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [276] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(515), + /* return_matcher_indices */ MatcherIndicesIndex(434), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [277] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 12, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(434), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [278] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(434), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [279] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(516), + /* return_matcher_indices */ MatcherIndicesIndex(434), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [280] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(517), + /* return_matcher_indices */ MatcherIndicesIndex(434), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [281] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(440), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [282] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(518), + /* return_matcher_indices */ MatcherIndicesIndex(440), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [283] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 16, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(440), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [284] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(440), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [285] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(519), + /* return_matcher_indices */ MatcherIndicesIndex(440), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [286] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(520), + /* return_matcher_indices */ MatcherIndicesIndex(440), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [287] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(27), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [288] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(80), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [289] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [290] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [291] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(481), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [292] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [293] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [294] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [295] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [296] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(455), + /* return_matcher_indices */ MatcherIndicesIndex(184), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [297] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [298] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [299] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [300] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [301] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(455), + /* return_matcher_indices */ MatcherIndicesIndex(184), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [302] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(18), + /* parameters */ ParameterIndex(439), + /* return_matcher_indices */ MatcherIndicesIndex(95), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [303] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(26), + /* parameters */ ParameterIndex(439), + /* return_matcher_indices */ MatcherIndicesIndex(95), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [304] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(439), + /* return_matcher_indices */ MatcherIndicesIndex(95), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [305] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(38), + /* parameters */ ParameterIndex(439), + /* return_matcher_indices */ MatcherIndicesIndex(95), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [306] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(43), + /* parameters */ ParameterIndex(361), + /* return_matcher_indices */ MatcherIndicesIndex(110), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [307] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(48), + /* parameters */ ParameterIndex(361), + /* return_matcher_indices */ MatcherIndicesIndex(110), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [308] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(53), + /* parameters */ ParameterIndex(361), + /* return_matcher_indices */ MatcherIndicesIndex(110), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [309] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(58), + /* parameters */ ParameterIndex(361), + /* return_matcher_indices */ MatcherIndicesIndex(110), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [310] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(447), + /* return_matcher_indices */ MatcherIndicesIndex(172), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [311] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(172), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [312] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(70), + /* parameters */ ParameterIndex(447), + /* return_matcher_indices */ MatcherIndicesIndex(172), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [313] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(70), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(172), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [314] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(64), + /* parameters */ ParameterIndex(485), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [315] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(98), + /* parameters */ ParameterIndex(486), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [316] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(71), + /* parameters */ ParameterIndex(485), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [317] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(105), + /* parameters */ ParameterIndex(486), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [318] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(90), + }, + { + /* [319] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(90), + }, + { + /* [320] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(90), + }, + { + /* [321] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(90), + }, + { + /* [322] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(91), + }, + { + /* [323] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(91), + }, + { + /* [324] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(91), + }, + { + /* [325] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(91), + }, + { + /* [326] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [327] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(203), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [328] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [329] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [330] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(94), + }, + { + /* [331] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(203), + /* const_eval_fn */ ConstEvalFunctionIndex(94), + }, + { + /* [332] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(94), + }, + { + /* [333] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(94), + }, + { + /* [334] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(42), + }, + { + /* [335] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(42), + }, + { + /* [336] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(285), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(42), + }, + { + /* [337] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(288), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(62), + }, + { + /* [338] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(280), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(62), + }, + { + /* [339] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(291), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(63), + }, + { + /* [340] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(22), + /* parameters */ ParameterIndex(441), + /* return_matcher_indices */ MatcherIndicesIndex(80), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [341] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(30), + /* parameters */ ParameterIndex(443), + /* return_matcher_indices */ MatcherIndicesIndex(125), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [342] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(30), + /* parameters */ ParameterIndex(445), + /* return_matcher_indices */ MatcherIndicesIndex(130), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [343] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [344] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(489), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [345] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [346] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [347] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [348] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(170), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [349] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [350] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(472), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [351] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(171), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [352] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [353] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(490), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [354] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [355] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [356] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [357] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(173), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [358] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(0), + }, + { + /* [359] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(0), + }, + { + /* [360] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(1), + }, + { + /* [361] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(1), + }, + { + /* [362] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(2), + }, + { + /* [363] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(2), + }, + { + /* [364] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(3), + }, + { + /* [365] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(3), + }, + { + /* [366] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(4), + }, + { + /* [367] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(4), + }, + { + /* [368] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(5), + }, + { + /* [369] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(5), + }, + { + /* [370] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(6), + }, + { + /* [371] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(6), + }, + { + /* [372] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(7), + }, + { + /* [373] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(7), + }, + { + /* [374] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(8), + }, + { + /* [375] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(8), + }, + { + /* [376] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(9), + }, + { + /* [377] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(9), + }, + { + /* [378] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [379] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [380] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(11), + }, + { + /* [381] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(11), + }, + { + /* [382] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(12), + }, + { + /* [383] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(12), + }, + { + /* [384] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(13), + }, + { + /* [385] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(13), + }, + { + /* [386] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(14), + }, + { + /* [387] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(14), + }, + { + /* [388] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(15), + }, + { + /* [389] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(15), + }, + { + /* [390] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(16), + }, + { + /* [391] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(16), + }, + { + /* [392] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(18), + }, + { + /* [393] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(18), + }, + { + /* [394] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(20), + }, + { + /* [395] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(24), + /* const_eval_fn */ ConstEvalFunctionIndex(20), + }, + { + /* [396] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(472), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [397] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(209), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [398] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(24), + }, + { + /* [399] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(24), + }, + { + /* [400] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(25), + }, + { + /* [401] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(25), + }, + { + /* [402] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(16), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(26), + }, + { + /* [403] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(180), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(26), + }, + { + /* [404] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(28), + }, + { + /* [405] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(28), + }, + { + /* [406] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(29), + }, + { + /* [407] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(29), + }, + { + /* [408] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(30), + }, + { + /* [409] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(30), + }, + { + /* [410] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(31), + }, + { + /* [411] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(31), + }, + { + /* [412] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(32), + }, + { + /* [413] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(32), + }, + { + /* [414] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(338), + /* const_eval_fn */ ConstEvalFunctionIndex(33), + }, + { + /* [415] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(212), + /* const_eval_fn */ ConstEvalFunctionIndex(33), + }, + { + /* [416] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(15), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(34), + }, + { + /* [417] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(34), + }, + { + /* [418] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(35), + }, + { + /* [419] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(35), + }, + { + /* [420] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(373), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(36), + }, + { + /* [421] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(375), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(36), + }, + { + /* [422] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(37), + }, + { + /* [423] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(24), + /* const_eval_fn */ ConstEvalFunctionIndex(37), + }, + { + /* [424] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(38), + }, + { + /* [425] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(38), + }, + { + /* [426] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(39), + }, + { + /* [427] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(39), + }, + { + /* [428] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(40), + }, + { + /* [429] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(40), + }, + { + /* [430] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(41), + }, + { + /* [431] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(41), + }, + { + /* [432] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(340), + /* const_eval_fn */ ConstEvalFunctionIndex(43), + }, + { + /* [433] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(218), + /* const_eval_fn */ ConstEvalFunctionIndex(43), + }, + { + /* [434] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(54), + }, + { + /* [435] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(54), + }, + { + /* [436] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(472), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(55), + }, + { + /* [437] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(209), + /* const_eval_fn */ ConstEvalFunctionIndex(55), + }, + { + /* [438] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(56), + }, + { + /* [439] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(56), + }, + { + /* [440] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(59), + }, + { + /* [441] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(59), + }, + { + /* [442] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(60), + }, + { + /* [443] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(60), + }, + { + /* [444] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(61), + }, + { + /* [445] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(61), + }, + { + /* [446] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(103), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(64), + }, + { + /* [447] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(102), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(64), + }, + { + /* [448] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(65), + }, + { + /* [449] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(65), + }, + { + /* [450] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(66), + }, + { + /* [451] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(66), + }, + { + /* [452] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(67), + }, + { + /* [453] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(67), + }, + { + /* [454] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(68), + }, + { + /* [455] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(68), + }, + { + /* [456] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(69), + }, + { + /* [457] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(69), + }, + { + /* [458] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(70), + }, + { + /* [459] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(70), + }, + { + /* [460] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(71), + }, + { + /* [461] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(71), + }, + { + /* [462] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(73), + }, + { + /* [463] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(73), + }, + { + /* [464] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(343), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [465] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(349), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [466] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [467] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(295), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [468] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [469] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(425), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [470] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [471] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(425), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [472] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(427), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [473] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(429), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [474] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(431), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [475] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(433), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [476] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [477] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(425), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [478] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(435), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [479] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(437), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [480] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(435), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [481] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(437), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [482] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [483] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [484] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(81), + }, + { + /* [485] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(203), + /* const_eval_fn */ ConstEvalFunctionIndex(81), + }, + { + /* [486] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [487] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [488] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(103), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(83), + }, + { + /* [489] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(103), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(83), + }, + { + /* [490] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(92), + }, + { + /* [491] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(92), + }, + { + /* [492] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(97), + }, + { + /* [493] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(332), + /* const_eval_fn */ ConstEvalFunctionIndex(97), + }, + { + /* [494] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(98), + }, + { + /* [495] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(101), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(332), + /* const_eval_fn */ ConstEvalFunctionIndex(98), + }, + { + /* [496] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(99), + }, + { + /* [497] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(332), + /* const_eval_fn */ ConstEvalFunctionIndex(99), + }, + { + /* [498] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(100), + }, + { + /* [499] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(332), + /* const_eval_fn */ ConstEvalFunctionIndex(100), + }, + { + /* [500] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(101), + }, + { + /* [501] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(332), + /* const_eval_fn */ ConstEvalFunctionIndex(101), + }, + { + /* [502] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(102), + }, + { + /* [503] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(332), + /* const_eval_fn */ ConstEvalFunctionIndex(102), + }, + { + /* [504] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(16), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(103), + }, + { + /* [505] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(453), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(103), + }, + { + /* [506] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(16), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(104), + }, + { + /* [507] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(453), + /* return_matcher_indices */ MatcherIndicesIndex(206), + /* const_eval_fn */ ConstEvalFunctionIndex(104), + }, + { + /* [508] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(141), + /* parameters */ ParameterIndex(470), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [509] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(51), + /* const_eval_fn */ ConstEvalFunctionIndex(17), + }, + { + /* [510] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(471), + /* return_matcher_indices */ MatcherIndicesIndex(24), + /* const_eval_fn */ ConstEvalFunctionIndex(19), + }, + { + /* [511] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(24), + /* const_eval_fn */ ConstEvalFunctionIndex(21), + }, + { + /* [512] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(22), + }, + { + /* [513] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(23), + }, + { + /* [514] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(27), + }, + { + /* [515] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(44), + }, + { + /* [516] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(45), + }, + { + /* [517] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(46), + }, + { + /* [518] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(47), + }, + { + /* [519] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(475), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(48), + }, + { + /* [520] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(475), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(49), + }, + { + /* [521] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(476), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(50), + }, + { + /* [522] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(477), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(51), + }, + { + /* [523] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(476), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(52), + }, + { + /* [524] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(477), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(53), + }, + { + /* [525] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(57), + }, + { + /* [526] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(285), + /* return_matcher_indices */ MatcherIndicesIndex(200), + /* const_eval_fn */ ConstEvalFunctionIndex(58), + }, + { + /* [527] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [528] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(87), + /* parameters */ ParameterIndex(478), + /* return_matcher_indices */ MatcherIndicesIndex(164), + /* const_eval_fn */ ConstEvalFunctionIndex(72), + }, + { + /* [529] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(342), + /* const_eval_fn */ ConstEvalFunctionIndex(74), + }, + { + /* [530] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(342), + /* const_eval_fn */ ConstEvalFunctionIndex(75), + }, + { + /* [531] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(342), + /* const_eval_fn */ ConstEvalFunctionIndex(76), + }, + { + /* [532] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(77), + }, + { + /* [533] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(5), + /* const_eval_fn */ ConstEvalFunctionIndex(78), + }, + { + /* [534] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(12), + /* const_eval_fn */ ConstEvalFunctionIndex(79), + }, + { + /* [535] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(80), + }, + { + /* [536] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(79), + /* parameters */ ParameterIndex(484), + /* return_matcher_indices */ MatcherIndicesIndex(62), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [537] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(77), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [538] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(77), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [539] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(77), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [540] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(77), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(382), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [541] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(19), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [542] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [543] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [544] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(95), + }, + { + /* [545] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(96), + }, + { + /* [546] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 3, + /* num_templates */ 3, + /* templates */ TemplateIndex(132), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(145), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [547] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 3, + /* num_templates */ 3, + /* templates */ TemplateIndex(135), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(150), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [548] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 3, + /* num_templates */ 3, + /* templates */ TemplateIndex(138), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(155), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, +}; + +static_assert(OverloadIndex::CanIndex(kOverloads), + "OverloadIndex is not large enough to index kOverloads"); + +constexpr IntrinsicInfo kBuiltins[] = { + { + /* [0] */ + /* fn abs[T : fiu32_f16](T) -> T */ + /* fn abs[N : num, T : fiu32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(358), + }, + { + /* [1] */ + /* fn acos[T : f32_f16](@test_value(0.96891242171) T) -> T */ + /* fn acos[N : num, T : f32_f16](@test_value(0.96891242171) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(360), + }, + { + /* [2] */ + /* fn acosh[T : f32_f16](@test_value(1.5430806348) T) -> T */ + /* fn acosh[N : num, T : f32_f16](@test_value(1.5430806348) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(362), + }, + { + /* [3] */ + /* fn all(bool) -> bool */ + /* fn all[N : num](vec) -> bool */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(364), + }, + { + /* [4] */ + /* fn any(bool) -> bool */ + /* fn any[N : num](vec) -> bool */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(366), + }, + { + /* [5] */ + /* fn arrayLength[T, A : access](ptr, A>) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(508), + }, + { + /* [6] */ + /* fn asin[T : f32_f16](@test_value(0.479425538604) T) -> T */ + /* fn asin[N : num, T : f32_f16](@test_value(0.479425538604) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(368), + }, + { + /* [7] */ + /* fn asinh[T : f32_f16](T) -> T */ + /* fn asinh[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(370), + }, + { + /* [8] */ + /* fn atan[T : f32_f16](T) -> T */ + /* fn atan[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(372), + }, + { + /* [9] */ + /* fn atan2[T : f32_f16](T, T) -> T */ + /* fn atan2[T : f32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(374), + }, + { + /* [10] */ + /* fn atanh[T : f32_f16](@test_value(0.5) T) -> T */ + /* fn atanh[N : num, T : f32_f16](@test_value(0.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(376), + }, + { + /* [11] */ + /* fn ceil[T : f32_f16](@test_value(1.5) T) -> T */ + /* fn ceil[N : num, T : f32_f16](@test_value(1.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(378), + }, + { + /* [12] */ + /* fn clamp[T : fiu32_f16](T, T, T) -> T */ + /* fn clamp[T : fiu32_f16, N : num](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(380), + }, + { + /* [13] */ + /* fn cos[T : f32_f16](@test_value(0) T) -> T */ + /* fn cos[N : num, T : f32_f16](@test_value(0) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(382), + }, + { + /* [14] */ + /* fn cosh[T : f32_f16](@test_value(0) T) -> T */ + /* fn cosh[N : num, T : f32_f16](@test_value(0) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(384), + }, + { + /* [15] */ + /* fn countLeadingZeros[T : iu32](T) -> T */ + /* fn countLeadingZeros[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(386), + }, + { + /* [16] */ + /* fn countOneBits[T : iu32](T) -> T */ + /* fn countOneBits[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(388), + }, + { + /* [17] */ + /* fn countTrailingZeros[T : iu32](T) -> T */ + /* fn countTrailingZeros[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(390), + }, + { + /* [18] */ + /* fn cross[T : f32_f16](vec3, vec3) -> vec3 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(509), + }, + { + /* [19] */ + /* fn degrees[T : f32_f16](T) -> T */ + /* fn degrees[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(392), + }, + { + /* [20] */ + /* fn determinant[N : num, T : f32_f16](mat) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(510), + }, + { + /* [21] */ + /* fn distance[T : f32_f16](T, T) -> T */ + /* fn distance[N : num, T : f32_f16](vec, vec) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(394), + }, + { + /* [22] */ + /* fn dot[N : num, T : fiu32_f16](vec, vec) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(511), + }, + { + /* [23] */ + /* fn dot4I8Packed(u32, u32) -> i32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(512), + }, + { + /* [24] */ + /* fn dot4U8Packed(u32, u32) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(513), + }, + { + /* [25] */ + /* fn dpdx(f32) -> f32 */ + /* fn dpdx[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [26] */ + /* fn dpdxCoarse(f32) -> f32 */ + /* fn dpdxCoarse[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [27] */ + /* fn dpdxFine(f32) -> f32 */ + /* fn dpdxFine[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [28] */ + /* fn dpdy(f32) -> f32 */ + /* fn dpdy[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [29] */ + /* fn dpdyCoarse(f32) -> f32 */ + /* fn dpdyCoarse[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [30] */ + /* fn dpdyFine(f32) -> f32 */ + /* fn dpdyFine[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [31] */ + /* fn exp[T : f32_f16](T) -> T */ + /* fn exp[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(398), + }, + { + /* [32] */ + /* fn exp2[T : f32_f16](T) -> T */ + /* fn exp2[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(400), + }, + { + /* [33] */ + /* fn extractBits[T : iu32](T, u32, u32) -> T */ + /* fn extractBits[N : num, T : iu32](vec, u32, u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(402), + }, + { + /* [34] */ + /* fn faceForward[N : num, T : f32_f16](vec, vec, vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(514), + }, + { + /* [35] */ + /* fn firstLeadingBit[T : iu32](T) -> T */ + /* fn firstLeadingBit[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(404), + }, + { + /* [36] */ + /* fn firstTrailingBit[T : iu32](T) -> T */ + /* fn firstTrailingBit[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(406), + }, + { + /* [37] */ + /* fn floor[T : f32_f16](@test_value(1.5) T) -> T */ + /* fn floor[N : num, T : f32_f16](@test_value(1.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(408), + }, + { + /* [38] */ + /* fn fma[T : f32_f16](T, T, T) -> T */ + /* fn fma[N : num, T : f32_f16](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(410), + }, + { + /* [39] */ + /* fn fract[T : f32_f16](@test_value(1.25) T) -> T */ + /* fn fract[N : num, T : f32_f16](@test_value(1.25) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(412), + }, + { + /* [40] */ + /* fn frexp[T : f32_f16](T) -> __frexp_result */ + /* fn frexp[N : num, T : f32_f16](vec) -> __frexp_result_vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(414), + }, + { + /* [41] */ + /* fn fwidth(f32) -> f32 */ + /* fn fwidth[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [42] */ + /* fn fwidthCoarse(f32) -> f32 */ + /* fn fwidthCoarse[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [43] */ + /* fn fwidthFine(f32) -> f32 */ + /* fn fwidthFine[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(396), + }, + { + /* [44] */ + /* fn insertBits[T : iu32](T, T, u32, u32) -> T */ + /* fn insertBits[N : num, T : iu32](vec, vec, u32, u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(416), + }, + { + /* [45] */ + /* fn inverseSqrt[T : f32_f16](T) -> T */ + /* fn inverseSqrt[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(418), + }, + { + /* [46] */ + /* fn ldexp[T : f32_f16, U : i32](T, U) -> T */ + /* fn ldexp[N : num, T : f32_f16, U : i32](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(420), + }, + { + /* [47] */ + /* fn length[T : f32_f16](@test_value(0) T) -> T */ + /* fn length[N : num, T : f32_f16](@test_value(0) vec) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(422), + }, + { + /* [48] */ + /* fn log[T : f32_f16](T) -> T */ + /* fn log[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(424), + }, + { + /* [49] */ + /* fn log2[T : f32_f16](T) -> T */ + /* fn log2[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(426), + }, + { + /* [50] */ + /* fn max[T : fiu32_f16](T, T) -> T */ + /* fn max[N : num, T : fiu32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(428), + }, + { + /* [51] */ + /* fn min[T : fiu32_f16](T, T) -> T */ + /* fn min[N : num, T : fiu32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(430), + }, + { + /* [52] */ + /* fn mix[T : f32_f16](T, T, T) -> T */ + /* fn mix[N : num, T : f32_f16](vec, vec, vec) -> vec */ + /* fn mix[N : num, T : f32_f16](vec, vec, T) -> vec */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(334), + }, + { + /* [53] */ + /* fn modf[T : f32_f16](@test_value(-1.5) T) -> __modf_result */ + /* fn modf[N : num, T : f32_f16](@test_value(-1.5) vec) -> __modf_result_vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(432), + }, + { + /* [54] */ + /* fn normalize[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(515), + }, + { + /* [55] */ + /* fn pack2x16float(vec2) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(516), + }, + { + /* [56] */ + /* fn pack2x16snorm(vec2) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(517), + }, + { + /* [57] */ + /* fn pack2x16unorm(vec2) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(518), + }, + { + /* [58] */ + /* fn pack4x8snorm(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(519), + }, + { + /* [59] */ + /* fn pack4x8unorm(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(520), + }, + { + /* [60] */ + /* fn pack4xI8(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(521), + }, + { + /* [61] */ + /* fn pack4xU8(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(522), + }, + { + /* [62] */ + /* fn pack4xI8Clamp(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(523), + }, + { + /* [63] */ + /* fn pack4xU8Clamp(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(524), + }, + { + /* [64] */ + /* fn pow[T : f32_f16](T, T) -> T */ + /* fn pow[N : num, T : f32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(434), + }, + { + /* [65] */ + /* fn quantizeToF16(f32) -> f32 */ + /* fn quantizeToF16[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(436), + }, + { + /* [66] */ + /* fn radians[T : f32_f16](T) -> T */ + /* fn radians[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(438), + }, + { + /* [67] */ + /* fn reflect[N : num, T : f32_f16](vec, vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(525), + }, + { + /* [68] */ + /* fn refract[N : num, T : f32_f16](vec, vec, T) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(526), + }, + { + /* [69] */ + /* fn reverseBits[T : iu32](T) -> T */ + /* fn reverseBits[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(440), + }, + { + /* [70] */ + /* fn round[T : f32_f16](@test_value(3.5) T) -> T */ + /* fn round[N : num, T : f32_f16](@test_value(3.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(442), + }, + { + /* [71] */ + /* fn saturate[T : f32_f16](@test_value(2) T) -> T */ + /* fn saturate[T : f32_f16, N : num](@test_value(2) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(444), + }, + { + /* [72] */ + /* fn select[T : scalar](T, T, bool) -> T */ + /* fn select[T : scalar, N : num](vec, vec, bool) -> vec */ + /* fn select[N : num, T : scalar](vec, vec, vec) -> vec */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(337), + }, + { + /* [73] */ + /* fn sign[T : fi32_f16](T) -> T */ + /* fn sign[N : num, T : fi32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(446), + }, + { + /* [74] */ + /* fn sin[T : f32_f16](@test_value(1.57079632679) T) -> T */ + /* fn sin[N : num, T : f32_f16](@test_value(1.57079632679) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(448), + }, + { + /* [75] */ + /* fn sinh[T : f32_f16](T) -> T */ + /* fn sinh[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(450), + }, + { + /* [76] */ + /* fn smoothstep[T : f32_f16](@test_value(2) T, @test_value(4) T, @test_value(3) T) -> T */ + /* fn smoothstep[N : num, T : f32_f16](@test_value(2) vec, @test_value(4) vec, @test_value(3) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(452), + }, + { + /* [77] */ + /* fn sqrt[T : f32_f16](T) -> T */ + /* fn sqrt[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(454), + }, + { + /* [78] */ + /* fn step[T : f32_f16](T, T) -> T */ + /* fn step[N : num, T : f32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(456), + }, + { + /* [79] */ + /* fn storageBarrier() */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(527), + }, + { + /* [80] */ + /* fn tan[T : f32_f16](T) -> T */ + /* fn tan[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(458), + }, + { + /* [81] */ + /* fn tanh[T : f32_f16](T) -> T */ + /* fn tanh[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(460), + }, + { + /* [82] */ + /* fn transpose[M : num, N : num, T : f32_f16](mat) -> mat */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(528), + }, + { + /* [83] */ + /* fn trunc[T : f32_f16](@test_value(1.5) T) -> T */ + /* fn trunc[N : num, T : f32_f16](@test_value(1.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(462), + }, + { + /* [84] */ + /* fn unpack2x16float(u32) -> vec2 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(529), + }, + { + /* [85] */ + /* fn unpack2x16snorm(u32) -> vec2 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(530), + }, + { + /* [86] */ + /* fn unpack2x16unorm(u32) -> vec2 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(531), + }, + { + /* [87] */ + /* fn unpack4x8snorm(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(532), + }, + { + /* [88] */ + /* fn unpack4x8unorm(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(533), + }, + { + /* [89] */ + /* fn unpack4xI8(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(534), + }, + { + /* [90] */ + /* fn unpack4xU8(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(535), + }, + { + /* [91] */ + /* fn workgroupBarrier() */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(527), + }, + { + /* [92] */ + /* fn textureBarrier() */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(527), + }, + { + /* [93] */ + /* fn textureDimensions[T : fiu32](texture: texture_1d) -> u32 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_1d, level: L) -> u32 */ + /* fn textureDimensions[T : fiu32](texture: texture_2d) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_2d, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_2d_array) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_2d_array, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_3d) -> vec3 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_3d, level: L) -> vec3 */ + /* fn textureDimensions[T : fiu32](texture: texture_cube) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_cube, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_cube_array) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_cube_array, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_multisampled_2d) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_2d) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_2d, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_2d_array) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_2d_array, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_cube) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_cube, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_cube_array) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_cube_array, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_multisampled_2d) -> vec2 */ + /* fn textureDimensions[F : texel_format, A : access](texture: texture_storage_1d) -> u32 */ + /* fn textureDimensions[F : texel_format, A : access](texture: texture_storage_2d) -> vec2 */ + /* fn textureDimensions[F : texel_format, A : access](texture: texture_storage_2d_array) -> vec2 */ + /* fn textureDimensions[F : texel_format, A : access](texture: texture_storage_3d) -> vec3 */ + /* fn textureDimensions[F : texel_format, A : access](texture: texel_buffer) -> u32 */ + /* fn textureDimensions(texture: texture_external) -> vec2 */ + /* num overloads */ 28, + /* overloads */ OverloadIndex(0), + }, + { + /* [94] */ + /* fn textureGather[T : fiu32, C : iu32](@const component: C, texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32](@const component: C, texture: texture_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32, A : iu32](@const component: C, texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32, A : iu32](@const component: C, texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32](@const component: C, texture: texture_cube, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32, A : iu32](@const component: C, texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A) -> vec4 */ + /* fn textureGather(texture: texture_depth_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureGather(texture: texture_depth_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> vec4 */ + /* fn textureGather[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A) -> vec4 */ + /* fn textureGather[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> vec4 */ + /* fn textureGather(texture: texture_depth_cube, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureGather[A : iu32](texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: A) -> vec4 */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(112), + }, + { + /* [95] */ + /* fn textureGatherCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> vec4 */ + /* fn textureGatherCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, @const offset: vec2) -> vec4 */ + /* fn textureGatherCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32) -> vec4 */ + /* fn textureGatherCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32, @const offset: vec2) -> vec4 */ + /* fn textureGatherCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> vec4 */ + /* fn textureGatherCompare[A : iu32](texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: A, depth_ref: f32) -> vec4 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(203), + }, + { + /* [96] */ + /* fn textureNumLayers[T : fiu32](texture: texture_2d_array) -> u32 */ + /* fn textureNumLayers[T : fiu32](texture: texture_cube_array) -> u32 */ + /* fn textureNumLayers(texture: texture_depth_2d_array) -> u32 */ + /* fn textureNumLayers(texture: texture_depth_cube_array) -> u32 */ + /* fn textureNumLayers[F : texel_format, A : access](texture: texture_storage_2d_array) -> u32 */ + /* num overloads */ 5, + /* overloads */ OverloadIndex(287), + }, + { + /* [97] */ + /* fn textureNumLevels[T : fiu32](texture: texture_1d) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_2d) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_2d_array) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_3d) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_cube) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_cube_array) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_2d) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_2d_array) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_cube) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_cube_array) -> u32 */ + /* num overloads */ 10, + /* overloads */ OverloadIndex(159), + }, + { + /* [98] */ + /* fn textureNumSamples[T : fiu32](texture: texture_multisampled_2d) -> u32 */ + /* fn textureNumSamples(texture: texture_depth_multisampled_2d) -> u32 */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(464), + }, + { + /* [99] */ + /* fn textureSample(texture: texture_1d, sampler: sampler, coords: f32) -> vec4 */ + /* fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> vec4 */ + /* fn textureSample[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A) -> vec4 */ + /* fn textureSample[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> vec4 */ + /* fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3, @const offset: vec3) -> vec4 */ + /* fn textureSample(texture: texture_cube, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureSample[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A) -> vec4 */ + /* fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2) -> f32 */ + /* fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> f32 */ + /* fn textureSample[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A) -> f32 */ + /* fn textureSample[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> f32 */ + /* fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3) -> f32 */ + /* fn textureSample[A : iu32](texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: A) -> f32 */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(52), + }, + { + /* [100] */ + /* fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32) -> vec4 */ + /* fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleBias[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, bias: f32) -> vec4 */ + /* fn textureSampleBias[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, bias: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32) -> vec4 */ + /* fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32, @const offset: vec3) -> vec4 */ + /* fn textureSampleBias(texture: texture_cube, sampler: sampler, coords: vec3, bias: f32) -> vec4 */ + /* fn textureSampleBias[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A, bias: f32) -> vec4 */ + /* num overloads */ 8, + /* overloads */ OverloadIndex(187), + }, + { + /* [101] */ + /* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> f32 */ + /* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32) -> f32 */ + /* fn textureSampleCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> f32 */ + /* fn textureSampleCompare[A : iu32](texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: A, depth_ref: f32) -> f32 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(209), + }, + { + /* [102] */ + /* fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> f32 */ + /* fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompareLevel[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32) -> f32 */ + /* fn textureSampleCompareLevel[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompareLevel(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> f32 */ + /* fn textureSampleCompareLevel[A : iu32](texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: A, depth_ref: f32) -> f32 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(215), + }, + { + /* [103] */ + /* fn textureSampleGrad(texture: texture_2d, sampler: sampler, coords: vec2, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn textureSampleGrad(texture: texture_2d, sampler: sampler, coords: vec2, ddx: vec2, ddy: vec2, @const offset: vec2) -> vec4 */ + /* fn textureSampleGrad[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn textureSampleGrad[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, ddx: vec2, ddy: vec2, @const offset: vec2) -> vec4 */ + /* fn textureSampleGrad(texture: texture_3d, sampler: sampler, coords: vec3, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn textureSampleGrad(texture: texture_3d, sampler: sampler, coords: vec3, ddx: vec3, ddy: vec3, @const offset: vec3) -> vec4 */ + /* fn textureSampleGrad(texture: texture_cube, sampler: sampler, coords: vec3, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn textureSampleGrad[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A, ddx: vec3, ddy: vec3) -> vec4 */ + /* num overloads */ 8, + /* overloads */ OverloadIndex(195), + }, + { + /* [104] */ + /* fn textureSampleLevel(texture: texture_1d, sampler: sampler, coords: f32, level: f32) -> vec4 */ + /* fn textureSampleLevel(texture: texture_2d, sampler: sampler, coords: vec2, level: f32) -> vec4 */ + /* fn textureSampleLevel(texture: texture_2d, sampler: sampler, coords: vec2, level: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleLevel[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, level: f32) -> vec4 */ + /* fn textureSampleLevel[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, level: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleLevel(texture: texture_3d, sampler: sampler, coords: vec3, level: f32) -> vec4 */ + /* fn textureSampleLevel(texture: texture_3d, sampler: sampler, coords: vec3, level: f32, @const offset: vec3) -> vec4 */ + /* fn textureSampleLevel(texture: texture_cube, sampler: sampler, coords: vec3, level: f32) -> vec4 */ + /* fn textureSampleLevel[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A, level: f32) -> vec4 */ + /* fn textureSampleLevel[L : iu32](texture: texture_depth_2d, sampler: sampler, coords: vec2, level: L) -> f32 */ + /* fn textureSampleLevel[L : iu32](texture: texture_depth_2d, sampler: sampler, coords: vec2, level: L, @const offset: vec2) -> f32 */ + /* fn textureSampleLevel[A : iu32, L : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, level: L) -> f32 */ + /* fn textureSampleLevel[A : iu32, L : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, level: L, @const offset: vec2) -> f32 */ + /* fn textureSampleLevel[L : iu32](texture: texture_depth_cube, sampler: sampler, coords: vec3, level: L) -> f32 */ + /* fn textureSampleLevel[A : iu32, L : iu32](texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: A, level: L) -> f32 */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(67), + }, + { + /* [105] */ + /* fn textureSampleBaseClampToEdge(texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureSampleBaseClampToEdge(texture: texture_external, sampler: sampler, coords: vec2) -> vec4 */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(466), + }, + { + /* [106] */ + /* fn textureStore[C : iu32](texture: texture_storage_1d, coords: C, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_2d, coords: vec2, value: vec4) */ + /* fn textureStore[C : iu32, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_3d, coords: vec3, value: vec4) */ + /* fn textureStore[C : iu32](texture: texel_buffer, coords: C, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_1d, coords: C, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_2d, coords: vec2, value: vec4) */ + /* fn textureStore[C : iu32, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_3d, coords: vec3, value: vec4) */ + /* fn textureStore[C : iu32](texture: texel_buffer, coords: C, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_1d, coords: C, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_2d, coords: vec2, value: vec4) */ + /* fn textureStore[C : iu32, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A, value: vec4) */ + /* fn textureStore[C : iu32](texture: texture_storage_3d, coords: vec3, value: vec4) */ + /* fn textureStore[C : iu32](texture: texel_buffer, coords: C, value: vec4) */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(82), + }, + { + /* [107] */ + /* fn textureLoad[T : fiu32, C : iu32, L : iu32](texture: texture_1d, coords: C, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, L : iu32](texture: texture_2d, coords: vec2, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, A : iu32, L : iu32](texture: texture_2d_array, coords: vec2, array_index: A, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, L : iu32](texture: texture_3d, coords: vec3, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, S : iu32](texture: texture_multisampled_2d, coords: vec2, sample_index: S) -> vec4 */ + /* fn textureLoad[C : iu32, L : iu32](texture: texture_depth_2d, coords: vec2, level: L) -> f32 */ + /* fn textureLoad[C : iu32, A : iu32, L : iu32](texture: texture_depth_2d_array, coords: vec2, array_index: A, level: L) -> f32 */ + /* fn textureLoad[C : iu32, S : iu32](texture: texture_depth_multisampled_2d, coords: vec2, sample_index: S) -> f32 */ + /* fn textureLoad[C : iu32](texture: texture_external, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32](texture: texel_buffer, coords: C) -> vec4 */ + /* num overloads */ 24, + /* overloads */ OverloadIndex(28), + }, + { + /* [108] */ + /* fn inputAttachmentLoad[T : fiu32](input_attachment: input_attachment) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(536), + }, + { + /* [109] */ + /* fn atomicLoad[T : iu32, S : workgroup_or_storage](ptr, read_write>) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(537), + }, + { + /* [110] */ + /* fn atomicStore[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(538), + }, + { + /* [111] */ + /* fn atomicAdd[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [112] */ + /* fn atomicSub[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [113] */ + /* fn atomicMax[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [114] */ + /* fn atomicMin[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [115] */ + /* fn atomicAnd[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [116] */ + /* fn atomicOr[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [117] */ + /* fn atomicXor[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [118] */ + /* fn atomicExchange[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(539), + }, + { + /* [119] */ + /* fn atomicCompareExchangeWeak[T : iu32, S : workgroup_or_storage](ptr, read_write>, T, T) -> __atomic_compare_exchange_result */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(540), + }, + { + /* [120] */ + /* fn subgroupBallot(bool) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(541), + }, + { + /* [121] */ + /* fn subgroupElect() -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(542), + }, + { + /* [122] */ + /* fn subgroupBroadcast[T : fiu32_f16](value: T, @const sourceLaneIndex: iu32) -> T */ + /* fn subgroupBroadcast[N : num, T : fiu32_f16](value: vec, @const sourceLaneIndex: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(468), + }, + { + /* [123] */ + /* fn subgroupBroadcastFirst[T : fiu32_f16](value: T) -> T */ + /* fn subgroupBroadcastFirst[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [124] */ + /* fn subgroupShuffle[T : fiu32_f16](value: T, sourceLaneIndex: iu32) -> T */ + /* fn subgroupShuffle[N : num, T : fiu32_f16](value: vec, sourceLaneIndex: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(468), + }, + { + /* [125] */ + /* fn subgroupShuffleXor[T : fiu32_f16](value: T, mask: u32) -> T */ + /* fn subgroupShuffleXor[N : num, T : fiu32_f16](value: vec, mask: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(472), + }, + { + /* [126] */ + /* fn subgroupShuffleUp[T : fiu32_f16](value: T, delta: u32) -> T */ + /* fn subgroupShuffleUp[N : num, T : fiu32_f16](value: vec, delta: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(474), + }, + { + /* [127] */ + /* fn subgroupShuffleDown[T : fiu32_f16](value: T, delta: u32) -> T */ + /* fn subgroupShuffleDown[N : num, T : fiu32_f16](value: vec, delta: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(474), + }, + { + /* [128] */ + /* fn subgroupAdd[T : fiu32_f16](value: T) -> T */ + /* fn subgroupAdd[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [129] */ + /* fn subgroupInclusiveAdd[T : fiu32_f16](value: T) -> T */ + /* fn subgroupInclusiveAdd[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [130] */ + /* fn subgroupExclusiveAdd[T : fiu32_f16](value: T) -> T */ + /* fn subgroupExclusiveAdd[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [131] */ + /* fn subgroupMul[T : fiu32_f16](value: T) -> T */ + /* fn subgroupMul[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [132] */ + /* fn subgroupInclusiveMul[T : fiu32_f16](value: T) -> T */ + /* fn subgroupInclusiveMul[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [133] */ + /* fn subgroupExclusiveMul[T : fiu32_f16](value: T) -> T */ + /* fn subgroupExclusiveMul[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [134] */ + /* fn subgroupAnd[T : iu32](value: T) -> T */ + /* fn subgroupAnd[N : num, T : iu32](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(476), + }, + { + /* [135] */ + /* fn subgroupOr[T : iu32](value: T) -> T */ + /* fn subgroupOr[N : num, T : iu32](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(476), + }, + { + /* [136] */ + /* fn subgroupXor[T : iu32](value: T) -> T */ + /* fn subgroupXor[N : num, T : iu32](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(476), + }, + { + /* [137] */ + /* fn subgroupMin[T : fiu32_f16](value: T) -> T */ + /* fn subgroupMin[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [138] */ + /* fn subgroupMax[T : fiu32_f16](value: T) -> T */ + /* fn subgroupMax[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [139] */ + /* fn subgroupAll(bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(543), + }, + { + /* [140] */ + /* fn subgroupAny(bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(543), + }, + { + /* [141] */ + /* fn quadBroadcast[T : fiu32_f16](e: T, @const id: iu32) -> T */ + /* fn quadBroadcast[N : num, T : fiu32_f16](e: vec, @const id: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(478), + }, + { + /* [142] */ + /* fn quadSwapX[T : fiu32_f16](e: T) -> T */ + /* fn quadSwapX[N : num, T : fiu32_f16](e: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [143] */ + /* fn quadSwapY[T : fiu32_f16](e: T) -> T */ + /* fn quadSwapY[N : num, T : fiu32_f16](e: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [144] */ + /* fn quadSwapDiagonal[T : fiu32_f16](e: T) -> T */ + /* fn quadSwapDiagonal[N : num, T : fiu32_f16](e: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [145] */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num](ptr, readable>, u32, @const bool, u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num, AC : num](ptr, readable>, u32, @const bool, u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : i8, C : num, R : num](ptr, readable>, u32, @const bool, u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : u8, C : num, R : num](ptr, readable>, u32, @const bool, u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : i8, C : num, R : num, AC : num](ptr, readable>, u32, @const bool, u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : u8, C : num, R : num, AC : num](ptr, readable>, u32, @const bool, u32) -> T */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(221), + }, + { + /* [146] */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num](ptr, writable>, u32, subgroup_matrix, @const bool, u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num, AC : num](ptr, writable>, u32, subgroup_matrix, @const bool, u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : i8, C : num, R : num](ptr, writable>, u32, subgroup_matrix, @const bool, u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : u8, C : num, R : num](ptr, writable>, u32, subgroup_matrix, @const bool, u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : i8, C : num, R : num, AC : num](ptr, writable>, u32, subgroup_matrix, @const bool, u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : u8, C : num, R : num, AC : num](ptr, writable>, u32, subgroup_matrix, @const bool, u32) */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(227), + }, + { + /* [147] */ + /* fn subgroupMatrixMultiply[T : f16, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiply[T : f32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiply[T : iu8, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiply[T : iu32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(302), + }, + { + /* [148] */ + /* fn subgroupMatrixMultiplyAccumulate[T : f16, TR : f32_f16, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiplyAccumulate[T : f32, TR : f32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiplyAccumulate[T : iu8, TR : iu32_iu8, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiplyAccumulate[T : iu32, TR : iu32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(306), + }, + { + /* [149] */ + /* fn subgroupMatrixScalarAdd[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](m: subgroup_matrix, s: T) -> subgroup_matrix */ + /* fn subgroupMatrixScalarAdd[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, s: i32) -> subgroup_matrix */ + /* fn subgroupMatrixScalarAdd[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, s: u32) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(340), + }, + { + /* [150] */ + /* fn subgroupMatrixScalarSubtract[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](m: subgroup_matrix, s: T) -> subgroup_matrix */ + /* fn subgroupMatrixScalarSubtract[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, s: i32) -> subgroup_matrix */ + /* fn subgroupMatrixScalarSubtract[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, s: u32) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(340), + }, + { + /* [151] */ + /* fn subgroupMatrixScalarMultiply[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](m: subgroup_matrix, s: T) -> subgroup_matrix */ + /* fn subgroupMatrixScalarMultiply[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, s: i32) -> subgroup_matrix */ + /* fn subgroupMatrixScalarMultiply[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, s: u32) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(340), + }, + { + /* [152] */ + /* fn bufferView[R : read, AS : uniform_or_storage, O : iu32](ptr, O) -> ptr */ + /* fn bufferView[R : read, AS : uniform_or_storage, O : iu32, N : num](ptr, R>, O) -> ptr */ + /* fn bufferView[W : read_write, AS : workgroup_or_storage, O : iu32](ptr, O) -> ptr */ + /* fn bufferView[W : read_write, AS : workgroup_or_storage, O : iu32, N : num](ptr, W>, O) -> ptr */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(310), + }, + { + /* [153] */ + /* fn bufferLength[R : read, AS : uniform_or_storage](ptr) -> u32 */ + /* fn bufferLength[R : read, AS : uniform_or_storage, N : num](ptr, R>) -> u32 */ + /* fn bufferLength[W : read_write, AS : workgroup_or_storage](ptr) -> u32 */ + /* fn bufferLength[W : read_write, AS : workgroup_or_storage, N : num](ptr, W>) -> u32 */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(314), + }, + { + /* [154] */ + /* fn print[T : scalar](T) */ + /* fn print[N : num, T : scalar](vec) */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(482), + }, + { + /* [155] */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(124), + }, + { + /* [156] */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(136), + }, +}; + +constexpr IntrinsicInfo kUnaryOperators[] = { + { + /* [0] */ + /* op !(bool) -> bool */ + /* op ![N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(484), + }, + { + /* [1] */ + /* op ~[T : iu32](T) -> T */ + /* op ~[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(486), + }, + { + /* [2] */ + /* op -[T : fi32_f16](T) -> T */ + /* op -[T : fi32_f16, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(488), + }, +}; +constexpr uint8_t kUnaryOperatorNot = 0; +constexpr uint8_t kUnaryOperatorComplement = 1; +constexpr uint8_t kUnaryOperatorMinus = 2; + +constexpr IntrinsicInfo kBinaryOperators[] = { + { + /* [0] */ + /* op +[T : fiu32_f16](T, T) -> T */ + /* op +[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* op +[T : fiu32_f16, N : num](vec, T) -> vec */ + /* op +[T : fiu32_f16, N : num](T, vec) -> vec */ + /* op +[T : f32_f16, N : num, M : num](mat, mat) -> mat */ + /* num overloads */ 5, + /* overloads */ OverloadIndex(292), + }, + { + /* [1] */ + /* op -[T : fiu32_f16](T, T) -> T */ + /* op -[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* op -[T : fiu32_f16, N : num](vec, T) -> vec */ + /* op -[T : fiu32_f16, N : num](T, vec) -> vec */ + /* op -[T : f32_f16, N : num, M : num](mat, mat) -> mat */ + /* num overloads */ 5, + /* overloads */ OverloadIndex(297), + }, + { + /* [2] */ + /* op *[T : fiu32_f16](T, T) -> T */ + /* op *[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* op *[T : fiu32_f16, N : num](vec, T) -> vec */ + /* op *[T : fiu32_f16, N : num](T, vec) -> vec */ + /* op *[T : f32_f16, N : num, M : num](T, mat) -> mat */ + /* op *[T : f32_f16, N : num, M : num](mat, T) -> mat */ + /* op *[T : f32_f16, C : num, R : num](mat, vec) -> vec */ + /* op *[T : f32_f16, C : num, R : num](vec, mat) -> vec */ + /* op *[T : f32_f16, K : num, C : num, R : num](mat, mat) -> mat */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(169), + }, + { + /* [3] */ + /* op /[T : fiu32_f16](T, T) -> T */ + /* op /[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* op /[T : fiu32_f16, N : num](vec, T) -> vec */ + /* op /[T : fiu32_f16, N : num](T, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(318), + }, + { + /* [4] */ + /* op %[T : fiu32_f16](T, T) -> T */ + /* op %[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* op %[T : fiu32_f16, N : num](vec, T) -> vec */ + /* op %[T : fiu32_f16, N : num](T, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(322), + }, + { + /* [5] */ + /* op ^[T : iu32](T, T) -> T */ + /* op ^[T : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(490), + }, + { + /* [6] */ + /* op &(bool, bool) -> bool */ + /* op &[N : num](vec, vec) -> vec */ + /* op &[T : iu32](T, T) -> T */ + /* op &[T : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(326), + }, + { + /* [7] */ + /* op |(bool, bool) -> bool */ + /* op |[N : num](vec, vec) -> vec */ + /* op |[T : iu32](T, T) -> T */ + /* op |[T : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(330), + }, + { + /* [8] */ + /* op &&(bool, bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(544), + }, + { + /* [9] */ + /* op ||(bool, bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(545), + }, + { + /* [10] */ + /* op ==[T : scalar](T, T) -> bool */ + /* op ==[T : scalar, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(492), + }, + { + /* [11] */ + /* op !=[T : scalar](T, T) -> bool */ + /* op !=[T : scalar, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(494), + }, + { + /* [12] */ + /* op <[T : fiu32_f16](T, T) -> bool */ + /* op <[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(496), + }, + { + /* [13] */ + /* op >[T : fiu32_f16](T, T) -> bool */ + /* op >[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(498), + }, + { + /* [14] */ + /* op <=[T : fiu32_f16](T, T) -> bool */ + /* op <=[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(500), + }, + { + /* [15] */ + /* op >=[T : fiu32_f16](T, T) -> bool */ + /* op >=[T : fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(502), + }, + { + /* [16] */ + /* op <<[T : iu32](T, u32) -> T */ + /* op <<[T : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(504), + }, + { + /* [17] */ + /* op >>[T : iu32](T, u32) -> T */ + /* op >>[T : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(506), + }, +}; +constexpr uint8_t kBinaryOperatorPlus = 0; +constexpr uint8_t kBinaryOperatorMinus = 1; +constexpr uint8_t kBinaryOperatorStar = 2; +constexpr uint8_t kBinaryOperatorDivide = 3; +constexpr uint8_t kBinaryOperatorModulo = 4; +constexpr uint8_t kBinaryOperatorXor = 5; +constexpr uint8_t kBinaryOperatorAnd = 6; +constexpr uint8_t kBinaryOperatorOr = 7; +constexpr uint8_t kBinaryOperatorLogicalAnd = 8; +constexpr uint8_t kBinaryOperatorLogicalOr = 9; +constexpr uint8_t kBinaryOperatorEqual = 10; +constexpr uint8_t kBinaryOperatorNotEqual = 11; +constexpr uint8_t kBinaryOperatorLessThan = 12; +constexpr uint8_t kBinaryOperatorGreaterThan = 13; +constexpr uint8_t kBinaryOperatorLessThanEqual = 14; +constexpr uint8_t kBinaryOperatorGreaterThanEqual = 15; +constexpr uint8_t kBinaryOperatorShiftLeft = 16; +constexpr uint8_t kBinaryOperatorShiftRight = 17; + +constexpr IntrinsicInfo kConstructorsAndConverters[] = { + { + /* [0] */ + /* ctor i32() -> i32 */ + /* ctor i32(i32) -> i32 */ + /* conv i32[T : scalar_no_i32](T) -> i32 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(343), + }, + { + /* [1] */ + /* ctor u32() -> u32 */ + /* ctor u32(u32) -> u32 */ + /* conv u32[T : scalar_no_u32](T) -> u32 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(346), + }, + { + /* [2] */ + /* ctor f32() -> f32 */ + /* ctor f32(f32) -> f32 */ + /* conv f32[T : scalar_no_f32](T) -> f32 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(349), + }, + { + /* [3] */ + /* ctor f16() -> f16 */ + /* ctor f16(f16) -> f16 */ + /* conv f16[T : scalar_no_f16](T) -> f16 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(352), + }, + { + /* [4] */ + /* ctor bool() -> bool */ + /* ctor bool(bool) -> bool */ + /* conv bool[T : scalar_no_bool](T) -> bool */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(355), + }, + { + /* [5] */ + /* ctor vec2() -> vec2 */ + /* ctor vec2(vec2) -> vec2 */ + /* ctor vec2(T) -> vec2 */ + /* ctor vec2(x: T, y: T) -> vec2 */ + /* conv vec2[U : scalar_no_f32](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_f16](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_i32](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_u32](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_bool](vec2) -> vec2 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(178), + }, + { + /* [6] */ + /* ctor vec3() -> vec3 */ + /* ctor vec3(vec3) -> vec3 */ + /* ctor vec3(T) -> vec3 */ + /* ctor vec3(x: T, y: T, z: T) -> vec3 */ + /* ctor vec3(xy: vec2, z: T) -> vec3 */ + /* ctor vec3(x: T, yz: vec2) -> vec3 */ + /* conv vec3[U : scalar_no_f32](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_f16](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_i32](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_u32](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_bool](vec3) -> vec3 */ + /* num overloads */ 11, + /* overloads */ OverloadIndex(148), + }, + { + /* [7] */ + /* ctor vec4() -> vec4 */ + /* ctor vec4(vec4) -> vec4 */ + /* ctor vec4(T) -> vec4 */ + /* ctor vec4(x: T, y: T, z: T, w: T) -> vec4 */ + /* ctor vec4(xy: vec2, z: T, w: T) -> vec4 */ + /* ctor vec4(x: T, yz: vec2, w: T) -> vec4 */ + /* ctor vec4(x: T, y: T, zw: vec2) -> vec4 */ + /* ctor vec4(xy: vec2, zw: vec2) -> vec4 */ + /* ctor vec4(xyz: vec3, w: T) -> vec4 */ + /* ctor vec4(x: T, zyw: vec3) -> vec4 */ + /* conv vec4[U : scalar_no_f32](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_f16](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_i32](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_u32](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_bool](vec4) -> vec4 */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(97), + }, + { + /* [8] */ + /* ctor mat2x2() -> mat2x2 */ + /* ctor mat2x2(mat2x2) -> mat2x2 */ + /* ctor mat2x2(T, T, T, T) -> mat2x2 */ + /* ctor mat2x2(vec2, vec2) -> mat2x2 */ + /* conv mat2x2(mat2x2) -> mat2x2 */ + /* conv mat2x2(mat2x2) -> mat2x2 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(233), + }, + { + /* [9] */ + /* ctor mat2x3() -> mat2x3 */ + /* ctor mat2x3(mat2x3) -> mat2x3 */ + /* ctor mat2x3(T, T, T, T, T, T) -> mat2x3 */ + /* ctor mat2x3(vec3, vec3) -> mat2x3 */ + /* conv mat2x3(mat2x3) -> mat2x3 */ + /* conv mat2x3(mat2x3) -> mat2x3 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(239), + }, + { + /* [10] */ + /* ctor mat2x4() -> mat2x4 */ + /* ctor mat2x4(mat2x4) -> mat2x4 */ + /* ctor mat2x4(T, T, T, T, T, T, T, T) -> mat2x4 */ + /* ctor mat2x4(vec4, vec4) -> mat2x4 */ + /* conv mat2x4(mat2x4) -> mat2x4 */ + /* conv mat2x4(mat2x4) -> mat2x4 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(245), + }, + { + /* [11] */ + /* ctor mat3x2() -> mat3x2 */ + /* ctor mat3x2(mat3x2) -> mat3x2 */ + /* ctor mat3x2(T, T, T, T, T, T) -> mat3x2 */ + /* ctor mat3x2(vec2, vec2, vec2) -> mat3x2 */ + /* conv mat3x2(mat3x2) -> mat3x2 */ + /* conv mat3x2(mat3x2) -> mat3x2 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(251), + }, + { + /* [12] */ + /* ctor mat3x3() -> mat3x3 */ + /* ctor mat3x3(mat3x3) -> mat3x3 */ + /* ctor mat3x3(T, T, T, T, T, T, T, T, T) -> mat3x3 */ + /* ctor mat3x3(vec3, vec3, vec3) -> mat3x3 */ + /* conv mat3x3(mat3x3) -> mat3x3 */ + /* conv mat3x3(mat3x3) -> mat3x3 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(257), + }, + { + /* [13] */ + /* ctor mat3x4() -> mat3x4 */ + /* ctor mat3x4(mat3x4) -> mat3x4 */ + /* ctor mat3x4(T, T, T, T, T, T, T, T, T, T, T, T) -> mat3x4 */ + /* ctor mat3x4(vec4, vec4, vec4) -> mat3x4 */ + /* conv mat3x4(mat3x4) -> mat3x4 */ + /* conv mat3x4(mat3x4) -> mat3x4 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(263), + }, + { + /* [14] */ + /* ctor mat4x2() -> mat4x2 */ + /* ctor mat4x2(mat4x2) -> mat4x2 */ + /* ctor mat4x2(T, T, T, T, T, T, T, T) -> mat4x2 */ + /* ctor mat4x2(vec2, vec2, vec2, vec2) -> mat4x2 */ + /* conv mat4x2(mat4x2) -> mat4x2 */ + /* conv mat4x2(mat4x2) -> mat4x2 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(269), + }, + { + /* [15] */ + /* ctor mat4x3() -> mat4x3 */ + /* ctor mat4x3(mat4x3) -> mat4x3 */ + /* ctor mat4x3(T, T, T, T, T, T, T, T, T, T, T, T) -> mat4x3 */ + /* ctor mat4x3(vec3, vec3, vec3, vec3) -> mat4x3 */ + /* conv mat4x3(mat4x3) -> mat4x3 */ + /* conv mat4x3(mat4x3) -> mat4x3 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(275), + }, + { + /* [16] */ + /* ctor mat4x4() -> mat4x4 */ + /* ctor mat4x4(mat4x4) -> mat4x4 */ + /* ctor mat4x4(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> mat4x4 */ + /* ctor mat4x4(vec4, vec4, vec4, vec4) -> mat4x4 */ + /* conv mat4x4(mat4x4) -> mat4x4 */ + /* conv mat4x4(mat4x4) -> mat4x4 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(281), + }, + { + /* [17] */ + /* ctor subgroup_matrix_left() -> subgroup_matrix */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(546), + }, + { + /* [18] */ + /* ctor subgroup_matrix_right() -> subgroup_matrix */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(547), + }, + { + /* [19] */ + /* ctor subgroup_matrix_result() -> subgroup_matrix */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(548), + }, +}; + +} // anonymous namespace + +const core::intrinsic::TableData Dialect::kData{ + /* templates */ kTemplates, + /* type_matcher_indices */ kMatcherIndices, + /* type_matchers */ kTypeMatchers, + /* number_matchers */ kNumberMatchers, + /* parameters */ kParameters, + /* overloads */ kOverloads, + /* const_eval_functions */ kConstEvalFunctions, + /* ctor_conv */ kConstructorsAndConverters, + /* builtins */ kBuiltins, + /* binary '+' */ kBinaryOperators[kBinaryOperatorPlus], + /* binary '-' */ kBinaryOperators[kBinaryOperatorMinus], + /* binary '*' */ kBinaryOperators[kBinaryOperatorStar], + /* binary '/' */ kBinaryOperators[kBinaryOperatorDivide], + /* binary '%' */ kBinaryOperators[kBinaryOperatorModulo], + /* binary '^' */ kBinaryOperators[kBinaryOperatorXor], + /* binary '&' */ kBinaryOperators[kBinaryOperatorAnd], + /* binary '|' */ kBinaryOperators[kBinaryOperatorOr], + /* binary '&&' */ kBinaryOperators[kBinaryOperatorLogicalAnd], + /* binary '||' */ kBinaryOperators[kBinaryOperatorLogicalOr], + /* binary '==' */ kBinaryOperators[kBinaryOperatorEqual], + /* binary '!=' */ kBinaryOperators[kBinaryOperatorNotEqual], + /* binary '<' */ kBinaryOperators[kBinaryOperatorLessThan], + /* binary '>' */ kBinaryOperators[kBinaryOperatorGreaterThan], + /* binary '<=' */ kBinaryOperators[kBinaryOperatorLessThanEqual], + /* binary '>=' */ kBinaryOperators[kBinaryOperatorGreaterThanEqual], + /* binary '<<' */ kBinaryOperators[kBinaryOperatorShiftLeft], + /* binary '>>' */ kBinaryOperators[kBinaryOperatorShiftRight], + /* unary '!' */ kUnaryOperators[kUnaryOperatorNot], + /* unary '~' */ kUnaryOperators[kUnaryOperatorComplement], + /* unary '-' */ kUnaryOperators[kUnaryOperatorMinus], + /* unary '*' */ tint::core::intrinsic::kNoOverloads, + /* unary '&' */ tint::core::intrinsic::kNoOverloads, +}; + +} // namespace tint::core::intrinsic + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/dialect.h b/3rdparty/dawn/src/tint/lang/core/intrinsic/dialect.h new file mode 100644 index 000000000..cd9215dd9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/dialect.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_INTRINSIC_DIALECT_H_ +#define SRC_TINT_LANG_CORE_INTRINSIC_DIALECT_H_ + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/intrinsic/ctor_conv.h" +#include "src/tint/lang/core/intrinsic/table_data.h" + +namespace tint::core::intrinsic { + +/// Dialect holds the intrinsic table data and types for the core dialect +struct Dialect { + /// The dialect's intrinsic table data + static const TableData kData; + + /// The dialect's builtin function enumerator + using BuiltinFn = core::BuiltinFn; + + /// The dialect's type constructor / convertor enumerator + using CtorConv = core::intrinsic::CtorConv; + + /// @returns the name of the builtin function @p fn + /// @param fn the builtin function + static std::string_view ToString(BuiltinFn fn) { return str(fn); } + + /// @returns the name of the type constructor / convertor @p ty + /// @param ty the type constructor / convertor + static std::string_view ToString(CtorConv ty) { return str(ty); } +}; + +} // namespace tint::core::intrinsic + +#endif // SRC_TINT_LANG_CORE_INTRINSIC_DIALECT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/table.cc b/3rdparty/dawn/src/tint/lang/core/intrinsic/table.cc new file mode 100644 index 000000000..cd08fb2d9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/table.cc @@ -0,0 +1,895 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/intrinsic/table.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/evaluation_stage.h" +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/type/invalid.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/utils/containers/slice.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +namespace tint::core::intrinsic { + +const Number Number::any{Number::kAny}; +const Number Number::invalid{Number::kInvalid}; + +Any::Any() : Base(0u, core::type::Flags{}) {} +Any::~Any() = default; + +bool Any::Equals(const core::type::UniqueNode&) const { + return false; +} + +std::string Any::FriendlyName() const { + return ""; +} + +core::type::Type* Any::Clone(core::type::CloneContext&) const { + return nullptr; +} + +namespace { + +/// The Vector `N` template argument value for arrays of parameters. +constexpr const size_t kNumFixedParameters = Overload::kNumFixedParameters; + +/// The Vector `N` template argument value for arrays of overload candidates. +constexpr const size_t kNumFixedCandidates = 8; + +/// A list of candidates +using Candidates = Vector; + +/// Callback function when no overloads match. +using OnNoMatch = std::function)>; + +/// Sorts the candidates based on their score, with the lowest (best-ranking) scores first. +static inline void SortCandidates(Candidates& candidates) { + std::stable_sort(candidates.begin(), candidates.end(), + [&](const Candidate& a, const Candidate& b) { return a.score < b.score; }); +} + +/// Prints a list of types. +static void PrintTypeList(StyledText& ss, VectorRef types) { + bool first = true; + for (auto* arg : types) { + if (!first) { + ss << ", "; + } + first = false; + ss << style::Type((arg != nullptr) ? arg->FriendlyName() : "undef"); + } +} + +/// Attempts to find a single intrinsic overload that matches the provided argument types. +/// @param context the intrinsic context +/// @param intrinsic the intrinsic being called +/// @param intrinsic_name the name of the intrinsic +/// @param template_args the template argument types +/// @param args the argument types +/// @param earliest_eval_stage the earliest evaluation stage that the call can be made +/// @param member_function `true` if the builtin should be a member function +/// @param on_no_match an error callback when no intrinsic overloads matched the provided +/// arguments. +/// @returns the matched intrinsic +Result MatchIntrinsic(Context& context, + const IntrinsicInfo& intrinsic, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage, + bool member_function, + const OnNoMatch& on_no_match); + +/// The scoring mode for ScoreOverload() +enum class ScoreMode { + /// If the overload doesn't match, then the returned Candidate will simply have a score of 1. + /// No other fields will be populated. + kEarlyReject, + /// A more expensive score calculations will be made for the overload, which can be used + /// to rank potential overloads + kFull +}; + +/// Evaluates the single overload for the provided argument types. +/// @param context the intrinsic context +/// @param overload the overload being considered +/// @param template_args the template argument types +/// @param args the argument types +/// @tparam MODE the scoring mode to use. Passed as a template argument to ensure that the +/// extremely-hot function is specialized without scoring logic for the common code path. +/// @returns the evaluated Candidate information. +template +Candidate ScoreOverload(Context& context, + const OverloadInfo& overload, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage); + +/// Performs overload resolution given the list of candidates, by ranking the conversions of +/// arguments to the each of the candidate's parameter types. +/// @param context the intrinsic context +/// @param candidates the list of candidate overloads +/// @param intrinsic_name the name of the intrinsic +/// @param template_args the template argument types +/// @param args the argument types +/// @see https://www.w3.org/TR/WGSL/#overload-resolution-section +/// @returns the resolved Candidate. +Result ResolveCandidate(Context& context, + Candidates&& candidates, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args); + +// Prints the list of candidates for emitting diagnostics +void PrintCandidates(StyledText& err, + Context& context, + VectorRef candidates, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args); + +/// Raises an ICE when no overload is a clear winner of overload resolution +StyledText ErrAmbiguousOverload(Context& context, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args, + VectorRef candidates); + +/// @return a string representing a call to a builtin with the given argument types. +StyledText CallSignature(std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args) { + StyledText out; + out << style::Code << style::Function(intrinsic_name); + if (!template_args.IsEmpty()) { + out << "<"; + PrintTypeList(out, template_args); + out << ">"; + } + out << "("; + PrintTypeList(out, args); + out << ")"; + + return out; +} + +Result MatchIntrinsic(Context& context, + const IntrinsicInfo& intrinsic, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage, + bool member_function, + const OnNoMatch& on_no_match) { + const size_t num_overloads = static_cast(intrinsic.num_overloads); + size_t num_matched = 0; + size_t match_idx = 0; + Vector candidates; + candidates.Reserve(intrinsic.num_overloads); + for (size_t overload_idx = 0; overload_idx < num_overloads; overload_idx++) { + auto& overload = context.data[intrinsic.overloads + overload_idx]; + + // Check that the overload is a member function iff we expect one. + if (overload.flags.Contains(OverloadFlag::kMemberFunction) != member_function) { + continue; + } + + auto candidate = ScoreOverload(context, overload, template_args, + args, earliest_eval_stage); + if (candidate.score == 0) { + match_idx = candidates.Length(); + num_matched++; + } + candidates.Push(std::move(candidate)); + } + + // How many candidates matched? + if (DAWN_UNLIKELY(num_matched == 0)) { + // Perform the full scoring of each overload + for (size_t overload_idx = 0; overload_idx < num_overloads; overload_idx++) { + auto& overload = context.data[intrinsic.overloads + overload_idx]; + + // Check that the overload is a member function iff we expect one. + if (overload.flags.Contains(OverloadFlag::kMemberFunction) != member_function) { + continue; + } + + candidates[overload_idx] = ScoreOverload( + context, overload, template_args, args, earliest_eval_stage); + } + // Sort the candidates with the most promising first + SortCandidates(candidates); + return on_no_match(std::move(candidates)); + } + + Candidate match; + + if (num_matched == 1) { + match = std::move(candidates[match_idx]); + } else { + TINT_CHECK_RESULT_UNWRAP(result, ResolveCandidate(context, std::move(candidates), + intrinsic_name, template_args, args)); + match = result; + } + + // Build the return type + const core::type::Type* return_type = nullptr; + if (auto* matcher_indices = context.data[match.overload->return_matcher_indices]) { + Any any; + return_type = + context.Match(match.templates, *match.overload, matcher_indices, earliest_eval_stage) + .Type(&any); + if (DAWN_UNLIKELY(!return_type)) { + StyledText err; + err << "MatchState.MatchState() returned null"; + TINT_ICE() << err.Plain(); + } + } else { + return_type = context.types.void_(); + } + + return Overload{match.overload, return_type, std::move(match.parameters), + context.data[match.overload->const_eval_fn]}; +} + +template +Candidate ScoreOverload(Context& context, + const OverloadInfo& overload, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { +#define MATCH_FAILURE(PENALTY) \ + do { \ + if constexpr (MODE == ScoreMode::kEarlyReject) { \ + return Candidate{1}; \ + } else { \ + score += PENALTY; \ + } \ + } while (false) + + // Penalty weights for overload mismatching. + // This scoring is used to order the suggested overloads in diagnostic on overload mismatch, and + // has no impact for a correct program. + // The overloads with the lowest score will be displayed first (top-most). + constexpr int kMismatchedExplicitTemplateCountPenalty = 10; + constexpr int kMismatchedParamCountPenalty = 3; + constexpr int kMismatchedParamTypePenalty = 2; + constexpr int kMismatchedExplicitTemplateTypePenalty = 1; + constexpr int kMismatchedImplicitTemplateTypePenalty = 1; + constexpr int kMismatchedImplicitTemplateNumberPenalty = 1; + + const size_t num_parameters = static_cast(overload.num_parameters); + const size_t num_arguments = static_cast(args.Length()); + + size_t score = 0; + + if (num_parameters != num_arguments) { + MATCH_FAILURE(kMismatchedParamCountPenalty * (std::max(num_parameters, num_arguments) - + std::min(num_parameters, num_arguments))); + } + + // Check that all of the template arguments provided are actually expected by the overload. + const size_t expected_templates = overload.num_explicit_templates; + const size_t provided_templates = template_args.Length(); + if (provided_templates != expected_templates) { + MATCH_FAILURE(kMismatchedExplicitTemplateCountPenalty * + (std::max(expected_templates, provided_templates) - + std::min(expected_templates, provided_templates))); + } + + TemplateState templates; + + // Check that the explicit template arguments match the constraint if specified, otherwise + // just set the template type. + auto num_tmpl_args = std::min(overload.num_explicit_templates, template_args.Length()); + for (size_t i = 0; i < num_tmpl_args; ++i) { + auto& tmpl = context.data[overload.templates + i]; + auto* type = template_args[i]; + if (auto* matcher_indices = context.data[tmpl.matcher_indices]) { + // Ensure type matches the template's matcher. + type = + context.Match(templates, overload, matcher_indices, earliest_eval_stage).Type(type); + if (!type) { + MATCH_FAILURE(kMismatchedExplicitTemplateTypePenalty); + continue; + } + } + templates.SetType(i, type); + } + + // Invoke the matchers for each parameter <-> argument pair. + // If any arguments cannot be matched, then `score` will be increased. + // If the overload has any template types or numbers then these will be set based on the + // argument types. Template types may be refined by constraining with later argument types. For + // example calling `F(T, T)` with the argument types (abstract-int, i32) will first set T to + // abstract-int when matching the first argument, and then constrained down to i32 when matching + // the second argument. + // Note that inferred template types are not tested against their matchers at this point. + auto num_params = std::min(num_parameters, num_arguments); + for (size_t p = 0; p < num_params; p++) { + auto& parameter = context.data[overload.parameters + p]; + auto* matcher_indices = context.data[parameter.matcher_indices]; + if (!context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .Type(args[p])) { + MATCH_FAILURE(kMismatchedParamTypePenalty); + } + } + + // Check each of the inferred types and numbers for the implicit templates match their + // respective matcher. + for (size_t i = overload.num_explicit_templates; i < overload.num_templates; i++) { + auto& tmpl = context.data[overload.templates + i]; + auto* matcher_indices = context.data[tmpl.matcher_indices]; + if (!matcher_indices) { + continue; + } + + auto matcher = context.Match(templates, overload, matcher_indices, earliest_eval_stage); + + switch (tmpl.kind) { + case TemplateInfo::Kind::kType: { + // Check all constrained template types matched their constraint matchers. + // If the template type *does not* match any of the types in the constraint + // matcher, then `score` is incremented and the template is assigned an invalid + // type. If the template type *does* match a type, then the template type is + // replaced with the first matching type. The order of types in the template matcher + // is important here, which can be controlled with the [[precedence(N)]] decorations + // on the types in the def file. + if (auto* type = templates.Type(i)) { + if (auto* ty = matcher.Type(type)) { + // Template type matched one of the types in the template type's + // matcher. Replace the template type with this type. + templates.SetType(i, ty); + continue; + } + } + templates.SetType(i, context.types.invalid()); + MATCH_FAILURE(kMismatchedImplicitTemplateTypePenalty); + break; + } + + case TemplateInfo::Kind::kNumber: { + // Checking that the inferred number matches the constraints on the + // template. Increments `score` and assigns the template an invalid number if the + // template numbers do not match their constraint matchers. + auto number = templates.Num(i); + if (!number.IsValid() || !matcher.Num(number).IsValid()) { + templates.SetNum(i, Number::invalid); + MATCH_FAILURE(kMismatchedImplicitTemplateNumberPenalty); + } + } + } + } + + // Now that all the template types have been finalized, we can construct the parameters. + Vector parameters; + parameters.Reserve(num_params); + for (size_t p = 0; p < num_params; p++) { + auto& parameter = context.data[overload.parameters + p]; + auto* matcher_indices = context.data[parameter.matcher_indices]; + auto* ty = + context.Match(templates, overload, matcher_indices, earliest_eval_stage).Type(args[p]); + parameters.Emplace(ty, parameter.usage); + } + + return Candidate{score, &overload, templates, parameters}; +#undef MATCH_FAILURE +} + +Result ResolveCandidate(Context& context, + Candidates&& candidates, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args) { + Vector best_ranks; + best_ranks.Resize(args.Length(), 0xffffffff); + size_t num_matched = 0; + Candidate* best = nullptr; + for (auto& candidate : candidates) { + if (candidate.score > 0) { + continue; // Candidate has already been ruled out. + } + bool some_won = false; // An argument ranked less than the 'best' overload's argument + bool some_lost = false; // An argument ranked more than the 'best' overload's argument + for (size_t i = 0; i < args.Length(); i++) { + auto rank = core::type::Type::ConversionRank(args[i], candidate.parameters[i].type); + if (best_ranks[i] > rank) { + best_ranks[i] = rank; + some_won = true; + } else if (best_ranks[i] < rank) { + some_lost = true; + } + } + // If no arguments of this candidate ranked worse than the previous best candidate, then + // this candidate becomes the new best candidate. + // If no arguments of this candidate ranked better than the previous best candidate, then + // this candidate is removed from the list of matches. + // If neither of the above apply, then we have two candidates with no clear winner, which + // results in an ambiguous overload error. In this situation the loop ends with + // `num_matched > 1`. + if (some_won) { + // One or more arguments of this candidate ranked better than the previous best + // candidate's argument(s). + num_matched++; + if (!some_lost) { + // All arguments were at as-good or better than the previous best. + if (best) { + // Mark the previous best candidate as no longer being in the running, by + // setting its score to a non-zero value. We pick 1 as this is the closest to 0 + // (match) as we can get. + best->score = 1; + num_matched--; + } + // This candidate is the new best. + best = &candidate; + } + } else { + // No arguments ranked better than the current best. + // Change the score of this candidate to a non-zero value, so that it's not considered a + // match. + candidate.score = 1; + } + } + + if (num_matched > 1) { + // Re-sort the candidates with the most promising first + SortCandidates(candidates); + // Raise an error + return ErrAmbiguousOverload(context, intrinsic_name, template_args, args, candidates); + } + + return std::move(*best); +} + +void PrintCandidates(StyledText& ss, + Context& context, + VectorRef candidates, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args) { + for (auto& candidate : candidates) { + ss << " • "; + PrintCandidate(ss, context, candidate, intrinsic_name, template_args, args); + ss << "\n"; + } +} + +StyledText ErrAmbiguousOverload(Context& context, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args, + VectorRef candidates) { + StyledText err; + err << "ambiguous overload while attempting to match " + << CallSignature(intrinsic_name, template_args, args) << "\n"; + + for (auto& candidate : candidates) { + if (candidate.score == 0) { + err << " "; + PrintCandidate(err, context, candidate, intrinsic_name, template_args, args); + err << "\n"; + } + } + TINT_ICE() << err.Plain(); +} + +} // namespace + +void PrintCandidate(StyledText& ss, + Context& context, + const Candidate& candidate, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args) { + // Restore old style before returning. + auto prev_style = ss.Style(); + TINT_DEFER(ss << prev_style); + + auto& overload = *candidate.overload; + + TemplateState templates = candidate.templates; + + // TODO(crbug.com/tint/1730): Use input evaluation stage to output only relevant overloads. + auto earliest_eval_stage = EvaluationStage::kConstant; + + ss << style::Code << style::Function(intrinsic_name); + + if (overload.num_explicit_templates > 0) { + ss << "<"; + for (size_t i = 0; i < overload.num_explicit_templates; i++) { + const auto& tmpl = context.data[overload.templates + i]; + + bool matched = false; + if (i < template_args.Length()) { + auto* matcher_indices = context.data[tmpl.matcher_indices]; + matched = (matcher_indices == nullptr) || + (context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .Type(template_args[i]) != nullptr); + } + + if (i > 0) { + ss << ", "; + } + ss << style::Type(tmpl.name) << " "; + if (matched) { + ss << (style::Code + style::Match)(" ✓ "); + } else { + ss << (style::Code + style::Mismatch)(" ✗ "); + } + } + ss << ">"; + } + + bool all_params_match = true; + ss << "("; + for (size_t i = 0; i < overload.num_parameters; i++) { + const auto& parameter = context.data[overload.parameters + i]; + auto* matcher_indices = context.data[parameter.matcher_indices]; + + bool matched = false; + if (i < args.Length()) { + matched = (context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .Type(args[i]) != nullptr); + } + all_params_match = all_params_match && matched; + + if (i > 0) { + ss << ", "; + } + + if (parameter.usage != ParameterUsage::kNone) { + ss << style::Variable(parameter.usage, ": "); + } + context.Match(templates, overload, matcher_indices, earliest_eval_stage).PrintType(ss); + + ss << style::Code << " "; + if (matched) { + ss << (style::Code + style::Match)(" ✓ "); + } else { + ss << (style::Code + style::Mismatch)(" ✗ "); + } + } + ss << ")"; + if (overload.return_matcher_indices.IsValid()) { + ss << " -> "; + auto* matcher_indices = context.data[overload.return_matcher_indices]; + context.Match(templates, overload, matcher_indices, earliest_eval_stage).PrintType(ss); + } + + bool first = true; + auto separator = [&] { + ss << style::Plain(first ? " where:\n " : "\n "); + first = false; + }; + + if (all_params_match && args.Length() > overload.num_parameters) { + separator(); + ss << style::Mismatch(" ✗ ") + << style::Plain(" overload expects ", static_cast(overload.num_parameters), + " argument", overload.num_parameters != 1 ? "s" : "", ", call passed ", + args.Length(), " argument", args.Length() != 1 ? "s" : ""); + } + if (all_params_match && template_args.Length() > overload.num_explicit_templates) { + separator(); + ss << style::Mismatch(" ✗ ") + << style::Plain(" overload expects ", static_cast(overload.num_explicit_templates), + " template argument", overload.num_explicit_templates != 1 ? "s" : "", + ", call passed ", template_args.Length(), " argument", + template_args.Length() != 1 ? "s" : ""); + } + + for (size_t i = 0; i < overload.num_templates; i++) { + auto& tmpl = context.data[overload.templates + i]; + if (auto* matcher_indices = context.data[tmpl.matcher_indices]) { + separator(); + bool matched = false; + if (tmpl.kind == TemplateInfo::Kind::kType) { + if (auto* ty = templates.Type(i)) { + matched = + (context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .Type(ty) != nullptr); + } + } else { + matched = context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .Num(templates.Num(i)) + .IsValid(); + } + if (matched) { + ss << style::Match(" ✓ ") << style::Plain(" "); + } else { + ss << style::Mismatch(" ✗ ") << style::Plain(" "); + } + + ss << style::Type(tmpl.name) << style::Plain(" is "); + if (tmpl.kind == TemplateInfo::Kind::kType) { + context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .PrintType(ss); + } else { + context.Match(templates, overload, matcher_indices, earliest_eval_stage) + .PrintNum(ss); + } + } + } +} + +Result LookupFn(Context& context, + std::string_view intrinsic_name, + size_t function_id, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { + // Generates an error when no overloads match the provided arguments + auto on_no_match = [&](VectorRef candidates) { + StyledText err; + err << "no matching call to " << CallSignature(intrinsic_name, template_args, args) << "\n"; + if (!candidates.IsEmpty()) { + err << "\n" + << candidates.Length() << " candidate function" + << (candidates.Length() > 1 ? "s:" : ":") << "\n"; + PrintCandidates(err, context, candidates, intrinsic_name, template_args, args); + } + return err; + }; + + // Resolve the intrinsic overload + return MatchIntrinsic(context, context.data.builtins[function_id], intrinsic_name, + template_args, args, earliest_eval_stage, /* member_function */ false, + on_no_match); +} + +Result LookupMemberFn(Context& context, + std::string_view intrinsic_name, + size_t function_id, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { + // Generates an error when no overloads match the provided arguments + auto on_no_match = [&](VectorRef candidates) { + StyledText err; + err << "no matching call to " << CallSignature(intrinsic_name, template_args, args) << "\n"; + if (!candidates.IsEmpty()) { + err << "\n" + << candidates.Length() << " candidate function" + << (candidates.Length() > 1 ? "s:" : ":") << "\n"; + PrintCandidates(err, context, candidates, intrinsic_name, template_args, args); + } + return err; + }; + + // Resolve the intrinsic overload + return MatchIntrinsic(context, context.data.builtins[function_id], intrinsic_name, + template_args, args, earliest_eval_stage, /* member_function */ true, + on_no_match); +} + +Result LookupUnary(Context& context, + core::UnaryOp op, + const core::type::Type* arg, + EvaluationStage earliest_eval_stage) { + const IntrinsicInfo* intrinsic_info = nullptr; + std::string_view intrinsic_name; + switch (op) { + case core::UnaryOp::kComplement: + intrinsic_info = &context.data.unary_complement; + intrinsic_name = "operator ~ "; + break; + case core::UnaryOp::kNegation: + intrinsic_info = &context.data.unary_minus; + intrinsic_name = "operator - "; + break; + case core::UnaryOp::kAddressOf: + intrinsic_info = &context.data.unary_and; + intrinsic_name = "operator & "; + break; + case core::UnaryOp::kIndirection: + intrinsic_info = &context.data.unary_star; + intrinsic_name = "operator * "; + break; + case core::UnaryOp::kNot: + intrinsic_info = &context.data.unary_not; + intrinsic_name = "operator ! "; + break; + } + + Vector args{arg}; + + // Generates an error when no overloads match the provided arguments + auto on_no_match = [&, name = intrinsic_name](VectorRef candidates) { + StyledText err; + err << "no matching overload for " << CallSignature(name, Empty, args) << "\n"; + if (!candidates.IsEmpty()) { + err << "\n" + << candidates.Length() << " candidate operator" + << (candidates.Length() > 1 ? "s:" : ":") << "\n"; + PrintCandidates(err, context, candidates, name, Empty, Vector{arg}); + } + return err; + }; + + // Resolve the intrinsic overload + return MatchIntrinsic(context, *intrinsic_info, intrinsic_name, Empty, args, + earliest_eval_stage, /* member_function */ false, on_no_match); +} + +Result LookupBinary(Context& context, + core::BinaryOp op, + const core::type::Type* lhs, + const core::type::Type* rhs, + EvaluationStage earliest_eval_stage, + bool is_compound) { + const IntrinsicInfo* intrinsic_info = nullptr; + std::string_view intrinsic_name; + switch (op) { + case core::BinaryOp::kAnd: + intrinsic_info = &context.data.binary_and; + intrinsic_name = is_compound ? "operator &= " : "operator & "; + break; + case core::BinaryOp::kOr: + intrinsic_info = &context.data.binary_or; + intrinsic_name = is_compound ? "operator |= " : "operator | "; + break; + case core::BinaryOp::kXor: + intrinsic_info = &context.data.binary_xor; + intrinsic_name = is_compound ? "operator ^= " : "operator ^ "; + break; + case core::BinaryOp::kLogicalAnd: + intrinsic_info = &context.data.binary_logical_and; + intrinsic_name = "operator && "; + break; + case core::BinaryOp::kLogicalOr: + intrinsic_info = &context.data.binary_logical_or; + intrinsic_name = "operator || "; + break; + case core::BinaryOp::kEqual: + intrinsic_info = &context.data.binary_equal; + intrinsic_name = "operator == "; + break; + case core::BinaryOp::kNotEqual: + intrinsic_info = &context.data.binary_not_equal; + intrinsic_name = "operator != "; + break; + case core::BinaryOp::kLessThan: + intrinsic_info = &context.data.binary_less_than; + intrinsic_name = "operator < "; + break; + case core::BinaryOp::kGreaterThan: + intrinsic_info = &context.data.binary_greater_than; + intrinsic_name = "operator > "; + break; + case core::BinaryOp::kLessThanEqual: + intrinsic_info = &context.data.binary_less_than_equal; + intrinsic_name = "operator <= "; + break; + case core::BinaryOp::kGreaterThanEqual: + intrinsic_info = &context.data.binary_greater_than_equal; + intrinsic_name = "operator >= "; + break; + case core::BinaryOp::kShiftLeft: + intrinsic_info = &context.data.binary_shift_left; + intrinsic_name = is_compound ? "operator <<= " : "operator << "; + break; + case core::BinaryOp::kShiftRight: + intrinsic_info = &context.data.binary_shift_right; + intrinsic_name = is_compound ? "operator >>= " : "operator >> "; + break; + case core::BinaryOp::kAdd: + intrinsic_info = &context.data.binary_plus; + intrinsic_name = is_compound ? "operator += " : "operator + "; + break; + case core::BinaryOp::kSubtract: + intrinsic_info = &context.data.binary_minus; + intrinsic_name = is_compound ? "operator -= " : "operator - "; + break; + case core::BinaryOp::kMultiply: + intrinsic_info = &context.data.binary_star; + intrinsic_name = is_compound ? "operator *= " : "operator * "; + break; + case core::BinaryOp::kDivide: + intrinsic_info = &context.data.binary_divide; + intrinsic_name = is_compound ? "operator /= " : "operator / "; + break; + case core::BinaryOp::kModulo: + intrinsic_info = &context.data.binary_modulo; + intrinsic_name = is_compound ? "operator %= " : "operator % "; + break; + } + + Vector args{lhs, rhs}; + + // Generates an error when no overloads match the provided arguments + auto on_no_match = [&, name = intrinsic_name](VectorRef candidates) { + StyledText err; + err << "no matching overload for " << CallSignature(name, Empty, args) << "\n"; + if (!candidates.IsEmpty()) { + err << "\n" + << candidates.Length() << " candidate operator" + << (candidates.Length() > 1 ? "s:" : ":") << "\n"; + PrintCandidates(err, context, candidates, name, Empty, args); + } + return err; + }; + + // Resolve the intrinsic overload + return MatchIntrinsic(context, *intrinsic_info, intrinsic_name, Empty, args, + earliest_eval_stage, /* member_function */ false, on_no_match); +} + +Result LookupCtorConv(Context& context, + std::string_view type_name, + size_t type_id, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { + // Generates an error when no overloads match the provided arguments + auto on_no_match = [&](VectorRef candidates) { + StyledText err; + err << "no matching constructor for " << CallSignature(type_name, template_args, args) + << "\n"; + Candidates ctor, conv; + for (auto candidate : candidates) { + if (candidate.overload->flags.Contains(OverloadFlag::kIsConstructor)) { + ctor.Push(candidate); + } else { + conv.Push(candidate); + } + } + if (!ctor.IsEmpty()) { + err << "\n" + << ctor.Length() << " candidate constructor" << (ctor.Length() > 1 ? "s:" : ":") + << "\n"; + PrintCandidates(err, context, ctor, type_name, template_args, args); + } + if (!conv.IsEmpty()) { + err << "\n" + << conv.Length() << " candidate conversion" << (conv.Length() > 1 ? "s:" : ":") + << "\n"; + PrintCandidates(err, context, conv, type_name, template_args, args); + } + return err; + }; + + // Resolve the intrinsic overload + return MatchIntrinsic(context, context.data.ctor_conv[type_id], type_name, template_args, args, + earliest_eval_stage, /* member_function */ false, on_no_match); +} + +} // namespace tint::core::intrinsic + +/// TypeInfo for the Any type declared in the anonymous namespace above +TINT_INSTANTIATE_TYPEINFO(tint::core::intrinsic::Any); diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/table.h b/3rdparty/dawn/src/tint/lang/core/intrinsic/table.h new file mode 100644 index 000000000..6f950f11e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/table.h @@ -0,0 +1,401 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_INTRINSIC_TABLE_H_ +#define SRC_TINT_LANG_CORE_INTRINSIC_TABLE_H_ + +#include +#include +#include + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/evaluation_stage.h" +#include "src/tint/lang/core/intrinsic/ctor_conv.h" +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/unary_op.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/styled_text.h" + +// Forward declarations +namespace tint::diag { +class List; +} // namespace tint::diag + +namespace tint::core::intrinsic { + +/// Overload describes a fully matched builtin function overload +struct Overload { + static constexpr size_t kNumFixedParameters = 8; + + /// Parameter describes a single parameter + struct Parameter { + /// Parameter type + const core::type::Type* const type; + /// Parameter usage + core::ParameterUsage const usage = core::ParameterUsage::kNone; + + /// Equality operator + /// @param other the parameter to compare against + /// @returns true if this parameter and @p other are the same + bool operator==(const Parameter& other) const { + return type == other.type && usage == other.usage; + } + + /// Inequality operator + /// @param other the parameter to compare against + /// @returns false if this parameter and @p other are the same + bool operator!=(const Parameter& other) const { return !(*this == other); } + }; + + /// The overload information + const OverloadInfo* info = nullptr; + + /// The resolved overload return type + core::type::Type const* return_type = nullptr; + + /// The resolved overload parameters + Vector parameters; + + /// The constant evaluation function + constant::Eval::Function const_eval_fn = nullptr; + + /// Equality operator + /// @param other the overload to compare against + /// @returns true if this overload and @p other are the same + bool operator==(const Overload& other) const { + return info == other.info && return_type == other.return_type && + parameters == other.parameters; + } + + /// Inequality operator + /// @param other the overload to compare against + /// @returns false if this overload and @p other are the same + bool operator!=(const Overload& other) const { return !(*this == other); } +}; + +/// The context data used to lookup intrinsic information +struct Context { + /// The table table + const TableData& data; + /// The type manager + core::type::Manager& types; + /// The symbol table + SymbolTable& symbols; + + /// @returns a MatchState from the context and arguments. + /// @param templates the template state used for matcher evaluation + /// @param overload the overload being evaluated + /// @param matcher_indices pointer to a list of matcher indices + MatchState Match(TemplateState& templates, + const OverloadInfo& overload, + const MatcherIndex* matcher_indices, + EvaluationStage earliest_eval_stage) { + return MatchState(types, symbols, templates, data, overload, matcher_indices, + earliest_eval_stage); + } +}; + +/// Candidate holds information about an overload evaluated for resolution. +struct Candidate { + /// The match-score of the candidate overload. + /// A score of zero indicates an exact match. + /// Non-zero scores are used for diagnostics when no overload matches. + /// Lower scores are displayed first (top-most). + size_t score = 0; + /// The candidate overload + const OverloadInfo* overload = nullptr; + /// The template types and numbers + TemplateState templates{}; + /// The parameter types for the candidate overload + Vector parameters{}; +}; + +// Prints the candidate overload for emitting diagnostics +void PrintCandidate(StyledText& ss, + Context& context, + const Candidate& candidate, + std::string_view intrinsic_name, + VectorRef template_args, + VectorRef args); + +/// Lookup looks for the builtin overload with the given signature, raising an error diagnostic +/// if the builtin was not found. +/// @param context the intrinsic context +/// @param function_name the name of the function +/// @param function_id the function identifier +/// @param template_args the optional template arguments +/// @param args the argument types passed to the builtin function +/// @param earliest_eval_stage the earliest evaluation stage that a call to +/// the builtin can be made. This can alter the overloads considered. +/// For example, if the earliest evaluation stage is `EvaluationStage::kRuntime`, then +/// only overloads with concrete argument types will be considered, as all +/// abstract-numerics will have been materialized after shader creation time +/// (EvaluationStage::kConstant). +/// @return the resolved builtin function overload +Result LookupFn(Context& context, + std::string_view function_name, + size_t function_id, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage); + +/// Lookup looks for the member builtin overload with the given signature, raising an error +/// diagnostic if the builtin was not found. +/// @param context the intrinsic context +/// @param function_name the name of the function +/// @param function_id the function identifier +/// @param template_args the optional template arguments +/// @param args the argument types passed to the builtin function +/// @param earliest_eval_stage the earliest evaluation stage that a call to +/// the builtin can be made. This can alter the overloads considered. +/// For example, if the earliest evaluation stage is `EvaluationStage::kRuntime`, then +/// only overloads with concrete argument types will be considered, as all +/// abstract-numerics will have been materialized after shader creation time +/// (EvaluationStage::kConstant). +/// @return the resolved builtin function overload +Result LookupMemberFn(Context& context, + std::string_view function_name, + size_t function_id, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage); + +/// Lookup looks for the unary op overload with the given signature, raising an error +/// diagnostic if the operator was not found. +/// @param context the intrinsic context +/// @param op the unary operator +/// @param arg the type of the expression passed to the operator +/// @param earliest_eval_stage the earliest evaluation stage that a call to +/// the unary operator can be made. This can alter the overloads considered. +/// For example, if the earliest evaluation stage is +/// `EvaluationStage::kRuntime`, then only overloads with concrete argument types +/// will be considered, as all abstract-numerics will have been materialized +/// after shader creation time (EvaluationStage::kConstant). +/// @return the resolved unary operator overload +Result LookupUnary(Context& context, + core::UnaryOp op, + const core::type::Type* arg, + EvaluationStage earliest_eval_stage); + +/// Lookup looks for the binary op overload with the given signature, raising an error +/// diagnostic if the operator was not found. +/// @param context the intrinsic context +/// @param op the binary operator +/// @param lhs the LHS value type passed to the operator +/// @param rhs the RHS value type passed to the operator +/// @param earliest_eval_stage the earliest evaluation stage that a call to +/// the binary operator can be made. This can alter the overloads considered. +/// For example, if the earliest evaluation stage is +/// `EvaluationStage::kRuntime`, then only overloads with concrete argument types +/// will be considered, as all abstract-numerics will have been materialized +/// after shader creation time (EvaluationStage::kConstant). +/// @param is_compound true if the binary operator is being used as a compound assignment +/// @return the resolved binary operator overload +Result LookupBinary(Context& context, + core::BinaryOp op, + const core::type::Type* lhs, + const core::type::Type* rhs, + EvaluationStage earliest_eval_stage, + bool is_compound); + +/// Lookup looks for the value constructor or conversion overload for the given CtorConv. +/// @param context the intrinsic context +/// @param type_name the name of the type being constructed or converted +/// @param type_id the type identifier +/// @param template_args the optional template arguments +/// @param args the argument types passed to the constructor / conversion call +/// @param earliest_eval_stage the earliest evaluation stage that a call to +/// the constructor or conversion can be made. This can alter the overloads considered. +/// For example, if the earliest evaluation stage is +/// `EvaluationStage::kRuntime`, then only overloads with concrete argument types +/// will be considered, as all abstract-numerics will have been materialized +/// after shader creation time (EvaluationStage::kConstant). +/// @return the resolved type constructor or conversion function overload +Result LookupCtorConv(Context& context, + std::string_view type_name, + size_t type_id, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage); + +/// Table is a wrapper around a dialect to provide type-safe interface to the intrinsic table. +template +struct Table { + /// Alias to DIALECT::BuiltinFn + using BuiltinFn = typename DIALECT::BuiltinFn; + + /// Alias to DIALECT::CtorConv + using CtorConv = typename DIALECT::CtorConv; + + static_assert(std::is_enum_v); + static_assert(std::is_enum_v); + + /// @param types The type manager + /// @param symbols The symbol table + Table(core::type::Manager& types, SymbolTable& symbols) + : context{DIALECT::kData, types, symbols} {} + + /// Lookup looks for the builtin overload with the given signature, raising an error diagnostic + /// if the builtin was not found. + /// @param builtin_fn the builtin function + /// @param template_args the optional template arguments + /// @param args the argument types passed to the builtin function + /// @param earliest_eval_stage the earliest evaluation stage that a call to + /// the builtin can be made. This can alter the overloads considered. + /// For example, if the earliest evaluation stage is `EvaluationStage::kRuntime`, then + /// only overloads with concrete argument types will be considered, as all + /// abstract-numerics will have been materialized after shader creation time + /// (EvaluationStage::kConstant). + /// @return the resolved builtin function overload + Result Lookup(BuiltinFn builtin_fn, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { + std::string_view name = DIALECT::ToString(builtin_fn); + size_t id = static_cast(builtin_fn); + return LookupFn(context, name, id, std::move(template_args), std::move(args), + earliest_eval_stage); + } + + /// Lookup looks for the member builtin overload with the given signature, raising an error + /// diagnostic if the builtin was not found. + /// @param builtin_fn the builtin function + /// @param object the object type + /// @param template_args the optional template arguments + /// @param args the argument types passed to the builtin function + /// @param earliest_eval_stage the earliest evaluation stage that a call to + /// the builtin can be made. This can alter the overloads considered. + /// For example, if the earliest evaluation stage is `EvaluationStage::kRuntime`, then + /// only overloads with concrete argument types will be considered, as all + /// abstract-numerics will have been materialized after shader creation time + /// (EvaluationStage::kConstant). + /// @return the resolved builtin function overload + Result Lookup(BuiltinFn builtin_fn, + const core::type::Type* object, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { + // Push the object type into the argument list. + auto full_args = Vector({object}); + for (auto* arg : args) { + full_args.Push(arg); + } + std::string_view name = DIALECT::ToString(builtin_fn); + size_t id = static_cast(builtin_fn); + return LookupMemberFn(context, name, id, std::move(template_args), std::move(full_args), + earliest_eval_stage); + } + + /// Lookup looks for the unary op overload with the given signature, raising an error + /// diagnostic if the operator was not found. + /// @param op the unary operator + /// @param arg the type of the expression passed to the operator + /// @param earliest_eval_stage the earliest evaluation stage that a call to + /// the unary operator can be made. This can alter the overloads considered. + /// For example, if the earliest evaluation stage is + /// `EvaluationStage::kRuntime`, then only overloads with concrete argument types + /// will be considered, as all abstract-numerics will have been materialized + /// after shader creation time (EvaluationStage::kConstant). + + /// @return the resolved unary operator overload + Result Lookup(core::UnaryOp op, + const core::type::Type* arg, + EvaluationStage earliest_eval_stage) { + return LookupUnary(context, op, arg, earliest_eval_stage); + } + + /// Lookup looks for the binary op overload with the given signature, raising an error + /// diagnostic if the operator was not found. + /// @param op the binary operator + /// @param lhs the LHS value type passed to the operator + /// @param rhs the RHS value type passed to the operator + /// @param earliest_eval_stage the earliest evaluation stage that a call to + /// the binary operator can be made. This can alter the overloads considered. + /// For example, if the earliest evaluation stage is + /// `EvaluationStage::kRuntime`, then only overloads with concrete argument types + /// will be considered, as all abstract-numerics will have been materialized + /// after shader creation time (EvaluationStage::kConstant). + + /// @param is_compound true if the binary operator is being used as a compound assignment + /// @return the resolved binary operator overload + Result Lookup(core::BinaryOp op, + const core::type::Type* lhs, + const core::type::Type* rhs, + EvaluationStage earliest_eval_stage, + bool is_compound) { + return LookupBinary(context, op, lhs, rhs, earliest_eval_stage, is_compound); + } + + /// Lookup looks for the value constructor or conversion overload for the given CtorConv. + /// @param type the type being constructed or converted + /// @param template_args the optional template arguments + /// @param args the argument types passed to the constructor / conversion call + /// @param earliest_eval_stage the earliest evaluation stage that a call to + /// the constructor or conversion can be made. This can alter the overloads considered. + /// For example, if the earliest evaluation stage is + /// `EvaluationStage::kRuntime`, then only overloads with concrete argument types + /// will be considered, as all abstract-numerics will have been materialized + /// after shader creation time (EvaluationStage::kConstant). + /// @return the resolved type constructor or conversion function overload + Result Lookup(CtorConv type, + VectorRef template_args, + VectorRef args, + EvaluationStage earliest_eval_stage) { + std::string_view name = DIALECT::ToString(type); + size_t id = static_cast(type); + return LookupCtorConv(context, name, id, std::move(template_args), std::move(args), + earliest_eval_stage); + } + + /// The intrinsic context + Context context; +}; + +} // namespace tint::core::intrinsic + +namespace tint { + +/// Hasher specialization for core::intrinsic::Overload +template <> +struct Hasher { + /// @param i the core::intrinsic::Overload to create a hash for + /// @return the hash value + inline HashCode operator()(const core::intrinsic::Overload& i) const { + HashCode hash = Hash(i.parameters.Length()); + for (auto& p : i.parameters) { + hash = HashCombine(hash, p.type, p.usage); + } + return Hash(hash, i.info, i.return_type); + } +}; + +} // namespace tint + +#endif // SRC_TINT_LANG_CORE_INTRINSIC_TABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/table_data.h b/3rdparty/dawn/src/tint/lang/core/intrinsic/table_data.h new file mode 100644 index 000000000..da0d06955 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/table_data.h @@ -0,0 +1,678 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_INTRINSIC_TABLE_DATA_H_ +#define SRC_TINT_LANG_CORE_INTRINSIC_TABLE_DATA_H_ + +#include +#include +#include + +#include "src/tint/lang/core/constant/eval.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/evaluation_stage.h" +#include "src/tint/utils/containers/enum_set.h" +#include "src/tint/utils/containers/slice.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +/// Forward declaration +namespace tint::core::intrinsic { +struct TableData; +} // namespace tint::core::intrinsic + +namespace tint::core::intrinsic { + +/// An enumerator of index namespaces. +enum class TableIndexNamespace : uint8_t { + kTemplate, + kMatcher, + kMatcherIndices, + kTypeMatcher, + kNumberMatcher, + kParameter, + kOverload, + kConstEvalFunction, +}; + +/// A wrapper around an integer type, used to index intrinsic table data +/// @tparam T the index data type +/// @tparam N the index namespace +template +struct TableIndex { + static_assert(std::is_integral_v && std::is_unsigned_v, + "T must be an unsigned integer type"); + + /// The value used to represent an invalid index + static constexpr T kInvalid = std::numeric_limits::max(); + + /// Constructor for invalid index + constexpr TableIndex() : value(kInvalid) {} + + /// Constructor + /// @param index the index value + constexpr explicit TableIndex(T index) : value(index) {} + + /// @returns true if this index is not invalid + bool IsValid() const { return value != kInvalid; } + + /// Equality operator + /// @param other the index to compare against + /// @returns true if this index is equal to @p other + bool operator==(const TableIndex& other) { return value == other.value; } + + /// Inequality operator + /// @param other the index to compare against + /// @returns true if this index is equal to @p other + bool operator!=(const TableIndex& other) { return value != other.value; } + + /// @param offset the offset to apply to this index + /// @returns a new index offset by @p offset + template + auto operator+(U offset) const { + static_assert(std::is_integral_v && std::is_unsigned_v, + "T must be an unsigned integer type"); + using C = std::conditional_t<(sizeof(U) > sizeof(T)), U, T>; + C new_value = static_cast(value) + static_cast(offset); + return TableIndex(new_value); + } + + /// @param arr a C-style array + /// @returns true if the integer type `T` has enough bits to index all the + /// elements in the array @p arr. + template + static constexpr bool CanIndex(U (&arr)[COUNT]) { + (void)arr; // The array isn't actually used + /// kInvalid is the largest value representable by `T`. It is not a valid index. + return COUNT < kInvalid; + } + + /// The index value + const T value = kInvalid; +}; + +/// Index type used to index TableData::template_types +using TemplateIndex = TableIndex; + +/// Index type used to index TableData::type_matchers or TableData::number_matchers +using MatcherIndex = TableIndex; + +/// Index type used to index TableData::matcher_indices +using MatcherIndicesIndex = TableIndex; + +/// Index type used to index TableData::type_matchers +using TypeMatcherIndex = TableIndex; + +/// Index type used to index TableData::number_matchers +using NumberMatcherIndex = TableIndex; + +/// Index type used to index TableData::parameters +using ParameterIndex = TableIndex; + +/// Index type used to index TableData::overloads +using OverloadIndex = TableIndex; + +/// Index type used to index TableData::const_eval_functions +using ConstEvalFunctionIndex = TableIndex; + +/// Unique flag bits for overloads +enum class OverloadFlag : uint8_t { + kIsBuiltin, // The overload is a builtin ('fn') + kIsOperator, // The overload is an operator ('op') + kIsConstructor, // The overload is a value constructor ('ctor') + kIsConverter, // The overload is a value converter ('conv') + kSupportsVertexPipeline, // The overload can be used in vertex shaders + kSupportsFragmentPipeline, // The overload can be used in fragment shaders + kSupportsComputePipeline, // The overload can be used in compute shaders + kMustUse, // The overload cannot be called as a statement + kMemberFunction, // The overload is a member function + kIsDeprecated, // The overload is deprecated +}; + +/// An enum set of OverloadFlag, used by OperatorInfo +using OverloadFlags = tint::EnumSet; + +/// ParameterInfo describes a parameter +struct ParameterInfo { + /// The parameter usage (parameter name in definition file) + const ParameterUsage usage; + + /// Index of the matcher indices that are used to match the parameter types. + /// These indices are consumed by the matchers themselves. + const MatcherIndicesIndex matcher_indices; +}; + +/// TemplateInfo describes an template +struct TemplateInfo { + /// An enumerator of template kind + enum class Kind : uint8_t { kType, kNumber }; + + /// Name of the template type (e.g. 'T') + const char* name; + + /// Index of the type matcher indices that are used to match the template types. + /// These indices are consumed by the matchers themselves. + const MatcherIndicesIndex matcher_indices; + + /// The template kind + const Kind kind; +}; + +/// OverloadInfo describes a single function overload +struct OverloadInfo { + /// The flags for the overload + const OverloadFlags flags; + /// Total number of parameters for the overload + const uint8_t num_parameters; + /// Total number of explicit templates for the overload + const uint8_t num_explicit_templates; + /// Total number of implicit and explicit templates for the overload + const uint8_t num_templates; + /// Index of the first template in TableData::templates + /// This is a list of explicit template types followed by the implicit template types. + const TemplateIndex templates; + /// Index of the first parameter in TableData::parameters + const ParameterIndex parameters; + /// Index of a list of type matcher indices that are used to build the return type. + const MatcherIndicesIndex return_matcher_indices; + /// The function used to evaluate the overload at shader-creation time. + const ConstEvalFunctionIndex const_eval_fn; +}; + +/// IntrinsicInfo describes a builtin function or operator overload +struct IntrinsicInfo { + /// Number of overloads of the intrinsic + const uint8_t num_overloads; + /// Index of the first overload for the function + const OverloadIndex overloads; +}; + +/// A IntrinsicInfo with no overloads +static constexpr IntrinsicInfo kNoOverloads{0, OverloadIndex(OverloadIndex::kInvalid)}; + +/// Number is an 32 bit unsigned integer, which can be in one of three states: +/// * Invalid - Number has not been assigned a value +/// * Valid - a fixed integer value +/// * Any - matches any other non-invalid number +class Number { + enum State : uint8_t { + kInvalid, + kValid, + kAny, + }; + + constexpr explicit Number(State state) : state_(state) {} + + public: + /// A special number representing any number + static const Number any; + /// An invalid number + static const Number invalid; + + /// Constructed as a valid number with the value v + /// @param v the value for the number + explicit constexpr Number(uint32_t v) : value_(v), state_(kValid) {} + + /// @returns the value of the number + inline uint32_t Value() const { return value_; } + + /// @returns the true if the number is valid + inline bool IsValid() const { return state_ == kValid; } + + /// @returns the true if the number is any + inline bool IsAny() const { return state_ == kAny; } + + /// Assignment operator. + /// The number becomes valid, with the value n + /// @param n the new value for the number + /// @returns this so calls can be chained + inline Number& operator=(uint32_t n) { + value_ = n; + state_ = kValid; + return *this; + } + + private: + uint32_t value_ = 0; + State state_ = kInvalid; +}; + +/// A special type that matches all TypeMatchers +class Any final : public Castable { + public: + Any(); + ~Any() override; + + /// @copydoc core::type::UniqueNode::Equals + bool Equals(const core::type::UniqueNode& other) const override; + /// @copydoc core::type::Type::FriendlyName + std::string FriendlyName() const override; + /// @copydoc core::type::Type::Clone + core::type::Type* Clone(core::type::CloneContext& ctx) const override; +}; + +/// TemplateState holds the state of the template numbers and types. +/// Used by the MatchState. +class TemplateState { + public: + /// If the template type with index @p idx is undefined, then it is defined with the @p ty + /// and Type() returns @p ty. If the template type is defined, and @p ty can be converted to + /// the template type then the template type is returned. If the template type is defined, + /// and the template type can be converted to @p ty, then the template type is replaced with + /// @p ty, and @p ty is returned. If none of the above applies, then @p ty is a type + /// mismatch for the template type, and nullptr is returned. + /// @param idx the index of the template type + /// @param ty the type + /// @returns true on match or newly defined + const core::type::Type* Type(size_t idx, const core::type::Type* ty) { + if (idx >= types_.Length()) { + types_.Resize(idx + 1); + } + auto& t = types_[idx]; + if (t == nullptr) { + t = ty; + return ty; + } + ty = core::type::Type::Common(Vector{t, ty}); + if (ty) { + t = ty; + } + return ty; + } + + /// If the number with index @p idx is undefined, then it is defined with the number + /// `number` and Num() returns true. If the number is defined, then `Num()` returns true iff + /// it is equal to @p ty. + /// @param idx the index of the template number + /// @param number the number + /// @returns true on match or newly defined + bool Num(size_t idx, Number number) { + if (idx >= numbers_.Length()) { + numbers_.Resize(idx + 1, Number::any); + } + auto& n = numbers_[idx]; + if (n.IsAny()) { + n = number.Value(); + return true; + } + return n.Value() == number.Value(); + } + + /// @param idx the index of the template type + /// @returns the template type with index @p idx, or nullptr if the type was not + /// defined. + const core::type::Type* Type(size_t idx) const { + if (idx >= types_.Length()) { + return nullptr; + } + return types_[idx]; + } + + /// SetType replaces the template type with index @p idx with type @p ty. + /// @param idx the index of the template type + /// @param ty the new type for the template + void SetType(size_t idx, const core::type::Type* ty) { + if (idx >= types_.Length()) { + types_.Resize(idx + 1); + } + types_[idx] = ty; + } + + /// @returns the number type with index @p idx. + /// @param idx the index of the template number + Number Num(size_t idx) const { + if (idx >= numbers_.Length()) { + return Number::invalid; + } + return numbers_[idx]; + } + + /// SetNum replaces the template number with index @p idx with number @p num. + /// @param idx the index of the template number + /// @param num the new number for the template + void SetNum(size_t idx, Number num) { + if (idx >= numbers_.Length()) { + numbers_.Resize(idx + 1, Number::any); + } + numbers_[idx] = num; + } + + /// @return the total number of type and number templates + size_t Count() const { return types_.Length() + numbers_.Length(); } + + private: + Vector types_; + Vector numbers_; +}; + +/// The current overload match state +/// MatchState holds the state used to match an overload. +class MatchState { + public: + /// Constructor + /// @param ty_mgr the type manager + /// @param syms the symbol table + /// @param t the template state + /// @param d the table data + /// @param o the current overload + /// @param matcher_indices the remaining matcher indices + /// @param s the required evaluation stage of the overload + MatchState(core::type::Manager& ty_mgr, + SymbolTable& syms, + TemplateState& t, + const TableData& d, + const OverloadInfo& o, + const MatcherIndex* matcher_indices, + EvaluationStage s) + : types(ty_mgr), + symbols(syms), + templates(t), + data(d), + overload(o), + earliest_eval_stage(s), + matcher_indices_(matcher_indices) {} + + /// The type manager + core::type::Manager& types; + + /// The symbol manager + SymbolTable& symbols; + + /// The template types and numbers + TemplateState& templates; + + /// The table data + const TableData& data; + + /// The current overload being evaluated + const OverloadInfo& overload; + + /// The earliest evaluation stage of the builtin call + EvaluationStage earliest_eval_stage; + + /// Type uses the next TypeMatcher from the matcher indices to match the type @p ty. + /// @param ty the type to try matching + /// @returns the canonical expected type if the type matches, otherwise nullptr. + /// @note: The matcher indices are progressed on calling. + inline const core::type::Type* Type(const core::type::Type* ty); + + /// Num uses the next NumMatcher from the matcher indices to match @p number. + /// @param number the number to try matching + /// @returns the canonical expected number if the number matches, otherwise an invalid + /// number. + /// @note: The matcher indices are progressed on calling. + inline Number Num(Number number); + + /// Prints the type matcher representation to @p out + /// @note: The matcher indices are progressed on calling. + inline void PrintType(StyledText& out); + + /// Prints the number matcher representation to @p out + /// @note: The matcher indices are progressed on calling. + inline void PrintNum(StyledText& out); + + private: + const MatcherIndex* matcher_indices_ = nullptr; +}; + +/// A TypeMatcher is the interface used to match an type used as part of an +/// overload's parameter or return type. +struct TypeMatcher { + /// Checks whether the given type matches the matcher rules, and returns the + /// expected, canonicalized type on success. + /// Match may define and refine the template types and numbers in state. + /// The parameter `type` is the type to match + /// Returns the canonicalized type on match, otherwise nullptr + using MatchFn = const core::type::Type*(MatchState& state, const core::type::Type* type); + + /// @see #MatchFn + MatchFn* const match; + + /// Prints the representation of the matcher. + /// Used for printing error messages when no overload is found. + using PrintFn = void(MatchState* state, StyledText& out); + + /// @see #PrintFn + PrintFn* const print; +}; + +/// A NumberMatcher is the interface used to match a number or enumerator used +/// as part of an overload's parameter or return type. +struct NumberMatcher { + /// Checks whether the given number matches the matcher rules. + /// Match may define template numbers in state. + /// The parameter `number` is the number to match + /// Returns true if the argument type is as expected. + using MatchFn = Number(MatchState& state, Number number); + + /// @see #MatchFn + MatchFn* const match; + + /// Prints the representation of the matcher. + /// Used for printing error messages when no overload is found. + using PrintFn = void(MatchState* state, StyledText& out); + + /// @see #PrintFn + PrintFn* const print; +}; + +/// TableData holds the immutable data that holds the intrinsic data for a language. +struct TableData { + /// @param idx the index of the TemplateInfo in the table data + /// @returns the TemplateInfo with the given index + template + const TemplateInfo& operator[](TableIndex idx) const { + return templates[idx.value]; + } + + /// @param idx the index of the MatcherIndices in the table data + /// @returns the MatcherIndices with the given index + template + const MatcherIndex* operator[](TableIndex idx) const { + if (idx.IsValid()) { + return &matcher_indices[idx.value]; + } + return nullptr; + } + + /// @param idx the index of the TypeMatcher in the table data + /// @returns the TypeMatcher with the given index + template + const TypeMatcher& operator[](TableIndex idx) const { + return type_matchers[idx.value]; + } + + /// @param idx the index of the NumberMatcher in the table data + /// @returns the NumberMatcher with the given index + template + const NumberMatcher& operator[](TableIndex idx) const { + return number_matchers[idx.value]; + } + + /// @param idx the index of the ParameterInfo in the table data + /// @returns the ParameterInfo with the given index + template + const ParameterInfo& operator[](TableIndex idx) const { + return parameters[idx.value]; + } + + /// @param idx the index of the OverloadInfo in the table data + /// @returns the OverloadInfo with the given index + template + const OverloadInfo& operator[](TableIndex idx) const { + return overloads[idx.value]; + } + + /// @param idx the index of the constant::Eval::Function in the table data + /// @returns the constant::Eval::Function with the given index + template + constant::Eval::Function operator[]( + TableIndex idx) const { + return idx.IsValid() ? const_eval_functions[idx.value] : nullptr; + } + + /// The list of templates used by the intrinsic overloads + const Slice templates; + /// The list of type matcher indices + const Slice matcher_indices; + /// The list of type matchers used by the intrinsic overloads + const Slice type_matchers; + /// The list of number matchers used by the intrinsic overloads + const Slice number_matchers; + /// The list of parameters used by the intrinsic overloads + const Slice parameters; + /// The list of overloads used by the intrinsics + const Slice overloads; + /// The list of constant evaluation functions used by the intrinsics + const Slice const_eval_functions; + /// The type constructor and convertor intrinsics + const Slice ctor_conv; + /// The builtin function intrinsic + const Slice builtins; + /// The IntrinsicInfo for the binary operator 'plus' + const IntrinsicInfo& binary_plus; + /// The IntrinsicInfo for the binary operator 'minus' + const IntrinsicInfo& binary_minus; + /// The IntrinsicInfo for the binary operator 'star' + const IntrinsicInfo& binary_star; + /// The IntrinsicInfo for the binary operator 'divide' + const IntrinsicInfo& binary_divide; + /// The IntrinsicInfo for the binary operator 'modulo' + const IntrinsicInfo& binary_modulo; + /// The IntrinsicInfo for the binary operator 'xor' + const IntrinsicInfo& binary_xor; + /// The IntrinsicInfo for the binary operator 'and' + const IntrinsicInfo& binary_and; + /// The IntrinsicInfo for the binary operator 'or' + const IntrinsicInfo& binary_or; + /// The IntrinsicInfo for the binary operator 'logical_and' + const IntrinsicInfo& binary_logical_and; + /// The IntrinsicInfo for the binary operator 'logical_or' + const IntrinsicInfo& binary_logical_or; + /// The IntrinsicInfo for the binary operator 'equal' + const IntrinsicInfo& binary_equal; + /// The IntrinsicInfo for the binary operator 'not_equal' + const IntrinsicInfo& binary_not_equal; + /// The IntrinsicInfo for the binary operator 'less_than' + const IntrinsicInfo& binary_less_than; + /// The IntrinsicInfo for the binary operator 'greater_than' + const IntrinsicInfo& binary_greater_than; + /// The IntrinsicInfo for the binary operator 'less_than_equal' + const IntrinsicInfo& binary_less_than_equal; + /// The IntrinsicInfo for the binary operator 'greater_than_equal' + const IntrinsicInfo& binary_greater_than_equal; + /// The IntrinsicInfo for the binary operator 'shift_left' + const IntrinsicInfo& binary_shift_left; + /// The IntrinsicInfo for the binary operator 'shift_right' + const IntrinsicInfo& binary_shift_right; + /// The IntrinsicInfo for the unary operator 'not' + const IntrinsicInfo& unary_not; + /// The IntrinsicInfo for the unary operator 'complement' + const IntrinsicInfo& unary_complement; + /// The IntrinsicInfo for the unary operator 'minus' + const IntrinsicInfo& unary_minus; + /// The IntrinsicInfo for the unary operator 'star' + const IntrinsicInfo& unary_star; + /// The IntrinsicInfo for the unary operator 'and' + const IntrinsicInfo& unary_and; +}; + +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +const core::type::Type* MatchState::Type(const core::type::Type* ty) { + TypeMatcherIndex matcher_index{(*matcher_indices_++).value}; + auto& matcher = data[matcher_index]; + return matcher.match(*this, ty); +} + +Number MatchState::Num(Number number) { + NumberMatcherIndex matcher_index{(*matcher_indices_++).value}; + auto& matcher = data[matcher_index]; + return matcher.match(*this, number); +} + +void MatchState::PrintType(StyledText& out) { + TypeMatcherIndex matcher_index{(*matcher_indices_++).value}; + auto& matcher = data[matcher_index]; + matcher.print(this, out); +} + +void MatchState::PrintNum(StyledText& out) { + NumberMatcherIndex matcher_index{(*matcher_indices_++).value}; + auto& matcher = data[matcher_index]; + matcher.print(this, out); +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +/// TemplateTypeMatcher is a Matcher for a template type. +/// The TemplateTypeMatcher will initially match against any type, and then will only be further +/// constrained based on the conversion rules defined at +/// https://www.w3.org/TR/WGSL/#conversion-rank +template +struct TemplateTypeMatcher { + /// The TypeMatcher for the template type with the index `INDEX` + static constexpr TypeMatcher matcher{ + /* match */ + [](MatchState& state, const core::type::Type* type) -> const core::type::Type* { + if (type->Is()) { + return state.templates.Type(INDEX); + } + if (auto* templates = state.templates.Type(INDEX, type)) { + return templates; + } + return nullptr; + }, + /* print */ + [](MatchState* state, StyledText& out) { + out << style::Type(state->data[state->overload.templates + INDEX].name); + }, + }; +}; + +/// TemplateNumberMatcher is a Matcher for a template number. +/// The TemplateNumberMatcher will match against any number (so long as it is +/// consistent for all uses in the overload) +template +struct TemplateNumberMatcher { + /// The NumberMatcher for the template number with the index `INDEX` + static constexpr NumberMatcher matcher{ + /* match */ + [](MatchState& state, Number number) -> Number { + if (number.IsAny()) { + return state.templates.Num(INDEX); + } + return state.templates.Num(INDEX, number) ? number : Number::invalid; + }, + /* print */ + [](MatchState* state, StyledText& out) { + out << style::Variable(state->data[state->overload.templates + INDEX].name); + }, + }; +}; + +} // namespace tint::core::intrinsic + +#endif // SRC_TINT_LANG_CORE_INTRINSIC_TABLE_DATA_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/intrinsic/type_matchers.h b/3rdparty/dawn/src/tint/lang/core/intrinsic/type_matchers.h new file mode 100644 index 000000000..7c82d7e24 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/intrinsic/type_matchers.h @@ -0,0 +1,824 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_INTRINSIC_TYPE_MATCHERS_H_ +#define SRC_TINT_LANG_CORE_INTRINSIC_TYPE_MATCHERS_H_ + +#include "src/tint/lang/core/evaluation_stage.h" +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/abstract_numeric.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/atomic.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/string.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u64.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/core/type/vector.h" + +//! @cond Doxygen_Suppress + +namespace tint::core::intrinsic { + +inline bool MatchBool(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::Bool* BuildBool(intrinsic::MatchState& state, const type::Type*) { + return state.types.bool_(); +} + +inline const type::F16* BuildF16(intrinsic::MatchState& state, const type::Type*) { + return state.types.f16(); +} + +inline bool MatchF16(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::F32* BuildF32(intrinsic::MatchState& state, const type::Type*) { + return state.types.f32(); +} + +inline bool MatchF32(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::I32* BuildI32(intrinsic::MatchState& state, const type::Type*) { + return state.types.i32(); +} + +inline bool MatchI32(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::I8* BuildI8(intrinsic::MatchState& state, const type::Type*) { + return state.types.i8(); +} + +inline bool MatchI8(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::U32* BuildU32(intrinsic::MatchState& state, const type::Type*) { + return state.types.u32(); +} + +inline bool MatchU32(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::U64* BuildU64(intrinsic::MatchState& state, const type::Type*) { + return state.types.u64(); +} + +inline bool MatchU64(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::U8* BuildU8(intrinsic::MatchState& state, const type::Type*) { + return state.types.u8(); +} + +inline bool MatchU8(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline bool MatchVec(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& N, + const type::Type*& T) { + if (ty->Is()) { + N = intrinsic::Number::any; + T = ty; + return true; + } + + if (auto* v = ty->As()) { + N = v->Width(); + T = v->Type(); + return true; + } + return false; +} + +template +inline bool MatchVec(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + + if (auto* v = ty->As()) { + if (v->Width() == N) { + T = v->Type(); + return true; + } + } + return false; +} + +inline const type::Vector* BuildVec(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number N, + const type::Type* el) { + return state.types.vec(el, N.Value()); +} + +template +inline const type::Vector* BuildVec(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el) { + return state.types.vec(el, N); +} + +constexpr auto MatchVec2 = MatchVec<2>; +constexpr auto MatchVec3 = MatchVec<3>; +constexpr auto MatchVec4 = MatchVec<4>; + +constexpr auto BuildVec2 = BuildVec<2>; +constexpr auto BuildVec3 = BuildVec<3>; +constexpr auto BuildVec4 = BuildVec<4>; + +inline bool MatchPackedVec3(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + + if (auto* v = ty->As()) { + if (v->Packed()) { + T = v->Type(); + return true; + } + } + return false; +} + +inline const type::Vector* BuildPackedVec3(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el) { + return state.types.packed_vec(el, 3u); +} + +inline bool MatchMat(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& M, + intrinsic::Number& N, + const type::Type*& T) { + if (ty->Is()) { + M = intrinsic::Number::any; + N = intrinsic::Number::any; + T = ty; + return true; + } + if (auto* m = ty->As()) { + M = m->Columns(); + N = m->ColumnType()->Width(); + T = m->Type(); + return true; + } + return false; +} + +template +inline bool MatchMat(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + if (auto* m = ty->As()) { + if (m->Columns() == C && m->Rows() == R) { + T = m->Type(); + return true; + } + } + return false; +} + +inline const type::Matrix* BuildMat(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number C, + intrinsic::Number R, + const type::Type* T) { + auto* column_type = state.types.vec(T, R.Value()); + return state.types.mat(column_type, C.Value()); +} + +template +inline const type::Matrix* BuildMat(intrinsic::MatchState& state, + const type::Type*, + const type::Type* T) { + auto* column_type = state.types.vec(T, R); + return state.types.mat(column_type, C); +} + +constexpr auto BuildMat2X2 = BuildMat<2, 2>; +constexpr auto BuildMat2X3 = BuildMat<2, 3>; +constexpr auto BuildMat2X4 = BuildMat<2, 4>; +constexpr auto BuildMat3X2 = BuildMat<3, 2>; +constexpr auto BuildMat3X3 = BuildMat<3, 3>; +constexpr auto BuildMat3X4 = BuildMat<3, 4>; +constexpr auto BuildMat4X2 = BuildMat<4, 2>; +constexpr auto BuildMat4X3 = BuildMat<4, 3>; +constexpr auto BuildMat4X4 = BuildMat<4, 4>; + +constexpr auto MatchMat2X2 = MatchMat<2, 2>; +constexpr auto MatchMat2X3 = MatchMat<2, 3>; +constexpr auto MatchMat2X4 = MatchMat<2, 4>; +constexpr auto MatchMat3X2 = MatchMat<3, 2>; +constexpr auto MatchMat3X3 = MatchMat<3, 3>; +constexpr auto MatchMat3X4 = MatchMat<3, 4>; +constexpr auto MatchMat4X2 = MatchMat<4, 2>; +constexpr auto MatchMat4X3 = MatchMat<4, 3>; +constexpr auto MatchMat4X4 = MatchMat<4, 4>; + +inline bool MatchSubgroupMatrix(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& S, + const type::Type*& T, + intrinsic::Number& A, + intrinsic::Number& B) { + if (ty->Is()) { + A = intrinsic::Number::any; + B = intrinsic::Number::any; + S = intrinsic::Number::any; + T = ty; + return true; + } + if (auto* sm = ty->As()) { + A = sm->Columns(); + B = sm->Rows(); + S = intrinsic::Number(static_cast(sm->Kind())); + T = sm->Type(); + return true; + } + return false; +} + +inline const type::SubgroupMatrix* BuildSubgroupMatrix(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number S, + const type::Type* T, + intrinsic::Number A, + intrinsic::Number B) { + return state.types.subgroup_matrix(static_cast(S.Value()), T, + A.Value(), B.Value()); +} + +inline bool MatchUnsizedBuffer(intrinsic::MatchState&, const type::Type* ty) { + if (ty->Is()) { + return true; + } + if (auto* b = ty->As()) { + return b->Size() == 0; + } + return false; +} + +inline const type::Buffer* BuildUnsizedBuffer(intrinsic::MatchState& state, const type::Type*) { + return state.types.unsized_buffer(); +} + +inline bool MatchBuffer(intrinsic::MatchState&, const type::Type* ty, intrinsic::Number& N) { + if (ty->Is()) { + N = intrinsic::Number::any; + return true; + } + if (auto* b = ty->As()) { + if (b->Size() != 0) { + N = b->Size(); + return true; + } + } + return false; +} + +inline const type::Buffer* BuildBuffer(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number N) { + return state.types.buffer(N.Value()); +} + +inline bool MatchArray(intrinsic::MatchState&, + const type::Type* ty, + const type::Type*& T, + intrinsic::Number& C) { + if (ty->Is()) { + T = ty; + C = intrinsic::Number::any; + return true; + } + + if (auto* a = ty->As()) { + if (auto count = a->Count()->As()) { + T = a->ElemType(); + C = intrinsic::Number(count->value); + return true; + } + } + return false; +} + +inline const type::Array* BuildArray(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el, + intrinsic::Number C) { + return state.types.array(el, C.Value()); +} + +inline bool MatchRuntimeArray(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + + if (auto* a = ty->As()) { + if (a->Count()->Is()) { + T = a->ElemType(); + return true; + } + } + return false; +} + +inline const type::Array* BuildRuntimeArray(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el) { + return state.types.runtime_array(el); +} + +inline const type::BindingArray* BuildBindingArray(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el, + intrinsic::Number N) { + return state.types.binding_array(el, N.Value()); +} + +inline bool MatchBindingArray(intrinsic::MatchState&, + const type::Type* ty, + const type::Type*& T, + intrinsic::Number& N) { + if (ty->Is()) { + N = intrinsic::Number::any; + T = ty; + return true; + } + + if (auto* a = ty->As()) { + if (auto count = a->Count()->As()) { + N = intrinsic::Number(count->value); + T = a->ElemType(); + return true; + } + } + return false; +} + +inline bool MatchPtr(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& S, + const type::Type*& T, + intrinsic::Number& A) { + if (ty->Is()) { + S = intrinsic::Number::any; + T = ty; + A = intrinsic::Number::any; + return true; + } + + if (auto* p = ty->As()) { + S = intrinsic::Number(static_cast(p->AddressSpace())); + T = p->StoreType(); + A = intrinsic::Number(static_cast(p->Access())); + return true; + } + return false; +} + +inline const type::Pointer* BuildPtr(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number S, + const type::Type* T, + intrinsic::Number& A) { + return state.types.ptr(static_cast(S.Value()), T, + static_cast(A.Value())); +} + +inline bool MatchRef(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& S, + const type::Type*& T, + intrinsic::Number& A) { + if (ty->Is()) { + S = intrinsic::Number::any; + T = ty; + A = intrinsic::Number::any; + return true; + } + + if (auto* p = ty->As()) { + S = intrinsic::Number(static_cast(p->AddressSpace())); + T = p->StoreType(); + A = intrinsic::Number(static_cast(p->Access())); + return true; + } + return false; +} + +inline const type::Reference* BuildRef(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number S, + const type::Type* T, + intrinsic::Number& A) { + return state.types.ref(static_cast(S.Value()), T, + static_cast(A.Value())); +} + +inline bool MatchAtomic(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + + if (auto* a = ty->As()) { + T = a->Type(); + return true; + } + return false; +} + +inline const type::Atomic* BuildAtomic(intrinsic::MatchState& state, + const type::Type*, + const type::Type* T) { + return state.types.atomic(T); +} + +inline bool MatchSampler(intrinsic::MatchState&, const type::Type* ty) { + if (ty->Is()) { + return true; + } + return ty->Is([](const type::Sampler* s) { return s->Kind() == type::SamplerKind::kSampler; }); +} + +inline const type::Sampler* BuildSampler(intrinsic::MatchState& state, const type::Type*) { + return state.types.sampler(); +} + +inline bool MatchSamplerComparison(intrinsic::MatchState&, const type::Type* ty) { + if (ty->Is()) { + return true; + } + return ty->Is( + [](const type::Sampler* s) { return s->Kind() == type::SamplerKind::kComparisonSampler; }); +} + +inline const type::Sampler* BuildSamplerComparison(intrinsic::MatchState& state, + const type::Type*) { + return state.types.comparison_sampler(); +} + +inline bool MatchTexture(intrinsic::MatchState&, + const type::Type* ty, + type::TextureDimension dim, + const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + if (auto* v = ty->As()) { + if (v->Dim() == dim) { + T = v->Type(); + return true; + } + } + return false; +} + +#define JOIN(a, b) a##b + +#define DECLARE_SAMPLED_TEXTURE(suffix, dim) \ + inline bool JOIN(MatchTexture, suffix)(intrinsic::MatchState & state, const type::Type* ty, \ + const type::Type*& T) { \ + return MatchTexture(state, ty, dim, T); \ + } \ + inline const type::SampledTexture* JOIN(BuildTexture, suffix)( \ + intrinsic::MatchState & state, const type::Type*, const type::Type* T) { \ + return state.types.sampled_texture(dim, T); \ + } + +DECLARE_SAMPLED_TEXTURE(1D, type::TextureDimension::k1d) +DECLARE_SAMPLED_TEXTURE(2D, type::TextureDimension::k2d) +DECLARE_SAMPLED_TEXTURE(2DArray, type::TextureDimension::k2dArray) +DECLARE_SAMPLED_TEXTURE(3D, type::TextureDimension::k3d) +DECLARE_SAMPLED_TEXTURE(Cube, type::TextureDimension::kCube) +DECLARE_SAMPLED_TEXTURE(CubeArray, type::TextureDimension::kCubeArray) +#undef DECLARE_SAMPLED_TEXTURE + +inline bool MatchTextureMultisampled(intrinsic::MatchState&, + const type::Type* ty, + type::TextureDimension dim, + const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + if (auto* v = ty->As()) { + if (v->Dim() == dim) { + T = v->Type(); + return true; + } + } + return false; +} + +#define DECLARE_MULTISAMPLED_TEXTURE(suffix, dim) \ + inline bool JOIN(MatchTextureMultisampled, suffix)( \ + intrinsic::MatchState & state, const type::Type* ty, const type::Type*& T) { \ + return MatchTextureMultisampled(state, ty, dim, T); \ + } \ + inline const type::MultisampledTexture* JOIN(BuildTextureMultisampled, suffix)( \ + intrinsic::MatchState & state, const type::Type*, const type::Type* T) { \ + return state.types.multisampled_texture(dim, T); \ + } + +DECLARE_MULTISAMPLED_TEXTURE(2D, type::TextureDimension::k2d) +#undef DECLARE_MULTISAMPLED_TEXTURE + +inline bool MatchTextureDepth(intrinsic::MatchState&, + const type::Type* ty, + type::TextureDimension dim) { + if (ty->Is()) { + return true; + } + return ty->Is([&](const type::DepthTexture* t) { return t->Dim() == dim; }); +} + +#define DECLARE_DEPTH_TEXTURE(suffix, dim) \ + inline bool JOIN(MatchTextureDepth, suffix)(intrinsic::MatchState & state, \ + const type::Type* ty) { \ + return MatchTextureDepth(state, ty, dim); \ + } \ + inline const type::DepthTexture* JOIN(BuildTextureDepth, suffix)( \ + intrinsic::MatchState & state, const type::Type*) { \ + return state.types.depth_texture(dim); \ + } + +DECLARE_DEPTH_TEXTURE(2D, type::TextureDimension::k2d) +DECLARE_DEPTH_TEXTURE(2DArray, type::TextureDimension::k2dArray) +DECLARE_DEPTH_TEXTURE(Cube, type::TextureDimension::kCube) +DECLARE_DEPTH_TEXTURE(CubeArray, type::TextureDimension::kCubeArray) +#undef DECLARE_DEPTH_TEXTURE + +inline bool MatchTextureDepthMultisampled2D(intrinsic::MatchState&, const type::Type* ty) { + if (ty->Is()) { + return true; + } + return ty->Is([&](const type::DepthMultisampledTexture* t) { + return t->Dim() == type::TextureDimension::k2d; + }); +} + +inline const type::DepthMultisampledTexture* BuildTextureDepthMultisampled2D( + intrinsic::MatchState& state, + const type::Type*) { + return state.types.depth_multisampled_texture(type::TextureDimension::k2d); +} + +inline bool MatchTextureStorage(intrinsic::MatchState&, + const type::Type* ty, + type::TextureDimension dim, + intrinsic::Number& F, + intrinsic::Number& A) { + if (ty->Is()) { + F = intrinsic::Number::any; + A = intrinsic::Number::any; + return true; + } + if (auto* v = ty->As()) { + if (v->Dim() == dim) { + F = intrinsic::Number(static_cast(v->TexelFormat())); + A = intrinsic::Number(static_cast(v->Access())); + return true; + } + } + return false; +} + +#define DECLARE_STORAGE_TEXTURE(suffix, dim) \ + inline bool JOIN(MatchTextureStorage, suffix)(intrinsic::MatchState & state, \ + const type::Type* ty, intrinsic::Number& F, \ + intrinsic::Number& A) { \ + return MatchTextureStorage(state, ty, dim, F, A); \ + } \ + inline const type::StorageTexture* JOIN(BuildTextureStorage, suffix)( \ + intrinsic::MatchState & state, const type::Type*, intrinsic::Number F, \ + intrinsic::Number A) { \ + auto format = static_cast(F.Value()); \ + auto access = static_cast(A.Value()); \ + return state.types.storage_texture(dim, format, access); \ + } + +DECLARE_STORAGE_TEXTURE(1D, type::TextureDimension::k1d) +DECLARE_STORAGE_TEXTURE(2D, type::TextureDimension::k2d) +DECLARE_STORAGE_TEXTURE(2DArray, type::TextureDimension::k2dArray) +DECLARE_STORAGE_TEXTURE(3D, type::TextureDimension::k3d) +#undef DECLARE_STORAGE_TEXTURE + +inline bool MatchTextureExternal(intrinsic::MatchState&, const type::Type* ty) { + return ty->IsAnyOf(); +} + +inline const type::ExternalTexture* BuildTextureExternal(intrinsic::MatchState& state, + const type::Type*) { + return state.types.external_texture(); +} + +inline bool MatchTexelBuffer(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& F, + intrinsic::Number& A) { + if (ty->Is()) { + F = intrinsic::Number::any; + A = intrinsic::Number::any; + return true; + } + if (auto* v = ty->As()) { + F = intrinsic::Number(static_cast(v->TexelFormat())); + A = intrinsic::Number(static_cast(v->Access())); + return true; + } + return false; +} + +inline const type::TexelBuffer* BuildTexelBuffer(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number F, + intrinsic::Number A) { + auto format = static_cast(F.Value()); + auto access = static_cast(A.Value()); + return state.types.texel_buffer(format, access); +} + +inline bool MatchInputAttachment(intrinsic::MatchState&, + const type::Type* ty, + const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + if (auto* v = ty->As()) { + T = v->Type(); + return true; + } + return false; +} + +inline const type::InputAttachment* BuildInputAttachment(intrinsic::MatchState& state, + const type::Type*, + const type::Type* T) { + return state.types.input_attachment(T); +} + +// Builtin types starting with a _ prefix cannot be declared in WGSL, so they +// can only be used as return types. Because of this, they must only match Any, +// which is used as the return type matcher. +inline bool MatchModfResult(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (!ty->Is()) { + return false; + } + T = ty; + return true; +} +inline bool MatchModfResultVec(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& N, + const type::Type*& T) { + if (!ty->Is()) { + return false; + } + N = intrinsic::Number::any; + T = ty; + return true; +} +inline bool MatchFrexpResult(intrinsic::MatchState&, const type::Type* ty, const type::Type*& T) { + if (!ty->Is()) { + return false; + } + T = ty; + return true; +} +inline bool MatchFrexpResultVec(intrinsic::MatchState&, + const type::Type* ty, + intrinsic::Number& N, + const type::Type*& T) { + if (!ty->Is()) { + return false; + } + N = intrinsic::Number::any; + T = ty; + return true; +} + +inline bool MatchAtomicCompareExchangeResult(intrinsic::MatchState&, + const type::Type* ty, + const type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + return false; +} + +inline const type::Struct* BuildModfResult(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el) { + return type::CreateModfResult(state.types, state.symbols, el); +} + +inline const type::Struct* BuildModfResultVec(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number& n, + const type::Type* el) { + auto* vec = state.types.vec(el, n.Value()); + return type::CreateModfResult(state.types, state.symbols, vec); +} + +inline const type::Struct* BuildFrexpResult(intrinsic::MatchState& state, + const type::Type*, + const type::Type* el) { + return type::CreateFrexpResult(state.types, state.symbols, el); +} + +inline const type::Struct* BuildFrexpResultVec(intrinsic::MatchState& state, + const type::Type*, + intrinsic::Number& n, + const type::Type* el) { + auto* vec = state.types.vec(el, n.Value()); + return type::CreateFrexpResult(state.types, state.symbols, vec); +} + +inline const type::Struct* BuildAtomicCompareExchangeResult(intrinsic::MatchState& state, + const type::Type*, + const type::Type* ty) { + return type::CreateAtomicCompareExchangeResult(state.types, state.symbols, ty); +} + +inline bool MatchString(core::intrinsic::MatchState&, const core::type::Type* ty) { + return ty->Is(); +} + +inline const core::type::Type* BuildString(core::intrinsic::MatchState& state, + const core::type::Type*) { + return state.types.String(); +} + +} // namespace tint::core::intrinsic + +//! @endcond + +#endif // SRC_TINT_LANG_CORE_INTRINSIC_TYPE_MATCHERS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/io_attributes.h b/3rdparty/dawn/src/tint/lang/core/io_attributes.h new file mode 100644 index 000000000..80b6d803a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/io_attributes.h @@ -0,0 +1,104 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IO_ATTRIBUTES_H_ +#define SRC_TINT_LANG_CORE_IO_ATTRIBUTES_H_ + +#include +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/interpolation.h" + +namespace tint::core { + +/// Attributes that can be applied to an object that will be used for shader IO. +struct IOAttributes { + /// The value of a `@location` attribute. + std::optional location = std::nullopt; + /// The value of a `@blend_src` attribute. + std::optional blend_src = std::nullopt; + /// The value of a `@color` attribute. + std::optional color = std::nullopt; + /// The value of a `@builtin` attribute. + std::optional builtin = std::nullopt; + /// The depth mode of a `@builtin` attribute. + std::optional depth_mode = std::nullopt; + /// The values of a `@interpolate` attribute. + std::optional interpolation = std::nullopt; + /// The value of an `@input_attachment_index` attribute + std::optional input_attachment_index = std::nullopt; + /// The value of the `@binding` and `@group` attributes + std::optional binding_point = std::nullopt; + /// True if the object is annotated with `@invariant`. + bool invariant = false; +}; + +/// Used for referencing/tagging a specific IOAttribute. +/// IOAttributes above is intentionally not a key-value map (e.g. HashSet) using this enum, since it +/// has heterogeneous value types and would also cease to be a POD. +enum class IOAttributeKind : uint8_t { + kLocation, + kBlendSrc, + kColor, + kBuiltin, + kDepthMode, + kInterpolation, + kInputAttachmentIndex, + kBindingPoint, + kInvariant, +}; + +/// @returns a human-readable string representation of @p kind +inline std::string_view ToString(const IOAttributeKind kind) { + switch (kind) { + case IOAttributeKind::kLocation: + return "location"; + case IOAttributeKind::kBlendSrc: + return "blend src"; + case IOAttributeKind::kColor: + return "color"; + case IOAttributeKind::kBuiltin: + return "builtin"; + case IOAttributeKind::kDepthMode: + return "depth mode"; + case IOAttributeKind::kInterpolation: + return "interpolation"; + case IOAttributeKind::kInputAttachmentIndex: + return "input attachment index"; + case IOAttributeKind::kBindingPoint: + return "binding point"; + case IOAttributeKind::kInvariant: + return "invariant"; + } + TINT_ICE() << "Unknown kind passed to ToString(IOAttributeKind)"; +} + +} // namespace tint::core + +#endif // SRC_TINT_LANG_CORE_IO_ATTRIBUTES_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/access.cc b/3rdparty/dawn/src/tint/lang/core/ir/access.cc new file mode 100644 index 000000000..68817da47 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/access.cc @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/access.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Access); + +namespace tint::core::ir { + +//! @cond Doxygen_Suppress +Access::Access(Id id) : Base(id) {} + +Access::Access(Id id, InstructionResult* result, Value* object, VectorRef indices) + : Base(id) { + AddOperand(Access::kObjectOperandOffset, object); + AddOperands(Access::kIndicesOperandOffset, std::move(indices)); + AddResult(result); +} + +Access::~Access() = default; + +Access* Access::Clone(CloneContext& ctx) { + auto new_result = ctx.Clone(Result()); + auto obj = ctx.Remap(Object()); + auto indices = ctx.Remap(Indices()); + return ctx.ir.CreateInstruction(new_result, obj, indices); +} +//! @endcond + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/access.h b/3rdparty/dawn/src/tint/lang/core/ir/access.h new file mode 100644 index 000000000..30a816ee2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/access.h @@ -0,0 +1,97 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_ACCESS_H_ +#define SRC_TINT_LANG_CORE_IR_ACCESS_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// An access instruction in the IR. +class Access final : public Castable> { + public: + /// 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; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The minimum number of operands used by this instruction + static constexpr size_t kMinNumOperands = 2; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Access(Instruction::Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param object the accessor object + /// @param indices the indices to access + Access(Instruction::Id id, InstructionResult* result, Value* object, VectorRef indices); + + ~Access() override; + + /// @copydoc Instruction::Clone() + Access* Clone(CloneContext& ctx) override; + + /// @returns the object used for the access + Value* Object() { return Operand(kObjectOperandOffset); } + + /// @returns the object used for the access + const Value* Object() const { return Operand(kObjectOperandOffset); } + + /// Adds the given index to the end of the access chain + /// @param idx the index to add + void AddIndex(Value* idx) { AddOperand(operands_.Length(), idx); } + + /// @returns the accessor indices + tint::Slice Indices() { return operands_.Slice().Offset(kIndicesOperandOffset); } + + /// @returns the accessor indices + tint::Slice Indices() const { + return operands_.Slice().Offset(kIndicesOperandOffset); + } + + /// Removes the last index from the access indices + /// @returns the last index value + Value* PopLastIndex() { return PopOperand(); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "access"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_ACCESS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.cc b/3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.cc new file mode 100644 index 000000000..9cdbf9b74 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.cc @@ -0,0 +1,124 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/analysis/for_loop_analysis.h" + +#include + +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/builtin_call.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/load_vector_element.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/unary.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir::analysis { + +void ForLoopAnalysis::AttemptForLoopDeduction(const Loop* loop) { + // Find the first 'if' which should be the condition for the for-loop. + // Order here is critical since instructions in blocks are forward dependencies. + const core::ir::If* if_to_remove = nullptr; + for (auto* inst : *loop->Body()) { + if (auto* if_ = inst->As()) { + if (if_->Results().IsEmpty() && if_->True()->Length() == 1 && + if_->False()->Length() == 1 && tint::Is(if_->True()->Front()) && + tint::Is(if_->False()->Front())) { + // Matched the loop condition as it was converted from the 'for' originally. + if_to_remove = if_; + break; + } else { + // Conservatively fail to avoid the possibility of reordering instructions (when + // moving into conditional). + return; + } + } else if (inst->Is() || inst->Is() || + inst->Is() || inst->Is() || + inst->Is() || inst->Is() || + inst->Is()) { + // Allowed instructions since either load or operate on values (side effect free). + continue; + } else { + // Conservatively fail for all other functions that could potentially store/mutate + // memory. + return; + } + } + if (!if_to_remove) { + return; + } + + Hashset sink_chain; + // Add the 'if' instruction to set to avoid adding it to the body. + sink_chain.Add(if_to_remove); + const Instruction* inst = if_to_remove->prev; + while (inst) { + const auto& results = inst->Results(); + if (results.Length() != 1u) { + // We do not support more than one result for simplicity. + return; + } + + for (const auto& each_usage : inst->Result()->UsagesUnsorted()) { + // All usages must sink into the condition of the if + if (!each_usage->instruction || !sink_chain.Contains(each_usage->instruction)) { + return; + } + } + sink_chain.Add(inst); + inst = inst->prev; + } + + body_removed_instructions = std::move(sink_chain); + // Valid condition found. Success criteria for condition hoisting. + for_condition = if_to_remove->Condition(); +} + +ForLoopAnalysis::ForLoopAnalysis(const Loop& loop) { + AttemptForLoopDeduction(&loop); +} +ForLoopAnalysis::~ForLoopAnalysis() = default; + +} // namespace tint::core::ir::analysis diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.h b/3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.h new file mode 100644 index 000000000..a6049f7fb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/for_loop_analysis.h @@ -0,0 +1,73 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_ANALYSIS_FOR_LOOP_ANALYSIS_H_ +#define SRC_TINT_LANG_CORE_IR_ANALYSIS_FOR_LOOP_ANALYSIS_H_ + +#include +#include + +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::core::ir::analysis { + +/// ForLoopAnalysis is a helper used to find and hoist the condition into the for loop directly. +/// See crbug.com/429187478 for the rationale behind this analysis. +class ForLoopAnalysis { + public: + /// Constructor + /// @param loop the Loop to cache analyses for + explicit ForLoopAnalysis(const Loop& loop); + ~ForLoopAnalysis(); + + /// Returns the condition for the loop. + /// Otherwise if no condition can be hoisted it returns nullptr. + /// @returns the loop condition instruction result + const core::ir::Value* GetIfCondition() { return for_condition; } + + /// Returns true if the instruction should be removed from the body to support condition + /// hoisting. + /// @param inst from the body of the loop + /// @returns a boolean + bool IsBodyRemovedInstruction(const core::ir::Instruction* inst) { + TINT_ASSERT(GetIfCondition()); + return body_removed_instructions.Contains(inst); + } + + private: + void AttemptForLoopDeduction(const Loop* loop); + + Hashset body_removed_instructions; + const core::ir::Value* for_condition = nullptr; +}; + +} // namespace tint::core::ir::analysis + +#endif // SRC_TINT_LANG_CORE_IR_ANALYSIS_FOR_LOOP_ANALYSIS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.cc b/3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.cc new file mode 100644 index 000000000..290547ac6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.cc @@ -0,0 +1,1472 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/analysis/integer_range_analysis.h" + +#include +#include + +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir::analysis { + +namespace { +/// Returns true if v is the integer constant 1. +bool IsOne(const Value* v) { + if (auto* cv = v->As()) { + return Switch( + cv->Type(), + [&](const core::type::I32*) { return cv->Value()->ValueAs() == 1; }, + [&](const core::type::U32*) { return cv->Value()->ValueAs() == 1; }, + [&](const Default) -> bool { return false; }); + } + return false; +} + +bool IsConstantInteger(const Value* v) { + if (auto* cv = v->As()) { + return cv->Type()->IsIntegerScalar(); + } + return false; +} + +int64_t GetValueFromConstant(const Constant* value) { + // Return an int64_t is enough as the type of `value` can only be either i32 or u32. + [[maybe_unused]] bool is_i32_or_u32 = value->Type()->IsAnyOf(); + TINT_ASSERT(is_i32_or_u32); + return value->Value()->ValueAs(); +} + +struct CompareOpAndConstRHS { + BinaryOp op; + int64_t const_rhs = 0; + const Binary* binary = nullptr; +}; + +IntegerRangeInfo ToIntegerRangeInfo(const Constant* constant, + int64_t min_value, + int64_t max_value) { + if (constant->Type()->IsSignedIntegerScalar()) { + return IntegerRangeInfo(min_value, max_value); + } else { + return IntegerRangeInfo(static_cast(min_value), static_cast(max_value)); + } +} + +IntegerRangeInfo GetFullRangeWithSameIntegerRangeInfoType(const IntegerRangeInfo& range) { + if (std::holds_alternative(range.range)) { + return IntegerRangeInfo(static_cast(i32::kLowestValue), + static_cast(i32::kHighestValue)); + } else { + return IntegerRangeInfo(static_cast(u32::kLowestValue), + static_cast(u32::kHighestValue)); + } +} + +} // namespace + +IntegerRangeInfo::IntegerRangeInfo(int64_t min_bound, int64_t max_bound) { + TINT_ASSERT(min_bound <= max_bound); + range = SignedIntegerRange{min_bound, max_bound}; +} + +IntegerRangeInfo::IntegerRangeInfo(uint64_t min_bound, uint64_t max_bound) { + TINT_ASSERT(min_bound <= max_bound); + range = UnsignedIntegerRange{min_bound, max_bound}; +} + +bool IntegerRangeInfo::IsValid() const { + return !std::holds_alternative(range); +} + +struct IntegerRangeAnalysisImpl { + explicit IntegerRangeAnalysisImpl(Module* ir_module) { + for (Function* func : ir_module->functions) { + // Analyze all the function parameters. + AnalyzeFunctionParameters(func); + + // Analyze all of the loops in the function. + Traverse(func->Block(), [&](Loop* l) { AnalyzeLoop(l); }); + } + } + + IntegerRangeInfo GetInfo(const FunctionParam* param, uint32_t index) { + const auto& range_info = integer_function_param_range_info_map_.Get(param); + if (!range_info) { + return {}; + } + TINT_ASSERT(range_info.value->Length() > index); + return (*range_info)[index]; + } + + IntegerRangeInfo GetInfo(const Var* var) { return integer_var_range_info_map_.GetOr(var, {}); } + + IntegerRangeInfo GetInfo(const Load* load) { + const InstructionResult* instruction = load->From()->As(); + if (!instruction) { + return {}; + } + const Var* load_from_var = instruction->Instruction()->As(); + if (!load_from_var) { + return {}; + } + return GetInfo(load_from_var); + } + + IntegerRangeInfo GetInfo(const Access* access) { + const Value* obj = access->Object(); + + // Currently we only support the access to `local_invocation_id` or `local_invocation_index` + // as a function parameter. + const FunctionParam* function_param = obj->As(); + if (!function_param) { + return {}; + } + if (access->Indices().Length() > 1) { + return {}; + } + if (!access->Indices()[0]->As()) { + return {}; + } + uint32_t index = + static_cast(GetValueFromConstant(access->Indices()[0]->As())); + return GetInfo(function_param, index); + } + + IntegerRangeInfo GetInfo(const Let* let) { return GetInfo(let->Value()); } + + IntegerRangeInfo GetInfo(const Constant* constant) { + if (!IsConstantInteger(constant)) { + return {}; + } + return integer_constant_range_info_map_.GetOrAdd(constant, [&]() { + int64_t const_value = GetValueFromConstant(constant); + return ToIntegerRangeInfo(constant, const_value, const_value); + }); + } + + IntegerRangeInfo GetInfo(const Convert* convert) { + return integer_convert_range_info_map_.GetOrAdd(convert, [&]() -> IntegerRangeInfo { + auto* result_type = convert->Result()->Type(); + if (!result_type->IsIntegerScalar()) { + return {}; + } + + const auto* operand = convert->Operand(Convert::kValueOperandOffset); + IntegerRangeInfo operand_range_info = GetInfo(operand); + if (!operand_range_info.IsValid()) { + return {}; + } + + TINT_ASSERT(operand->Type()->IsIntegerScalar()); + TINT_ASSERT(operand->Type() != result_type); + + if (std::holds_alternative( + operand_range_info.range)) { + // result = convert(operand), operand cannot be negative. + TINT_ASSERT(result_type->As()); + const auto& range = + std::get(operand_range_info.range); + if (range.min_bound < 0) { + return {}; + } + return IntegerRangeInfo(static_cast(range.min_bound), + static_cast(range.max_bound)); + } else { + // result = convert(operand), operand cannot be greater than + // `i32::kHighestValue`. + TINT_ASSERT(result_type->As()); + const auto& range = + std::get(operand_range_info.range); + if (range.max_bound > i32::kHighestValue) { + return {}; + } + return IntegerRangeInfo(static_cast(range.min_bound), + static_cast(range.max_bound)); + } + }); + } + + IntegerRangeInfo GetInfo(const Value* value) { + return Switch( + value, [&](const Constant* constant) { return GetInfo(constant); }, + [&](const FunctionParam* param) { + if (!param->Type()->IsIntegerScalar()) { + return IntegerRangeInfo(); + } + return GetInfo(param, 0); + }, + [&](const InstructionResult* r) { + // TODO(348701956): Support more instruction types + return Switch( + r->Instruction(), [&](const Var* var) { return GetInfo(var); }, + [&](const Load* load) { return GetInfo(load); }, + [&](const Access* access) { return GetInfo(access); }, + [&](const Let* let) { return GetInfo(let); }, + [&](const Binary* binary) { return GetInfo(binary); }, + [&](const Convert* convert) { return GetInfo(convert); }, + [&](const CoreBuiltinCall* call) { return GetInfo(call); }, + [](Default) { return IntegerRangeInfo(); }); + }, + [](Default) { return IntegerRangeInfo(); }); + } + + IntegerRangeInfo GetInfo(const Binary* binary) { + return integer_binary_range_info_map_.GetOrAdd(binary, [&]() -> IntegerRangeInfo { + IntegerRangeInfo range_rhs = GetInfo(binary->RHS()); + if (!range_rhs.IsValid()) { + return {}; + } + + // We may compute the range of a `modulo` binary when the LHS doesn't have a valid + // range. + if (binary->Op() == BinaryOp::kModulo) { + return ComputeIntegerRangeForBinaryModulo(binary->LHS(), range_rhs); + } + + IntegerRangeInfo range_lhs = GetInfo(binary->LHS()); + if (!range_lhs.IsValid()) { + return {}; + } + + // TODO(348701956): Support more binary operators + switch (binary->Op()) { + case BinaryOp::kAdd: + return ComputeIntegerRangeForBinaryAdd(range_lhs, range_rhs); + + case BinaryOp::kSubtract: + return ComputeIntegerRangeForBinarySubtract(range_lhs, range_rhs); + + case BinaryOp::kMultiply: + return ComputeIntegerRangeForBinaryMultiply(range_lhs, range_rhs); + + case BinaryOp::kDivide: + return ComputeIntegerRangeForBinaryDivide(range_lhs, range_rhs); + + case BinaryOp::kShiftLeft: + return ComputeIntegerRangeForBinaryShiftLeft(range_lhs, range_rhs); + + case BinaryOp::kShiftRight: + return ComputeIntegerRangeForBinaryShiftRight(range_lhs, range_rhs); + + default: + return {}; + } + }); + } + + IntegerRangeInfo GetInfo(const CoreBuiltinCall* call) { + return integer_core_builtin_call_range_info_map_.GetOrAdd(call, [&]() -> IntegerRangeInfo { + // Currently we only support the integer builtin calls that return an integer value. + if (!call->Result()->Type()->IsIntegerScalar()) { + return {}; + } + + // TODO(348701956): Support more builtin functions + switch (call->Func()) { + case core::BuiltinFn::kMin: { + return ComputeIntegerRangeForBuiltinMin(call); + } + case core::BuiltinFn::kMax: { + return ComputeIntegerRangeForBuiltinMax(call); + } + default: + return {}; + } + }); + } + + /// Analyze a loop to compute the range of the loop control variable if possible. + void AnalyzeLoop(const Loop* loop) { + const Var* index = GetLoopControlVariableFromConstantInitializer(loop); + if (!index) { + return; + } + const Binary* update = GetBinaryToUpdateLoopControlVariableInContinuingBlock(loop, index); + if (!update) { + return; + } + CompareOpAndConstRHS compare_info = + GetCompareInfoOfLoopControlVariableInLoopBody(loop, index); + if (!compare_info.binary) { + return; + } + + TINT_ASSERT(index->Initializer()); + TINT_ASSERT(index->Initializer()->As()); + + // for (var i = const_init; ...) + const Constant* constant_initializer = index->Initializer()->As(); + int64_t const_init = GetValueFromConstant(constant_initializer); + + // for (...; i++) or for(...; i--) + bool index_is_increasing = update->Op() == BinaryOp::kAdd; + + switch (compare_info.op) { + case BinaryOp::kLessThanEqual: { + // for (var index = const_init; index <= const_rhs; index++) + // Only `const_init <= const_rhs` is valid. The range of `index` is: + // [const_init, const_rhs] + // Note that in `GetBinaryToCompareLoopControlVariableInLoopBody()` we disallow + // `const_rhs` to be the maximum value of `i32` or `u32`, so: + // - `index + 1` won't be overflow as `const_init` cannot be greater than + // `const_rhs`. + // - `index <= const_rhs` can correctly exit when `const_init + 1` is the maximum + // value of `i32` or `u32`. + if (index_is_increasing && const_init <= compare_info.const_rhs) { + IntegerRangeInfo range_info = ToIntegerRangeInfo( + constant_initializer, const_init, compare_info.const_rhs); + integer_var_range_info_map_.Add(index, range_info); + } + break; + } + case BinaryOp::kGreaterThanEqual: { + // for (var index = const_init; index >= const_rhs; index--) + // Only `const_init >= const_rhs` is valid. The range of `index` is: + // [const_rhs, const_init] + // Note that in `GetBinaryToCompareLoopControlVariableInLoopBody()` we disallow + // `const_rhs` to be the minimum value of `i32` or `u32`, so: + // - `index - 1` won't be underflow as `const_init` cannot be less than `const_rhs`. + // - `index >= const_rhs` can correctly exit when `const_init - 1` is the minimum + // value of `i32` or `u32`. + if (!index_is_increasing && const_init >= compare_info.const_rhs) { + IntegerRangeInfo range_info = ToIntegerRangeInfo( + constant_initializer, compare_info.const_rhs, const_init); + integer_var_range_info_map_.Add(index, range_info); + } + break; + } + default: + break; + } + } + + const Var* GetLoopControlVariableFromConstantInitializer(const Loop* loop) { + TINT_ASSERT(loop); + + auto* init_block = loop->Initializer(); + if (!init_block) { + return nullptr; + } + + // Currently we only support the loop initializer of a simple for-loop, which only has two + // instructions + // - The first instruction is to initialize the loop control variable + // with a constant integer (signed or unsigned) value. + // - The second instruction is `next_iteration` + // e.g. for (var i = 0; ...) + if (init_block->Length() != 2u) { + return nullptr; + } + + auto* var = init_block->Front()->As(); + if (!var) { + return nullptr; + } + + if (!init_block->Back()->As()) { + return nullptr; + } + + const auto* pointer = var->Result()->Type()->As(); + if (!pointer->StoreType()->IsIntegerScalar()) { + return nullptr; + } + + const auto* initializer = var->Initializer(); + if (!initializer) { + return nullptr; + } + + if (!initializer->As()) { + return nullptr; + } + + return var; + } + + // Currently we only support the loop continuing of a simple for-loop, which only has 4 + // instructions + /// - The first instruction is to load the loop control variable into a temporary variable. + /// - The second instruction is to add one or minus one to the temporary variable. + /// - The third instruction is to store the value of the temporary variable into the loop + /// control variable. + /// - The fourth instruction is `next_iteration`. + const Binary* GetBinaryToUpdateLoopControlVariableInContinuingBlock( + const Loop* loop, + const Var* loop_control_variable) { + TINT_ASSERT(loop); + TINT_ASSERT(loop_control_variable); + + auto* continuing_block = loop->Continuing(); + if (!continuing_block) { + return nullptr; + } + + if (continuing_block->Length() != 4u) { + return nullptr; + } + + // 1st instruction: + // %src = load %loop_control_variable + const auto* load_from_loop_control_variable = continuing_block->Instructions()->As(); + if (!load_from_loop_control_variable) { + return nullptr; + } + if (load_from_loop_control_variable->From() != loop_control_variable->Result()) { + return nullptr; + } + + // 2nd instruction: + // %dst = add %src, 1 + // or %dst = add 1, %src + // or %dst = sub %src, 1 + const auto* add_or_sub_from_loop_control_variable = + load_from_loop_control_variable->next->As(); + if (!add_or_sub_from_loop_control_variable) { + return nullptr; + } + const auto* src = load_from_loop_control_variable->Result(); + const auto* lhs = add_or_sub_from_loop_control_variable->LHS(); + const auto* rhs = add_or_sub_from_loop_control_variable->RHS(); + switch (add_or_sub_from_loop_control_variable->Op()) { + case BinaryOp::kAdd: { + // %dst = add %src, 1 + if (lhs == src && IsOne(rhs)) { + break; + } + // %dst = add 1, %src + if (rhs == src && IsOne(lhs)) { + break; + } + return nullptr; + } + case BinaryOp::kSubtract: { + // %dst = sub %src, 1 + if (lhs == src && IsOne(rhs)) { + break; + } + return nullptr; + } + default: + return nullptr; + } + + // 3rd instruction: + // store %loop_control_variable, %dst + const auto* store_into_loop_control_variable = + add_or_sub_from_loop_control_variable->next->As(); + if (!store_into_loop_control_variable) { + return nullptr; + } + const auto* dst = add_or_sub_from_loop_control_variable->Result(); + if (store_into_loop_control_variable->From() != dst) { + return nullptr; + } + if (store_into_loop_control_variable->To() != loop_control_variable->Result()) { + return nullptr; + } + + // 4th instruction: + // next_iteration + if (!store_into_loop_control_variable->next->As()) { + return nullptr; + } + + return add_or_sub_from_loop_control_variable; + } + + // Currently we only support the loop continuing of a simple for-loop which meets all the below + // requirements: + // - The loop control variable is only used as the parameter of the load instruction. + // - The first instruction is to load the loop control variable into a temporary variable. + // - The second instruction is a `compare` binary to compare the temporary variable with a + // constant value and save the result to a boolean variable. + // - The second instruction cannot be a comparison that will never return true. + // - The third instruction is an `ifelse` expression that uses the boolean variable got in the + // second instruction as the condition. + // - The true block of the above `ifelse` expression doesn't contain `exit_loop`. + // - The false block of the above `ifelse` expression only contains `exit_loop`. + // A valid `compare` binary instruction (the second instruction) can be in one of the below + // formats: + // 1. variable >= constant variable <= constant + // 2. variable > constant variable < constant + // 3. constant >= variable constant <= variable + // 4. constant > variable constant < variable + // This function analyzes the `compare` binary and returns both `variable` and `constant` in the + // equivalent format of format 1 and a pointer to the `compare` binary in a + // `CompareOpAndConstRHS`struct when the input `loop` meets all the above requirements. + // `CompareOpAndConstRHS.binary` will be set to nullptr otherwise. + CompareOpAndConstRHS GetCompareInfoOfLoopControlVariableInLoopBody( + const Loop* loop, + const Var* loop_control_variable) { + TINT_ASSERT(loop); + TINT_ASSERT(loop_control_variable); + + auto* body_block = loop->Body(); + + CompareOpAndConstRHS compare_info = {}; + + // Reject any non-load instructions unless it is a store in the continuing block + const auto& uses = loop_control_variable->Result(0)->UsagesUnsorted(); + for (auto& use : uses) { + if (use->instruction->Is()) { + continue; + } + if (use->instruction->Is() && use->instruction->Block() == loop->Continuing()) { + continue; + } + return compare_info; + } + + // 1st instruction: + // %src = load %loop_control_variable + const auto* load_from_loop_control_variable = body_block->Instructions()->As(); + if (!load_from_loop_control_variable) { + return compare_info; + } + if (load_from_loop_control_variable->From() != loop_control_variable->Result(0)) { + return compare_info; + } + + // 2nd instruction: + // %condition:bool = lt(gt, lte, gte) %src, constant_value + // or %condition:bool = lt(gt, lte, gte) constant_value, %src + const auto* exit_condition_on_loop_control_variable = + load_from_loop_control_variable->next->As(); + if (!exit_condition_on_loop_control_variable) { + return compare_info; + } + BinaryOp op = exit_condition_on_loop_control_variable->Op(); + auto* lhs = exit_condition_on_loop_control_variable->LHS(); + auto* rhs = exit_condition_on_loop_control_variable->RHS(); + switch (op) { + case BinaryOp::kLessThan: + case BinaryOp::kGreaterThan: + case BinaryOp::kLessThanEqual: + case BinaryOp::kGreaterThanEqual: { + if (IsConstantInteger(rhs) && lhs == load_from_loop_control_variable->Result(0)) { + break; + } + if (IsConstantInteger(lhs) && rhs == load_from_loop_control_variable->Result(0)) { + break; + } + return compare_info; + } + default: + return compare_info; + } + + const bool is_signed = lhs->Type()->IsSignedIntegerScalar(); + auto const_i32 = [](const Value* val) { + return val->As()->Value()->ValueAs(); + }; + auto const_u32 = [](const Value* val) { + return val->As()->Value()->ValueAs(); + }; + + // Check and extract necessary information from `binary`. + // Note that we should early return when the comparison will never return true. + // e.g. for (...; i < 0u; ...) // The loop body will never be executed. + // We should also early return when the comparison will always return true, which means the + // loop exit condition takes no effect and the loop control variable can actually take all + // the numbers. + // e.g. for (i = 100u; i >= 0u; i--) // `i` can be any u32 value instead of [0u, 100u] + if (IsConstantInteger(rhs)) { + // Handle `binary` in the format of `variable op const_rhs` + int64_t const_rhs = GetValueFromConstant(rhs->As()); + + switch (op) { + case BinaryOp::kLessThan: { + // variable < std::numeric_limits::min() + if (!is_signed && const_u32(rhs) == u32::kLowestValue) { + return compare_info; + } + // variable < std::numeric_limits::min() + if (is_signed && const_i32(rhs) == i32::kLowestValue) { + return compare_info; + } + + // variable < constant => variable <= constant - 1 + // `const_rhs - 1` will always be safe after the above checks. + compare_info.op = BinaryOp::kLessThanEqual; + compare_info.const_rhs = const_rhs - 1; + break; + } + + case BinaryOp::kGreaterThan: { + // variable > std::numeric_limits::max() + if (!is_signed && const_u32(rhs) == u32::kHighestValue) { + return compare_info; + } + // variable > std::numeric_limits::max() + if (is_signed && const_i32(rhs) == i32::kHighestValue) { + return compare_info; + } + + // variable > constant => variable >= constant + 1 + // `const_rhs` will always be safe after the above checks. + compare_info.op = BinaryOp::kGreaterThanEqual; + compare_info.const_rhs = const_rhs + 1; + break; + } + + case BinaryOp::kLessThanEqual: { + // variable <= std::numeric_limits::max() + if (!is_signed && const_u32(rhs) == u32::kHighestValue) { + return compare_info; + } + // variable <= std::numeric_limits::max() + if (is_signed && const_i32(rhs) == i32::kHighestValue) { + return compare_info; + } + + compare_info.op = op; + compare_info.const_rhs = const_rhs; + break; + } + case BinaryOp::kGreaterThanEqual: { + // variable >= std::numeric_limits::min() + if (!is_signed && const_u32(rhs) == u32::kLowestValue) { + return compare_info; + } + // variable >= std::numeric_limits::min() + if (is_signed && const_i32(rhs) == i32::kLowestValue) { + return compare_info; + } + + compare_info.op = op; + compare_info.const_rhs = const_rhs; + break; + } + default: + TINT_UNREACHABLE(); + } + } else { + // Handle `binary` in the format of `const_lhs op variable` + TINT_ASSERT(IsConstantInteger(lhs)); + int64_t const_lhs = GetValueFromConstant(lhs->As()); + + switch (op) { + case BinaryOp::kLessThan: { + // std::numeric_limits::max() < variable + if (!is_signed && const_u32(lhs) == u32::kHighestValue) { + return compare_info; + } + // std::numeric_limits::max() < variable + if (is_signed && const_i32(lhs) == i32::kHighestValue) { + return compare_info; + } + + // constant < variable => variable > constant => variable >= constant + 1 + // `const_lhs + 1` will always be safe after the above checks. + compare_info.op = BinaryOp::kGreaterThanEqual; + compare_info.const_rhs = const_lhs + 1; + break; + } + + case BinaryOp::kGreaterThan: { + // std::numeric_limits::min() > variable + if (!is_signed && const_u32(lhs) == u32::kLowestValue) { + return compare_info; + } + // std::numeric_limits::min() > variable + if (is_signed && const_i32(lhs) == i32::kLowestValue) { + return compare_info; + } + + // constant > variable => variable < constant => variable <= constant - 1 + // `const_lhs - 1` will always be safe after the above checks. + compare_info.op = BinaryOp::kLessThanEqual; + compare_info.const_rhs = const_lhs - 1; + break; + } + + case BinaryOp::kLessThanEqual: { + // std::numeric_limits::min() <= variable + if (!is_signed && const_u32(lhs) == u32::kLowestValue) { + return compare_info; + } + // std::numeric_limits::min() <= variable + if (is_signed && const_i32(lhs) == i32::kLowestValue) { + return compare_info; + } + + // constant <= variable => variable >= constant + compare_info.op = BinaryOp::kGreaterThanEqual; + compare_info.const_rhs = const_lhs; + break; + } + + case BinaryOp::kGreaterThanEqual: { + // std::numeric_limits::max() >= variable + if (!is_signed && const_u32(lhs) == u32::kHighestValue) { + return compare_info; + } + // std::numeric_limits::max() >= variable + if (is_signed && const_i32(lhs) == i32::kHighestValue) { + return compare_info; + } + + // constant >= variable => variable <= constant + compare_info.op = BinaryOp::kLessThanEqual; + compare_info.const_rhs = const_lhs; + break; + } + + default: + TINT_UNREACHABLE(); + } + } + + // 3rd instruction: + // if %condition [t: $true, f: $false] { + // $true: { + // // Maybe some other instructions + // exit_if + // } + // $false: { exit_loop } + // } + const auto* if_on_exit_condition = exit_condition_on_loop_control_variable->next->As(); + if (!if_on_exit_condition) { + return compare_info; + } + if (if_on_exit_condition->Condition() != + exit_condition_on_loop_control_variable->Result(0)) { + return compare_info; + } + if (!if_on_exit_condition->True()->Terminator()->As()) { + return compare_info; + } + const auto* front_inst = if_on_exit_condition->False()->Front(); + if (!front_inst || !front_inst->As()) { + return compare_info; + } + + // Set `compare_info.binary` after the loop passes all the above checks. + compare_info.binary = exit_condition_on_loop_control_variable; + return compare_info; + } + + private: + void AnalyzeFunctionParameters(const Function* func) { + for (const auto* param : func->Params()) { + if (!param->Type()->IsIntegerScalarOrVector()) { + return; + } + + // Currently we only support the query of ranges of `local_invocation_id` or + // `local_invocation_index`. + if (!param->Builtin()) { + return; + } + + switch (*param->Builtin()) { + case BuiltinValue::kLocalInvocationIndex: { + // We shouldn't be trying to use range analysis on a module that has + // non-constant workgroup sizes, since we will always have replaced pipeline + // overrides with constant values early in the pipeline. + TINT_ASSERT(func->WorkgroupSizeAsConst().has_value()); + std::array workgroup_size = func->WorkgroupSizeAsConst().value(); + uint64_t max_bound = + workgroup_size[0] * workgroup_size[1] * workgroup_size[2] - 1u; + constexpr uint64_t kMinBound = 0; + integer_function_param_range_info_map_.Add( + param, + Vector({IntegerRangeInfo(kMinBound, max_bound)})); + break; + } + case BuiltinValue::kLocalInvocationId: { + TINT_ASSERT(func->WorkgroupSizeAsConst().has_value()); + std::array workgroup_size = func->WorkgroupSizeAsConst().value(); + + constexpr uint64_t kMinBound = 0; + Vector integerRanges; + for (uint32_t size_x_y_z : workgroup_size) { + integerRanges.Push({kMinBound, size_x_y_z - 1u}); + } + integer_function_param_range_info_map_.Add(param, integerRanges); + } + + break; + default: + break; + } + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinaryAdd(const IntegerRangeInfo& lhs, + const IntegerRangeInfo& rhs) { + // Add two 32-bit signed integer values saved in int64_t. Return {} when either overflow or + // underflow happens. + auto SafeAddI32 = [](int64_t a, int64_t b) -> std::optional { + TINT_ASSERT(a >= i32::kLowestValue && a <= i32::kHighestValue); + TINT_ASSERT(b >= i32::kLowestValue && b <= i32::kHighestValue); + + int64_t sum = a + b; + if (sum > i32::kHighestValue || sum < i32::kLowestValue) { + return {}; + } + return sum; + }; + + // No-overflow add between two 32-bit unsigned integer values saved in uint64_t. Return {} + // when overflow happens. + auto SafeAddU32 = [](uint64_t a, uint64_t b) -> std::optional { + TINT_ASSERT(a <= u32::kHighestValue); + TINT_ASSERT(b <= u32::kHighestValue); + + uint64_t sum = a + b; + if (sum > u32::kHighestValue) { + return {}; + } + return sum; + }; + + if (std::holds_alternative(lhs.range)) { + auto lhs_i32 = std::get(lhs.range); + auto rhs_i32 = std::get(rhs.range); + + // [min1, max1] + [min2, max2] => [min1 + min2, max1 + max2] + std::optional min_bound = SafeAddI32(lhs_i32.min_bound, rhs_i32.min_bound); + std::optional max_bound = SafeAddI32(lhs_i32.max_bound, rhs_i32.max_bound); + if (!min_bound.has_value() || !max_bound.has_value()) { + return {}; + } + return IntegerRangeInfo(*min_bound, *max_bound); + } else { + auto lhs_u32 = std::get(lhs.range); + auto rhs_u32 = std::get(rhs.range); + + // [min1, max1] + [min2, max2] => [min1 + min2, max1 + max2] + std::optional min_bound = SafeAddU32(lhs_u32.min_bound, rhs_u32.min_bound); + std::optional max_bound = SafeAddU32(lhs_u32.max_bound, rhs_u32.max_bound); + if (!min_bound || !max_bound) { + return {}; + } + return IntegerRangeInfo(*min_bound, *max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinarySubtract(const IntegerRangeInfo& lhs, + const IntegerRangeInfo& rhs) { + // Subtract two 32-bit signed integer values saved in int64_t. Return {} when either + // overflow or underflow happens. + auto SafeSubtractI32 = [](int64_t a, int64_t b) -> std::optional { + TINT_ASSERT(a >= i32::kLowestValue && a <= i32::kHighestValue); + TINT_ASSERT(b >= i32::kLowestValue && b <= i32::kHighestValue); + + int64_t diff = a - b; + if (diff > i32::kHighestValue || diff < i32::kLowestValue) { + return {}; + } + return diff; + }; + + // No-underflow Subtract between two 32-bit unsigned integer values saved in uint64_t. + // Return {} when underflow happens. + auto SafeSubtractU32 = [](uint64_t a, uint64_t b) -> std::optional { + TINT_ASSERT(a <= u32::kHighestValue); + TINT_ASSERT(b <= u32::kHighestValue); + + if (a < b) { + return {}; + } + return a - b; + }; + + if (std::holds_alternative(lhs.range)) { + auto lhs_i32 = std::get(lhs.range); + auto rhs_i32 = std::get(rhs.range); + + // [min1, max1] - [min2, max2] => [min1 - max2, max1 - min2] + std::optional min_bound = + SafeSubtractI32(lhs_i32.min_bound, rhs_i32.max_bound); + std::optional max_bound = + SafeSubtractI32(lhs_i32.max_bound, rhs_i32.min_bound); + if (!min_bound.has_value() || !max_bound.has_value()) { + return {}; + } + return IntegerRangeInfo(*min_bound, *max_bound); + } else { + auto lhs_u32 = std::get(lhs.range); + auto rhs_u32 = std::get(rhs.range); + + // [min1, max1] - [min2, max2] => [min1 - max2, max1 - min2] + std::optional min_bound = + SafeSubtractU32(lhs_u32.min_bound, rhs_u32.max_bound); + std::optional max_bound = + SafeSubtractU32(lhs_u32.max_bound, rhs_u32.min_bound); + if (!min_bound || !max_bound) { + return {}; + } + return IntegerRangeInfo(*min_bound, *max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinaryMultiply(const IntegerRangeInfo& lhs, + const IntegerRangeInfo& rhs) { + // Multiply two 32-bit non-negative signed integer values saved in int64_t. Return {} when + // overflow happens. + auto SafeMultiplyNonNegativeI32 = [](int64_t a, int64_t b) -> std::optional { + TINT_ASSERT(a >= 0 && a <= i32::kHighestValue); + TINT_ASSERT(b >= 0 && b <= i32::kHighestValue); + + int64_t multiply = a * b; + if (multiply > i32::kHighestValue) { + return {}; + } + return multiply; + }; + + // No-underflow multiply two 32-bit unsigned integer values saved in uint64_t. + // Return {} when underflow happens. + auto SafeMultiplyU32 = [](uint64_t a, uint64_t b) -> std::optional { + TINT_ASSERT(a <= u32::kHighestValue); + TINT_ASSERT(b <= u32::kHighestValue); + + uint64_t multiply = a * b; + if (multiply > u32::kHighestValue) { + return {}; + } + return multiply; + }; + + if (std::holds_alternative(lhs.range)) { + auto lhs_i32 = std::get(lhs.range); + auto rhs_i32 = std::get(rhs.range); + + // Currently we only handle multiplication with non-negative values, which means + // 0 <= min_bound <= max_bound + if (lhs_i32.min_bound < 0 || rhs_i32.min_bound < 0) { + return {}; + } + + // min1 >= 0, min2 >= 0 + // [min1, max1] * [min2, max2] => [min1 * min2, max1 * max2] + std::optional min_bound = + SafeMultiplyNonNegativeI32(lhs_i32.min_bound, rhs_i32.min_bound); + std::optional max_bound = + SafeMultiplyNonNegativeI32(lhs_i32.max_bound, rhs_i32.max_bound); + if (!min_bound.has_value() || !max_bound.has_value()) { + return {}; + } + return IntegerRangeInfo(*min_bound, *max_bound); + } else { + auto lhs_u32 = std::get(lhs.range); + auto rhs_u32 = std::get(rhs.range); + + // [min1, max1] * [min2, max2] => [min1 * min2, max1 * max2] + std::optional min_bound = + SafeMultiplyU32(lhs_u32.min_bound, rhs_u32.min_bound); + std::optional max_bound = + SafeMultiplyU32(lhs_u32.max_bound, rhs_u32.max_bound); + if (!min_bound || !max_bound) { + return {}; + } + return IntegerRangeInfo(*min_bound, *max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinaryDivide(const IntegerRangeInfo& lhs, + const IntegerRangeInfo& rhs) { + if (std::holds_alternative(lhs.range)) { + auto lhs_i32 = std::get(lhs.range); + auto rhs_i32 = std::get(rhs.range); + + // Currently we require `lhs` must be non-negative, and `rhs` must be positive. + // 0 <= lhs.min_bound <= lhs.max_bound + if (lhs_i32.min_bound < 0) { + return {}; + } + // 0 < rhs.min_bound <= rhs.max_bound + if (rhs_i32.min_bound <= 0) { + return {}; + } + + // min1 >= 0, min2 > 0 + // [min1, max1] / [min2, max2] => [min1 / max2, max1 / min2] + int64_t min_bound = lhs_i32.min_bound / rhs_i32.max_bound; + int64_t max_bound = lhs_i32.max_bound / rhs_i32.min_bound; + return IntegerRangeInfo(min_bound, max_bound); + } else { + auto lhs_u32 = std::get(lhs.range); + auto rhs_u32 = std::get(rhs.range); + + // `rhs` must be positive. + if (rhs_u32.min_bound == 0) { + return {}; + } + + // [min1, max1] / [min2, max2] => [min1 / max2, max1 / min2] + uint64_t min_bound = lhs_u32.min_bound / rhs_u32.max_bound; + uint64_t max_bound = lhs_u32.max_bound / rhs_u32.min_bound; + return IntegerRangeInfo(min_bound, max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinaryShiftLeft(const IntegerRangeInfo& lhs, + const IntegerRangeInfo& rhs) { + auto rhs_u32 = std::get(rhs.range); + + // rhs_u32 must be less than the bit width of i32 and u32 (32): + // rhs_u32.min_bound <= rhs_u32.max_bound < 32 + if (rhs_u32.max_bound >= 32) { + return {}; + } + + if (std::holds_alternative(lhs.range)) { + auto lhs_i32 = std::get(lhs.range); + + // Currently we require `lhs` must be non-negative. + // 0 <= lhs.min_bound <= lhs.max_bound + if (lhs_i32.min_bound < 0) { + return {}; + } + + // [min1, max1] << [min2, max2] => [min1 << min2, max1 << max2] + // `max_bound` (as a uint64_t) won't be overflow because `rhs_u32.max_bound` < 32. + uint64_t max_bound = static_cast(lhs_i32.max_bound) << rhs_u32.max_bound; + + // Overflow an `i32` is not allowed, which means: + // min_bound <= max_bound <= i32::kHighestValue + if (max_bound > static_cast(i32::kHighestValue)) { + return {}; + } + + int64_t min_bound = lhs_i32.min_bound << rhs_u32.min_bound; + return IntegerRangeInfo(min_bound, static_cast(max_bound)); + } else { + auto lhs_u32 = std::get(lhs.range); + + // `max_bound` (as a uint64_t) won't be overflow because `rhs_u32.max_bound` < 32. + uint64_t max_bound = lhs_u32.max_bound << rhs_u32.max_bound; + + // Overflow a `u32` is not allowed, which means: + // min_bound <= max_bound <= u32::kHighestValue + if (max_bound > u32::kHighestValue) { + return {}; + } + + uint64_t min_bound = lhs_u32.min_bound << rhs_u32.min_bound; + return IntegerRangeInfo(min_bound, max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinaryShiftRight(const IntegerRangeInfo& lhs, + const IntegerRangeInfo& rhs) { + auto rhs_u32 = std::get(rhs.range); + + // rhs_u32 must be less than the bit width of i32 and u32 (32): + // rhs_u32.min_bound <= rhs_u32.max_bound < 32 + if (rhs_u32.max_bound >= 32) { + return {}; + } + + if (std::holds_alternative(lhs.range)) { + auto lhs_i32 = std::get(lhs.range); + + // Currently we require `lhs` must be non-negative. + // 0 <= lhs.min_bound <= lhs.max_bound + if (lhs_i32.min_bound < 0) { + return {}; + } + + // [min1, max1] >> [min2, max2] => [min1 >> max2, max1 >> min2] + int64_t min_bound = lhs_i32.min_bound >> rhs_u32.max_bound; + int64_t max_bound = lhs_i32.max_bound >> rhs_u32.min_bound; + return IntegerRangeInfo(min_bound, max_bound); + } else { + auto lhs_u32 = std::get(lhs.range); + + uint64_t min_bound = lhs_u32.min_bound >> rhs_u32.max_bound; + uint64_t max_bound = lhs_u32.max_bound >> rhs_u32.min_bound; + return IntegerRangeInfo(min_bound, max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBinaryModulo(const Value* lhs, + const IntegerRangeInfo& rhs_range) { + TINT_ASSERT(rhs_range.IsValid()); + + if (!lhs->Type()->IsIntegerScalar()) { + return {}; + } + IntegerRangeInfo lhs_range = GetInfo(lhs); + if (!lhs_range.IsValid()) { + lhs_range = GetFullRangeWithSameIntegerRangeInfoType(rhs_range); + } + + // Suppose the range of `lhs` is [a, b], `a` and `b` are 64-bit signed positive integers + // and no greater than u32::kHighestValue. + // . + // `rhs` is a 64-bit signed constant positive integer. + // Let ra = a % rhs (0 <= ra <= rhs - 1), rb = b % rhs (0 <= rb <= rhs - 1) + // qa = a / rhs, qb = b / rhs + // Then a = qa * rhs + ra, b = qb * rhs + rb + // + // All the below arithmetic operations are done in the range of 64-bit signed integers so + // there won't be any overflow or underflow issues. + // + // I. We can ignore the case of qa > qb. + // Proof: + // Let qa = qb + d (d >= 1), then + // a = (qb + d) * rhs + ra + // = (qb * rhs + d * rhs) + ra + // = (qb * rhs + rb) - rb + (d * rhs + ra) + // = b - rb + (d * rhs) + ra + // >= b - rb + rhs + (ra) // d >= 1 + // >= b + (rhs - rb) // ra >= 0 + // > b (impossible) // rhs > rb + // + // II. When qa < qb, the range of `lhs % rhs` is [0, rhs- 1]. + // Proof: + // Let qb = qa + d (d >= 1), then + // b = (qa + d) * rhs + rb + // = (qa * rhs + d * rhs) + rb + // = qa * rhs + (ra - ra) + d * rhs + rb + // = (qa * rhs + ra) + rb - ra + d * rhs + // = a + rb - ra + d * rhs + // >= a + (rb) - ra + rhs // d >= 1 + // + // (1) rb >= 0 + // => b >= a - ra + rhs + // => b >= (a) + (rhs - ra) > a // rhs > ra + // => b >= (qa * rhs + ra) + (rhs - ra) > a + // => b >= (qa + 1) * rhs > a + // So there must exist a k = ((qa + 1) * rhs) in (a, b] that satisfies `k % rhs == 0` + // + // (2) k = (qa + 1) * rhs > a + // k > a, a >= 0 => k - 1 >= 0 + // Then b >= k + // > k - 1 = (qa + 1) * rhs - 1 + // = qa * rhs + (rhs - 1) // rhs - 1 >= ra + // >= qa * rhs + ra = a + // So there must exist a (k - 1) = ((qa + 1) * rhs - 1) in [a, b) that satisfies + // `(k - 1) % rhs == 0`. + // + // Based on (1) and (2), we can conclude the range of `lhs % rhs` is [0, rhs - 1]. + // + // III. When qa == qb, the range of `lhs % rhs` is `[ra, rb]`. + // Proof: + // let q = qa = qb, + // then a = q * rhs + ra, b = q * rhs + rb + // a = q * rhs + ra <= q * rhs + rb = b + // => ra <= rb + // Arbitrarily choose x in range [a, b], let rx = x % rhs, qx = x / rhs + // x = qx * rhs + rx (0 <= rx < rhs) + // a <= x <= b + // => (q * rhs + ra) <= (qx * rhs + rx) <= (q * rhs + rb) + // + // (1) q * rhs + ra <= qx * rhs + rx + // ra <= qx * rhs + rx - q * rhs // ra >= 0 + // 0 <= ra <= qx * rhs + rx - q * rhs + // 0 <= qx * rhs + rx - q * rhs + // q * rhs - qx * rhs <= rx < rhs + // q * rhs - qx * rhs < rhs // rhs > 0 + // q - qx < 1 + // qx > q - 1 + // + // (2) qx * rhs + rx <= q * rhs + rb + // qx * rhs + rx - q * rhs <= rb < rhs + // qx * rhs + rx - q * rhs < rhs + // rx < rhs + q * rhs - qx * rhs // rx >= 0 + // 0 <= rx < rhs + q * rhs - qx * rhs + // 0 < rhs + q * rhs - qx * rhs // rhs > 0 + // 0 < 1 + q - qx + // qx < q + 1 + // + // Based on (1) and (2), qx == q + // Then (q * rhs + ra) <= (q * rhs + rx) <= (q * rhs + rb) + // => ra <= rx <= rb + // The range of `lhs % rhs` is [ra, rb]. + if (std::holds_alternative(rhs_range.range)) { + // Currently we require `lhs` must be non-negative. + auto lhs_i32 = std::get(lhs_range.range); + if (lhs_i32.min_bound < 0) { + return {}; + } + + // Currently we only accept `rhs` as a constant positive integer. + auto rhs_i32 = std::get(rhs_range.range); + if (rhs_i32.min_bound != rhs_i32.max_bound) { + return {}; + } + int64_t rhs_const = rhs_i32.min_bound; + if (rhs_const <= 0) { + return {}; + } + + // Let: + // lhs_max = q_max * rhs_const + r_max; // 0 <= r_max < rhs_const + // lhs_min = q_min * rhs_const + r_min; // 0 <= r_min < rhs_const + if (lhs_i32.min_bound / rhs_const == lhs_i32.max_bound / rhs_const) { + // if q_min == q_max (matches case III): + // The range of `lhs % rhs` is [r_min, r_max]. + int64_t min_bound = lhs_i32.min_bound % rhs_const; + int64_t max_bound = lhs_i32.max_bound % rhs_const; + TINT_ASSERT(min_bound <= max_bound); + return IntegerRangeInfo(min_bound, max_bound); + } else { + // Otherwise (q_min < q_max, matches case II): + // The range of `lhs % rhs` is [0, rhs - 1] (the whole remainder range). + return IntegerRangeInfo(0, rhs_const - 1); + } + } else { + // Currently we only accept `rhs` as a constant positive integer. + auto rhs_u32 = std::get(rhs_range.range); + if (rhs_u32.min_bound != rhs_u32.max_bound) { + return {}; + } + uint64_t rhs_const = rhs_u32.min_bound; + if (rhs_const == 0) { + return {}; + } + + // `lhs` must not be negative so we don't need to do the check on it. + + // Let: + // lhs_max = q_max * rhs_const + r_max; // 0 <= r_max < rhs_const + // lhs_min = q_min * rhs_const + r_min; // 0 <= r_min < rhs_const + auto lhs_u32 = std::get(lhs_range.range); + if (lhs_u32.min_bound / rhs_const == lhs_u32.max_bound / rhs_const) { + // if q_min == q_max (matches case III): + // The range of `lhs % rhs` is [r_min, r_max]. + uint64_t min_bound = lhs_u32.min_bound % rhs_const; + uint64_t max_bound = lhs_u32.max_bound % rhs_const; + TINT_ASSERT(min_bound <= max_bound); + return IntegerRangeInfo(min_bound, max_bound); + } else { + // Otherwise (q_min < q_max, matches case II): + // The range of `lhs % rhs` is [0, rhs - 1] (the whole remainder range). + return IntegerRangeInfo(0, rhs_const - 1); + } + } + } + + IntegerRangeInfo ComputeIntegerRangeForBuiltinMin(const CoreBuiltinCall* call) { + TINT_ASSERT(call->Operands().Length() == 2u); + + TINT_ASSERT(call->Operand(0)->Type()->IsIntegerScalar()); + TINT_ASSERT(call->Operand(1)->Type()->IsIntegerScalar()); + + IntegerRangeInfo range1 = GetInfo(call->Operand(0)); + IntegerRangeInfo range2 = GetInfo(call->Operand(1)); + if (!range1.IsValid() && !range2.IsValid()) { + return {}; + } + + if (!range1.IsValid()) { + range1 = GetFullRangeWithSameIntegerRangeInfoType(range2); + } + if (!range2.IsValid()) { + range2 = GetFullRangeWithSameIntegerRangeInfoType(range1); + } + + // range1: [min1, max1] range2: [min2, max2] + // The minimum value of (min(range1, range2)) is min(min1, min2) and + // The maximum value of (min(range1, range2)) is min(max1, max2). + if (std::holds_alternative(range1.range)) { + TINT_ASSERT(std::holds_alternative(range2.range)); + + auto range1_i32 = std::get(range1.range); + auto range2_i32 = std::get(range2.range); + + // When the range is all i32 or u32, we will treat it as an invalid range. + int64_t min_bound = std::min(range1_i32.min_bound, range2_i32.min_bound); + int64_t max_bound = std::min(range1_i32.max_bound, range2_i32.max_bound); + if (min_bound == i32::kLowestValue && max_bound == i32::kHighestValue) { + return {}; + } + + return IntegerRangeInfo(min_bound, max_bound); + } else { + TINT_ASSERT( + std::holds_alternative(range2.range)); + + auto range1_u32 = std::get(range1.range); + auto range2_u32 = std::get(range2.range); + + // When the range is all i32 or u32, we will treat it as an invalid range. + uint64_t min_bound = std::min(range1_u32.min_bound, range2_u32.min_bound); + uint64_t max_bound = std::min(range1_u32.max_bound, range2_u32.max_bound); + if (min_bound == u32::kLowestValue && max_bound == u32::kHighestValue) { + return {}; + } + + return IntegerRangeInfo(min_bound, max_bound); + } + } + + IntegerRangeInfo ComputeIntegerRangeForBuiltinMax(const CoreBuiltinCall* call) { + TINT_ASSERT(call->Operands().Length() == 2u); + + TINT_ASSERT(call->Operand(0)->Type()->IsIntegerScalar()); + TINT_ASSERT(call->Operand(1)->Type()->IsIntegerScalar()); + + IntegerRangeInfo range1 = GetInfo(call->Operand(0)); + IntegerRangeInfo range2 = GetInfo(call->Operand(1)); + if (!range1.IsValid() && !range2.IsValid()) { + return {}; + } + + if (!range1.IsValid()) { + range1 = GetFullRangeWithSameIntegerRangeInfoType(range2); + } + if (!range2.IsValid()) { + range2 = GetFullRangeWithSameIntegerRangeInfoType(range1); + } + + // range1: [min1, max1] range2: [min2, max2] + // The minimum value of (max(range1, range2)) is max(min1, min2) and + // The maximum value of (max(range1, range2)) is max(max1, max2). + if (std::holds_alternative(range1.range)) { + TINT_ASSERT(std::holds_alternative(range2.range)); + + auto range1_i32 = std::get(range1.range); + auto range2_i32 = std::get(range2.range); + + // When the range is all i32 or u32, we will treat it as an invalid range. + int64_t min_bound = std::max(range1_i32.min_bound, range2_i32.min_bound); + int64_t max_bound = std::max(range1_i32.max_bound, range2_i32.max_bound); + if (min_bound == i32::kLowestValue && max_bound == i32::kHighestValue) { + return {}; + } + + return IntegerRangeInfo(min_bound, max_bound); + } else { + TINT_ASSERT( + std::holds_alternative(range2.range)); + + auto range1_u32 = std::get(range1.range); + auto range2_u32 = std::get(range2.range); + + // When the range is all i32 or u32, we will treat it as an invalid range. + uint64_t min_bound = std::max(range1_u32.min_bound, range2_u32.min_bound); + uint64_t max_bound = std::max(range1_u32.max_bound, range2_u32.max_bound); + if (min_bound == u32::kLowestValue && max_bound == u32::kHighestValue) { + return {}; + } + + return IntegerRangeInfo(min_bound, max_bound); + } + } + + Hashmap, 4> + integer_function_param_range_info_map_; + Hashmap integer_var_range_info_map_; + Hashmap integer_constant_range_info_map_; + Hashmap integer_binary_range_info_map_; + Hashmap integer_convert_range_info_map_; + Hashmap integer_core_builtin_call_range_info_map_; +}; + +IntegerRangeAnalysis::IntegerRangeAnalysis(Module* ir_module) + : impl_(new IntegerRangeAnalysisImpl(ir_module)) {} + +IntegerRangeAnalysis::~IntegerRangeAnalysis() = default; + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const FunctionParam* param, uint32_t index) { + return impl_->GetInfo(param, index); +} + +const Var* IntegerRangeAnalysis::GetLoopControlVariableFromConstantInitializerForTest( + const Loop* loop) { + return impl_->GetLoopControlVariableFromConstantInitializer(loop); +} + +const Binary* IntegerRangeAnalysis::GetBinaryToUpdateLoopControlVariableInContinuingBlockForTest( + const Loop* loop, + const Var* loop_control_variable) { + return impl_->GetBinaryToUpdateLoopControlVariableInContinuingBlock(loop, + loop_control_variable); +} + +const Binary* IntegerRangeAnalysis::GetBinaryToCompareLoopControlVariableInLoopBodyForTest( + const Loop* loop, + const Var* loop_control_variable) { + return impl_->GetCompareInfoOfLoopControlVariableInLoopBody(loop, loop_control_variable).binary; +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Var* var) { + return impl_->GetInfo(var); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Load* load) { + return impl_->GetInfo(load); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Access* access) { + return impl_->GetInfo(access); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Constant* constant) { + return impl_->GetInfo(constant); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Value* value) { + return impl_->GetInfo(value); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Binary* binary) { + return impl_->GetInfo(binary); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Let* let) { + return impl_->GetInfo(let); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const Convert* convert) { + return impl_->GetInfo(convert); +} + +IntegerRangeInfo IntegerRangeAnalysis::GetInfo(const CoreBuiltinCall* call) { + return impl_->GetInfo(call); +} + +} // namespace tint::core::ir::analysis diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.h b/3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.h new file mode 100644 index 000000000..b33b25606 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/integer_range_analysis.h @@ -0,0 +1,196 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_ANALYSIS_INTEGER_RANGE_ANALYSIS_H_ +#define SRC_TINT_LANG_CORE_IR_ANALYSIS_INTEGER_RANGE_ANALYSIS_H_ + +#include +#include +#include + +namespace tint::core::ir { +class Access; +class Binary; +class Constant; +class Convert; +class CoreBuiltinCall; +class Function; +class FunctionParam; +class Let; +class Load; +class Loop; +class Module; +class Value; +class Var; +} // namespace tint::core::ir + +namespace tint::core::ir::analysis { + +/// The result of a integer range analysis: the upper and lower bound of a given integer variable. +/// The bound is inclusive, which means the value x being bound satisfies: +/// min_bound <= x <= max_bound. +struct IntegerRangeInfo { + IntegerRangeInfo() = default; + IntegerRangeInfo(int64_t min_bound, int64_t max_bound); + IntegerRangeInfo(uint64_t min_bound, uint64_t max_bound); + + bool IsValid() const; + + struct SignedIntegerRange { + int64_t min_bound; + int64_t max_bound; + }; + struct UnsignedIntegerRange { + uint64_t min_bound; + uint64_t max_bound; + }; + std::variant range; +}; + +struct IntegerRangeAnalysisImpl; + +/// IntegerRangeAnalysis is a helper used to analyze integer ranges. +class IntegerRangeAnalysis { + public: + /// Constructor + /// @module ir_module the ir module to cache analyses for + explicit IntegerRangeAnalysis(Module* ir_module); + + ~IntegerRangeAnalysis(); + + /// Returns the integer range info of a given parameter with given index, if it is an integer + /// or an integer vector parameter. The index must not be over the maximum size of the vector + /// and must be 0 if the parameter is an integer. + /// Otherwise is not analyzable and returns an invalid `IntegerRangeInfo` object. If it is the + /// first time to query the info, the result will also be stored into a cache for future + /// queries. + /// @param param the variable to get information about + /// @param index the vector component index when the parameter is a vector type. if the + /// parameter is a scalar, then `index` must be zero. + /// @returns the integer range info + IntegerRangeInfo GetInfo(const FunctionParam* param, uint32_t index = 0); + + /// Returns the integer range info of a given variable if it is an integer variable and it has a + /// meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + /// @param var the variable to get information about + /// @returns the integer range info + IntegerRangeInfo GetInfo(const Var* var); + + /// Returns the integer range info of a given `Load` variable if it is an integer variable and + /// it has a meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Load* load_var); + + /// Returns the integer range info of a given `Access` variable if it is an integer variable and + /// it has a meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Access* access); + + /// Returns the integer range info of a given `Let` variable if it is an integer variable and it + /// has a meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Let* let); + + /// Returns the integer range info of a given `Constant` if it is an integer. + /// Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Constant* constant); + + /// Returns the integer range info of a given `Value` variable if it is an integer variable and + /// it has a meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Value* value); + + /// Returns the integer range info of a given `Binary` variable if it is an integer variable and + /// it has a meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Binary* binary); + + /// Returns the integer range info of a given `Convert` variable if it is an integer variable + /// and it has a meaningful range. Returns an invalid `IntegerRangeInfo` object otherwise. + IntegerRangeInfo GetInfo(const Convert* convert); + + /// Returns the integer range info of a given `CoreBuiltinCall` variable if it is an integer + /// variable and it has a meaningful range. Returns an invalid `IntegerRangeInfo` object + /// otherwise. + IntegerRangeInfo GetInfo(const CoreBuiltinCall* call); + + /// Note: This function is only for tests. + /// Returns the pointer of the loop control variable in the given loop when its initializer + /// meets the below requirements. + /// - There are only two instructions in the loop initializer block. + /// - The first instruction is to initialize the loop control variable + /// with a constant integer (signed or unsigned) value. + /// - The second instruction is `next_iteration`. + /// @param loop the Loop variable to investigate + /// @returns the pointer of the loop control variable when its loop initializer meets the + /// requirements, return nullptr otherwise. + const Var* GetLoopControlVariableFromConstantInitializerForTest(const Loop* loop); + + /// Note: This function is only for tests. + /// Returns the pointer of the binary operation that updates the loop control variable in the + /// continuing block of the given loop if the loop meets the below requirements. + /// - There are only 4 instructions in the loop initializer block. + /// - The first instruction is to load the loop control variable into a temporary variable. + /// - The second instruction is to add one or minus one to the temporary variable. + /// - The third instruction is to store the value of the temporary variable into the loop + /// control variable. + /// - The fourth instruction is `next_iteration`. + /// @param loop the Loop variable to investigate. + /// @param loop_control_variable the loop control variable to investigate. + /// @returns the pointer of the binary operation that updates the loop control variable in the + /// continuing block of the given loop if the loop meets all the requirements, return nullptr + /// otherwise. + const Binary* GetBinaryToUpdateLoopControlVariableInContinuingBlockForTest( + const Loop* loop, + const Var* loop_control_variable); + + /// Note: This function is only for tests + /// Returns the pointer of the binary operation that compares the loop control variable with its + /// limitations in the body block of the loop if the loop meets the below requirements: + /// - The loop control variable is only used as the parameter of the load instruction. + /// - The first instruction is to load the loop control variable into a temporary variable. + /// - The second instruction is to compare the temporary variable with a constant value and save + /// the result to a boolean variable. + /// - The second instruction cannot be a comparison that will never return true. + /// - The third instruction is an `ifelse` expression that uses the boolean variable got in the + /// second instruction as the condition. + // - The true block of the above `ifelse` expression doesn't contain `exit_loop`. + // - The false block of the above `ifelse` expression only contains `exit_loop`. + /// @param loop the Loop variable to investigate. + /// @param loop_control_variable the loop control variable to investigate. + /// @returns the pointer of the binary operation that compares the loop control variable with + /// its limitations in the body block of the loop if the loop meets the below requirements, + /// return nullptr otherwise. + const Binary* GetBinaryToCompareLoopControlVariableInLoopBodyForTest( + const Loop* loop, + const Var* loop_control_variable); + + private: + IntegerRangeAnalysis(const IntegerRangeAnalysis&) = delete; + IntegerRangeAnalysis(IntegerRangeAnalysis&&) = delete; + + std::unique_ptr impl_; +}; + +} // namespace tint::core::ir::analysis + +#endif // SRC_TINT_LANG_CORE_IR_ANALYSIS_INTEGER_RANGE_ANALYSIS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.cc b/3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.cc new file mode 100644 index 000000000..85c742d8d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.cc @@ -0,0 +1,321 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/analysis/loop_analysis.h" + +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir::analysis { + +namespace { + +/// Returns an instruction of the given kind if @p val is the result of such an instruction. +/// Otherwise returns nullptr. +template +InstClass* As(Value* val) { + if (auto* instres = val->As()) { + return instres->Instruction()->As(); + } + return nullptr; +} + +/// Returns the value, after unwrapping all bitcasts. +Value* UnwrapBitcast(Value* val) { + while (auto* bitcast = As(val)) { + val = bitcast->Val(); + } + return val; +} + +/// Returns true if v is the integer constant 1. +bool IsOne(Value* v) { + if (auto* cv = v->As()) { + return Switch( + cv->Type(), + [&](const core::type::I32*) { return cv->Value()->ValueAs() == 1; }, + [&](const core::type::U32*) { return cv->Value()->ValueAs() == 1; }, + [&](const Default) -> bool { return false; }); + } + return false; +} + +/// Returns `true` if `val` is definitely `var +/- 1`. +bool IsIncrementOrDecrementOfVar(const Var& var, Value* val) { + auto is_var_op_one = [&](Value* a, Value* b) { + if (auto* a_load = As(a)) { + return (a_load->From() == var.Result()) && IsOne(b); + } + return false; + }; + if (auto* binary = As(UnwrapBitcast(val))) { + auto* lhs = UnwrapBitcast(binary->LHS()); + auto* rhs = UnwrapBitcast(binary->RHS()); + if (binary->Op() == BinaryOp::kAdd) { + // Allow `var + 1` or `1 + var`. + return is_var_op_one(lhs, rhs) || is_var_op_one(rhs, lhs); + } else if (binary->Op() == BinaryOp::kSubtract) { + // Only allow `var - 1`. + return is_var_op_one(lhs, rhs); + } + } + return false; +} + +} // anonymous namespace + +/// PIMPL class that performs the analysis and holds the analysis cache. +struct LoopAnalysisImpl { + explicit LoopAnalysisImpl(Function& func) { + // Analyze all of the loops in the function. + Traverse(func.Block(), [&](Loop* l) { AnalyzeLoop(*l); }); + } + + /// @returns the info for a loop + const LoopInfo* GetInfo(const Loop& loop) const { return loop_info_map_.Get(&loop).value; } + + private: + Hashmap loop_info_map_; + + /// Analyze a loop. + void AnalyzeLoop(Loop& loop) { + if (auto* init_block = loop.Initializer()) { + // Look for variables that could be used as iteration indices. + for (auto* inst : *init_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + + const auto* pty = var->Result()->Type()->As(); + if (!pty->StoreType()->IsIntegerScalar()) { + break; + } + + // Check if the variable is an index that gives this loop a finite range. + if (IsFiniteLoopIndex(loop, *var)) { + loop_info_map_.Add(&loop, LoopInfo{var}); + return; + } + } + } + + // We could not determine that this was a finite loop. + loop_info_map_.Add(&loop, LoopInfo{}); + } + + /// Analyzes @p var as a candidate loop index variable for the given @p loop to see if it is + /// used in a way that guarantees the loop will be iterating over a finite range. + /// @returns true if @p var is an index variable for a finite ranged loop + bool IsFiniteLoopIndex(Loop& loop, Var& index) { + // Look for a store to the index in the continuing block. + // Make sure there is only one, and make sure that the only other uses are loads. + Store* single_store_in_continue_block = nullptr; + const auto& uses = index.Result()->UsagesUnsorted(); + for (auto& use : uses) { + if (auto* store = use->instruction->As()) { + if (store->Block() != loop.Continuing()) { + // Not in the continuing block, so we cannot easily prove that it will be + // executed. + return false; + } + if (single_store_in_continue_block) { + // Found more than one store, so we cannot easily analyze this candidate. + return false; + } + single_store_in_continue_block = store; + } else if (!use->instruction->Is()) { + // Not a store or a load, so reject this candidate. + return false; + } + } + if (!single_store_in_continue_block) { + return false; + } + + // Check that the store we found is either incrementing or decrementing the index by `1`. + if (!IsIncrementOrDecrementOfVar(index, single_store_in_continue_block->From())) { + return false; + } + + // We have proven that the variable increments exactly once per iteration. + // Now check that the loop body begins with a break-if construct that will is guaranteed to + // exit the loop if the index reaches the loop bound. + bool has_break_if = false; + for (auto* inst : *loop.Body()) { + // The Switch returns `true` if more instructions should be checked, otherwise `false`. + bool keep_going = Switch( + inst, // + [&](Load*) { return true; }, // + [&](Bitcast*) { return true; }, // + [&](Binary*) { return true; }, // + [&](If* i) { + if (IsBreakIfOnIndex(loop, i, index)) { + // The loop is finite. + has_break_if = true; + } + // Only look at the first 'if' we find. + return false; + }, + [&](Default) { return false; }); + if (!keep_going) { + break; + } + } + return has_break_if; + } + + /// @returns `true` if @p is a break-if construct that exits the loop based on @p index. + bool IsBreakIfOnIndex(const Loop& loop, If* i, Var& index) { + // Returns `true` if the given value is a load of the index variable. + auto is_index = [&index](Value* v) { + if (auto* load = As(UnwrapBitcast(v))) { + return load->From() == index.Result(); + } + return false; + }; + // Returns `true` if the given value an immutable value declared before the loop body. + auto is_immutable_before_body = [&loop](Value* v) { + return tint::Switch( + UnwrapBitcast(v), // + [](ir::Constant*) { return true; }, // + [](ir::FunctionParam*) { return true; }, // + [&](ir::InstructionResult* r) { + auto* let = r->Instruction()->As(); + return let && let->Block() != loop.Body(); + } // + ); + }; + auto is_constant_i32_or_u32 = [](Value* v) { + auto* constant_value = v->As(); + if (!constant_value) { + return false; + } + return constant_value->Type()->IsAnyOf(); + }; + auto is_capable_binary_for_loop_exit = [&](Binary* binary) { + switch (binary->Op()) { + case BinaryOp::kLessThan: + case BinaryOp::kGreaterThan: { + return (is_index(binary->LHS()) && is_immutable_before_body(binary->RHS())) || + (is_index(binary->RHS()) && is_immutable_before_body(binary->LHS())); + } + case BinaryOp::kLessThanEqual: { + if (is_index(binary->LHS()) && is_constant_i32_or_u32(binary->RHS())) { + // index <= kConstantValue + // `kConstantValue` being the highest value will cause an infinite loop. + auto* constant_value = binary->RHS()->As()->Value(); + if (constant_value->Type()->Is()) { + return constant_value->ValueAs() < i32::kHighestValue; + } else { + TINT_ASSERT(constant_value->Type()->Is()); + return constant_value->ValueAs() < u32::kHighestValue; + } + } else if (is_index(binary->RHS()) && is_constant_i32_or_u32(binary->LHS())) { + // kConstantValue <= index + // `kConstantValue` being the lowest value will cause an infinite loop. + auto* constant_value = binary->LHS()->As()->Value(); + if (constant_value->Type()->Is()) { + return constant_value->ValueAs() > i32::kLowestValue; + } else { + TINT_ASSERT(constant_value->Type()->Is()); + return constant_value->ValueAs() > u32::kLowestValue; + } + } + return false; + } + case BinaryOp::kGreaterThanEqual: { + if (is_index(binary->LHS()) && is_constant_i32_or_u32(binary->RHS())) { + // index >= kConstantValue + // `kConstantValue` being the lowest value will cause an infinite loop. + auto* constant_value = binary->RHS()->As()->Value(); + if (constant_value->Type()->Is()) { + return constant_value->ValueAs() > i32::kLowestValue; + } else { + TINT_ASSERT(constant_value->Type()->Is()); + return constant_value->ValueAs() > u32::kLowestValue; + } + } else if (is_index(binary->RHS()) && is_constant_i32_or_u32(binary->LHS())) { + // kConstantValue >= index + // `kConstantValue` being the highest value will cause an infinite loop. + auto* constant_value = binary->LHS()->As()->Value(); + if (constant_value->Type()->Is()) { + return constant_value->ValueAs() < i32::kHighestValue; + } else { + TINT_ASSERT(constant_value->Type()->Is()); + return constant_value->ValueAs() < u32::kHighestValue; + } + } + return false; + } + default: + return false; + } + }; + + // Check if the condition matches (%idx < %bound) or (%idx > %bound). + // The value %bound can be any immutable value that was declared before the body. + auto* binary = As(i->Condition()); + if (!binary) { + return false; + } + if (is_capable_binary_for_loop_exit(binary)) { + // The condition matches, so now make sure that one of the branches will exit from the + // loop and do nothing else. + auto is_simple_loop_exit = [](Block* b) { + return b && !b->IsEmpty() && (b->Front()->Is()); + }; + return is_simple_loop_exit(i->True()) || is_simple_loop_exit(i->False()); + } + return false; + } +}; + +LoopAnalysis::LoopAnalysis(Function& func) : impl_(new LoopAnalysisImpl(func)) {} +LoopAnalysis::~LoopAnalysis() = default; + +const LoopInfo* LoopAnalysis::GetInfo(const Loop& loop) const { + return impl_->GetInfo(loop); +} + +} // namespace tint::core::ir::analysis diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.h b/3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.h new file mode 100644 index 000000000..c431c637c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/loop_analysis.h @@ -0,0 +1,73 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_ANALYSIS_LOOP_ANALYSIS_H_ +#define SRC_TINT_LANG_CORE_IR_ANALYSIS_LOOP_ANALYSIS_H_ + +#include + +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/var.h" + +namespace tint::core::ir::analysis { + +/// The result of a loop analysis. +struct LoopInfo { + Var* const index_var = nullptr; + + /// @returns `true` if the loop is definitely finite, otherwise `false`. + bool IsFinite() const { return index_var != nullptr; } +}; + +struct LoopAnalysisImpl; + +/// LoopAnalysis is a helper used to analyze loops. +/// It caches loop analyses for a function. +class LoopAnalysis { + public: + /// Constructor + /// @param func the function to cache analyses for + explicit LoopAnalysis(ir::Function& func); + ~LoopAnalysis(); + + /// Returns the info for a given loop, if it is a loop. + /// Otherwise is not analyzable, and returns nullptr. + /// @param loop the loop to get information about + /// @returns the loop info + const LoopInfo* GetInfo(const Loop& loop) const; + + private: + LoopAnalysis(const LoopAnalysis&) = delete; + LoopAnalysis(LoopAnalysis&&) = delete; + + std::unique_ptr impl_; +}; + +} // namespace tint::core::ir::analysis + +#endif // SRC_TINT_LANG_CORE_IR_ANALYSIS_LOOP_ANALYSIS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.cc b/3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.cc new file mode 100644 index 000000000..7150811ee --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.cc @@ -0,0 +1,169 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/analysis/subgroup_matrix.h" + +#include +#include + +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/subgroup_matrix.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir::analysis { +namespace { + +struct State { + /// The IR module. + core::ir::Module& ir; + + SubgroupMatrixInfo info{}; + + /// Process the module. + SubgroupMatrixInfo Process() { + for (const auto* inst : ir.Instructions()) { + if (auto* call = inst->As()) { + GatherCall(call); + } + + for (auto* res : inst->Results()) { + GatherType(res->Type()->UnwrapPtr()); + } + } + + return std::move(info); + } + + SubgroupMatrixType TypeToSMType(const core::type::Type* ty) { + return tint::Switch( + ty, // + [&](const core::type::F16*) { return SubgroupMatrixType::kF16; }, + [&](const core::type::F32*) { return SubgroupMatrixType::kF32; }, + [&](const core::type::U8*) { return SubgroupMatrixType::kU8; }, + [&](const core::type::I8*) { return SubgroupMatrixType::kI8; }, + [&](const core::type::U32*) { return SubgroupMatrixType::kU32; }, + [&](const core::type::I32*) { return SubgroupMatrixType::kI32; }, // + TINT_ICE_ON_NO_MATCH); + } + + void GatherCall(const core::ir::CoreBuiltinCall* call) { + if (call->Func() != BuiltinFn::kSubgroupMatrixMultiply && + call->Func() != BuiltinFn::kSubgroupMatrixMultiplyAccumulate) { + return; + } + + auto* result_ty = call->Result()->Type()->As(); + TINT_ASSERT(result_ty); + + auto* left_ty = call->Args()[0]->Type()->As(); + TINT_ASSERT(left_ty); + + auto* right_ty = call->Args()[1]->Type()->As(); + TINT_ASSERT(right_ty); + + SubgroupMatrixMultiply cfg{ + .M = left_ty->Rows(), + .N = right_ty->Columns(), + .K = right_ty->Rows(), + .input_type = TypeToSMType(left_ty->Type()), + .output_type = TypeToSMType(result_ty->Type()), + }; + + info.multiplies.insert(cfg); + } + + void GatherType(const core::type::Type* ty) { + if (auto* str = ty->As()) { + for (auto* mem : str->Members()) { + GatherType(mem->Type()); + } + return; + } + if (auto* arr = ty->As()) { + GatherType(arr->ElemType()); + return; + } + + auto* sm = ty->As(); + if (!sm) { + return; + } + + SubgroupMatrixDirection dir = SubgroupMatrixDirection::kResult; + + uint32_t M = 0; + uint32_t N = 0; + uint32_t K = 0; + + switch (sm->Kind()) { + case SubgroupMatrixKind::kResult: + dir = SubgroupMatrixDirection::kResult; + M = sm->Rows(); + N = sm->Columns(); + break; + case SubgroupMatrixKind::kLeft: + dir = SubgroupMatrixDirection::kLeft; + M = sm->Rows(); + K = sm->Columns(); + break; + case SubgroupMatrixKind::kRight: + dir = SubgroupMatrixDirection::kRight; + K = sm->Rows(); + N = sm->Columns(); + break; + case SubgroupMatrixKind::kUndefined: + TINT_UNREACHABLE(); + } + + SubgroupMatrixConfig cfg{ + .M = M, + .N = N, + .K = K, + .type = TypeToSMType(sm->Type()), + .direction = dir, + }; + + info.configs.insert(cfg); + } +}; + +} // namespace + +SubgroupMatrixInfo GatherSubgroupMatrixInfo(core::ir::Module& ir) { + return State{ir}.Process(); +} + +} // namespace tint::core::ir::analysis diff --git a/3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.h b/3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.h new file mode 100644 index 000000000..6283ed2f4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/analysis/subgroup_matrix.h @@ -0,0 +1,60 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_ANALYSIS_SUBGROUP_MATRIX_H_ +#define SRC_TINT_LANG_CORE_IR_ANALYSIS_SUBGROUP_MATRIX_H_ + +#include "src/tint/api/common/subgroup_matrix.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::analysis { + +/// Gathers information about the subgroup matrix configurations used in the module. +/// +/// This returns two fundamental types of information on the subgroup matrix uses. +/// +/// 1. The Matrix multiply configurations +/// * This provides the `M`, `N`, `K`, input and output types for the +/// `subgroupMatrixMultiply` and `subgroupMatrtixMultiplyAccumulate` calls in the +/// module. (The configs are de-duplicated so each combination is only returned once.) +/// +/// 2. The used matrix configurations +/// * This provides the `C`, `R`, type and if it's left/right (input) or result usage for +/// every subgroup matrix seen in the file. (The configs are de-duplicated so each +/// combination is only returned once.) +/// +/// @param module the module to transform +/// @returns the subgroup matrix information +SubgroupMatrixInfo GatherSubgroupMatrixInfo(core::ir::Module& module); + +} // namespace tint::core::ir::analysis + +#endif // SRC_TINT_LANG_CORE_IR_ANALYSIS_SUBGROUP_MATRIX_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/binary.cc b/3rdparty/dawn/src/tint/lang/core/ir/binary.cc new file mode 100644 index 000000000..081e33fa2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/binary.cc @@ -0,0 +1,48 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/binary.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Binary); + +namespace tint::core::ir { + +Binary::Binary(Id id) : Base(id) {} + +Binary::Binary(Id id, InstructionResult* result, BinaryOp op, Value* lhs, Value* rhs) + : Base(id), op_(op) { + AddOperand(Binary::kLhsOperandOffset, lhs); + AddOperand(Binary::kRhsOperandOffset, rhs); + AddResult(result); +} + +Binary::~Binary() = default; + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/binary.h b/3rdparty/dawn/src/tint/lang/core/ir/binary.h new file mode 100644 index 000000000..cefae724b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/binary.h @@ -0,0 +1,101 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BINARY_H_ +#define SRC_TINT_LANG_CORE_IR_BINARY_H_ + +#include + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/ir/operand_instruction.h" + +// Forward declarations +namespace tint::core::intrinsic { +struct TableData; +} + +namespace tint::core::ir { + +/// The abstract base class for dialect-specific binary-op instructions in the IR. +class Binary : public Castable> { + 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 fixed number of results returned by binary instructions + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands expected for binary instructions + static constexpr size_t kNumOperands = 2; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Binary(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param op the binary operator + /// @param lhs the lhs of the instruction + /// @param rhs the rhs of the instruction + Binary(Id id, InstructionResult* result, BinaryOp op, Value* lhs, Value* rhs); + ~Binary() override; + + /// @returns the binary operator + BinaryOp Op() const { return op_; } + + /// @param op the new binary operator + void SetOp(BinaryOp op) { op_ = op; } + + /// @returns the left-hand-side value for the instruction + Value* LHS() { return Operand(kLhsOperandOffset); } + + /// @returns the left-hand-side value for the instruction + const Value* LHS() const { return Operand(kLhsOperandOffset); } + + /// @returns the right-hand-side value for the instruction + Value* RHS() { return Operand(kRhsOperandOffset); } + + /// @returns the right-hand-side value for the instruction + const Value* RHS() const { return Operand(kRhsOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "binary"; } + + /// @returns the table data to validate this builtin + virtual const core::intrinsic::TableData& TableData() const = 0; + + private: + BinaryOp op_ = BinaryOp::kAdd; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BINARY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/binary/decode.cc b/3rdparty/dawn/src/tint/lang/core/ir/binary/decode.cc new file mode 100644 index 000000000..c9c961015 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/binary/decode.cc @@ -0,0 +1,2097 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/binary/decode.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/function.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/invalid.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/internal_limits.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/result.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/text_style.h" + +TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS(); +#include "src/tint/utils/protos/ir/ir.pb.h" +TINT_END_DISABLE_PROTOBUF_WARNINGS(); + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::core::ir::binary { +namespace { + +struct Decoder { + const pb::Module& mod_in_; + + Module mod_out_{}; + Vector blocks_{}; + Vector types_{}; + Vector constant_values_{}; + Vector values_{}; + Builder b{mod_out_}; + + Vector exit_ifs_{}; + Vector exit_switches_{}; + Vector exit_loops_{}; + Vector next_iterations_{}; + Vector break_ifs_{}; + Vector continues_{}; + + std::stringstream err_{}; + Hashset struct_names_{}; + + Result Decode() { + { + const size_t n = static_cast(mod_in_.types().size()); + types_.Reserve(n); + for (auto& type_in : mod_in_.types()) { + types_.Push(CreateType(type_in)); + } + } + { + const size_t n = static_cast(mod_in_.functions().size()); + mod_out_.functions.Reserve(n); + for (auto& fn_in : mod_in_.functions()) { + mod_out_.functions.Push(CreateFunction(fn_in)); + } + } + { + const size_t n = static_cast(mod_in_.blocks().size()); + blocks_.Reserve(n); + for (size_t i = 0; i < n; i++) { + auto id = static_cast(i); + if (id == mod_in_.root_block()) { + blocks_.Push(mod_out_.root_block); + } else { + auto& block_in = mod_in_.blocks()[static_cast(i)]; + blocks_.Push(CreateBlock(block_in)); + } + } + } + { + const size_t n = static_cast(mod_in_.constant_values().size()); + constant_values_.Reserve(n); + for (auto& value_in : mod_in_.constant_values()) { + constant_values_.Push(CreateConstantValue(value_in)); + } + } + { + const size_t n = static_cast(mod_in_.values().size()); + values_.Reserve(n); + for (auto& value_in : mod_in_.values()) { + values_.Push(CreateValue(value_in)); + } + } + for (size_t i = 0, n = static_cast(mod_in_.functions().size()); i < n; i++) { + PopulateFunction(mod_out_.functions[i], mod_in_.functions()[static_cast(i)]); + } + for (size_t i = 0, n = static_cast(mod_in_.blocks().size()); i < n; i++) { + PopulateBlock(blocks_[i], mod_in_.blocks()[static_cast(i)]); + } + + auto err = err_.str(); + if (!err.empty()) { + // Note: Its not safe to call InferControlInstruction() with a broken IR. + return Failure{err}; + } + + if (CheckBlocks()) { + for (auto* exit : exit_ifs_) { + InferControlInstruction(exit, &ExitIf::SetIf); + } + for (auto* exit : exit_switches_) { + InferControlInstruction(exit, &ExitSwitch::SetSwitch); + } + for (auto* exit : exit_loops_) { + InferControlInstruction(exit, &ExitLoop::SetLoop); + } + for (auto* break_ifs : break_ifs_) { + InferControlInstruction(break_ifs, &BreakIf::SetLoop); + } + for (auto* next_iters : next_iterations_) { + InferControlInstruction(next_iters, &NextIteration::SetLoop); + } + for (auto* cont : continues_) { + InferControlInstruction(cont, &Continue::SetLoop); + } + } + + err = err_.str(); + if (!err.empty()) { + return Failure{err}; + } + return std::move(mod_out_); + } + + /// Errors if @p number is not finite. + /// @returns @p number if finite, otherwise 0. + template + Number CheckFinite(Number number) { + if (DAWN_UNLIKELY(!std::isfinite(number.value))) { + err_ << "value must be finite\n"; + return Number{}; + } + return number; + } + + /// Checks that the given @p name is valid. + /// @returns true if the name is valid. + bool CheckName(const std::string& name, const char* kind) { + if (DAWN_UNLIKELY(name.find('\0') != std::string::npos)) { + err_ << kind << " '" << name << "' contains '\\0' before end of the string\n"; + return false; + } + + // Reject excessively long names as they cause problems in some backends. + if (DAWN_UNLIKELY(name.length() > 16384)) { + err_ << kind << " '" << name << "' is longer than 16384 characters\n"; + return false; + } + return true; + } + + /// @returns true if all blocks are reachable, acyclic nesting depth is less than or equal to + /// kMaxBlockDepth. + bool CheckBlocks() { + const size_t kMaxBlockDepth = 128; + Vector, 32> pending; + pending.Push(std::make_pair(mod_out_.root_block, 0)); + for (auto& fn : mod_out_.functions) { + pending.Push(std::make_pair(fn->Block(), 0)); + } + Hashset seen; + while (!pending.IsEmpty()) { + const auto block_depth = pending.Pop(); + const auto* block = block_depth.first; + const size_t depth = block_depth.second; + if (!seen.Add(block)) { + err_ << "cyclic nesting of blocks\n"; + return false; + } + if (depth > kMaxBlockDepth) { + err_ << "block nesting exceeds " << kMaxBlockDepth << "\n"; + return false; + } + for (auto* inst = block->Instructions(); inst; inst = inst->next) { + if (auto* ctrl = inst->As()) { + ctrl->ForeachBlock([&](const ir::Block* child) { + pending.Push(std::make_pair(child, depth + 1)); + }); + } + } + } + + for (auto* block : blocks_) { + if (!seen.Contains(block)) { + err_ << "unreachable block\n"; + return false; + } + } + + return true; + } + + template + void InferControlInstruction(EXIT* exit, void (EXIT::*set)(CTRL_INST*)) { + for (auto* block = exit->Block(); block;) { + auto* parent = block->Parent(); + if (!parent) { + break; + } + if (auto* ctrl_inst = parent->template As()) { + (exit->*set)(ctrl_inst); + break; + } + block = parent->Block(); + } + } + + //////////////////////////////////////////////////////////////////////////// + // Functions + //////////////////////////////////////////////////////////////////////////// + ir::Function* CreateFunction(const pb::Function&) { + auto* result = mod_out_.CreateValue(); + result->SetType(mod_out_.Types().function()); + return result; + } + + void PopulateFunction(ir::Function* fn_out, const pb::Function& fn_in) { + if (!fn_in.name().empty()) { + if (CheckName(fn_in.name(), "function name")) { + mod_out_.SetName(fn_out, fn_in.name()); + } + } + fn_out->SetReturnType(Type(fn_in.return_type())); + if (fn_in.has_pipeline_stage()) { + if (PipelineStage_IsValid(fn_in.pipeline_stage())) { + fn_out->SetStage(PipelineStage(fn_in.pipeline_stage())); + } else { + err_ << "invalid pipe line state, " << std::to_string(fn_in.pipeline_stage()) + << "\n"; + } + } + if (fn_in.has_workgroup_size()) { + auto& wg_size_in = fn_in.workgroup_size(); + // TODO(dsinclair): When overrides are supported we should add support for generating + // override expressions here. + fn_out->SetWorkgroupSize(Value(wg_size_in.x()), Value(wg_size_in.y()), + Value(wg_size_in.z())); + } + + if (fn_in.has_subgroup_size()) { + uint32_t subgroup_size_in = fn_in.subgroup_size(); + fn_out->SetSubgroupSize(Value(subgroup_size_in)); + } + + Vector params_out; + for (auto param_in : fn_in.parameters()) { + auto* param_out = ValueAs(param_in); + if (DAWN_LIKELY(param_out)) { + params_out.Push(param_out); + } + } + if (fn_in.has_return_location()) { + fn_out->SetReturnLocation(fn_in.return_location()); + } + if (fn_in.has_return_interpolation()) { + fn_out->SetReturnInterpolation(Interpolation(fn_in.return_interpolation())); + } + if (fn_in.has_return_builtin()) { + fn_out->SetReturnBuiltin(BuiltinValue(fn_in.return_builtin())); + } + if (fn_in.return_invariant()) { + fn_out->SetReturnInvariant(true); + } + fn_out->SetParams(std::move(params_out)); + fn_out->SetBlock(Block(fn_in.block())); + } + + ir::Function* Function(uint32_t id) { + if (DAWN_UNLIKELY(id >= mod_out_.functions.Length())) { + err_ << "function id " << id << " out of range\n"; + return nullptr; + } + return mod_out_.functions[id]; + } + + Function::PipelineStage PipelineStage(pb::PipelineStage stage) { + switch (stage) { + case pb::PipelineStage::Compute: + return Function::PipelineStage::kCompute; + case pb::PipelineStage::Fragment: + return Function::PipelineStage::kFragment; + case pb::PipelineStage::Vertex: + return Function::PipelineStage::kVertex; + + case pb::PipelineStage::PipelineStage_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::PipelineStage::PipelineStage_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "unhandled PipelineStage: " << stage; + } + + //////////////////////////////////////////////////////////////////////////// + // Blocks + //////////////////////////////////////////////////////////////////////////// + ir::Block* CreateBlock(const pb::Block& block_in) { + return block_in.is_multi_in() ? b.MultiInBlock() : b.Block(); + } + + void PopulateBlock(ir::Block* block_out, const pb::Block& block_in) { + if (auto* mib = block_out->As()) { + Vector params; + for (auto param_in : block_in.parameters()) { + auto* param_out = ValueAs(param_in); + if (DAWN_LIKELY(param_out)) { + params.Push(param_out); + } + } + mib->SetParams(std::move(params)); + } + for (auto& inst : block_in.instructions()) { + block_out->Append(Instruction(inst)); + } + } + + ir::Block* Block(uint32_t id) { + if (DAWN_UNLIKELY(id >= blocks_.Length())) { + err_ << "block id " << id << " out of range\n"; + return b.Block(); + } + return blocks_[id]; + } + + template + T* BlockAs(uint32_t id) { + auto* block = Block(id); + if (auto cast = As(block); DAWN_LIKELY(cast)) { + return cast; + } + err_ << "block " << id << " is " << (block ? block->TypeInfo().name : "") + << " expected " << TypeInfo::Of().name << "\n"; + return nullptr; + } + + //////////////////////////////////////////////////////////////////////////// + // Instructions + //////////////////////////////////////////////////////////////////////////// + ir::Instruction* Instruction(const pb::Instruction& inst_in) { + ir::Instruction* inst_out = nullptr; + switch (inst_in.kind_case()) { + case pb::Instruction::KindCase::kAccess: + inst_out = CreateInstructionAccess(inst_in.access()); + break; + case pb::Instruction::KindCase::kBinary: + inst_out = CreateInstructionBinary(inst_in.binary()); + break; + case pb::Instruction::KindCase::kBitcast: + inst_out = CreateInstructionBitcast(inst_in.bitcast()); + break; + case pb::Instruction::KindCase::kBreakIf: + inst_out = CreateInstructionBreakIf(inst_in.break_if()); + break; + case pb::Instruction::KindCase::kBuiltinCall: + inst_out = CreateInstructionBuiltinCall(inst_in.builtin_call()); + break; + case pb::Instruction::KindCase::kConstruct: + inst_out = CreateInstructionConstruct(inst_in.construct()); + break; + case pb::Instruction::KindCase::kContinue: + inst_out = CreateInstructionContinue(inst_in.continue_()); + break; + case pb::Instruction::KindCase::kConvert: + inst_out = CreateInstructionConvert(inst_in.convert()); + break; + case pb::Instruction::KindCase::kExitIf: + inst_out = CreateInstructionExitIf(inst_in.exit_if()); + break; + case pb::Instruction::KindCase::kExitLoop: + inst_out = CreateInstructionExitLoop(inst_in.exit_loop()); + break; + case pb::Instruction::KindCase::kExitSwitch: + inst_out = CreateInstructionExitSwitch(inst_in.exit_switch()); + break; + case pb::Instruction::KindCase::kDiscard: + inst_out = CreateInstructionDiscard(inst_in.discard()); + break; + case pb::Instruction::KindCase::kIf: + inst_out = CreateInstructionIf(inst_in.if_()); + break; + case pb::Instruction::KindCase::kLet: + inst_out = CreateInstructionLet(inst_in.let()); + break; + case pb::Instruction::KindCase::kLoad: + inst_out = CreateInstructionLoad(inst_in.load()); + break; + case pb::Instruction::KindCase::kLoadVectorElement: + inst_out = CreateInstructionLoadVectorElement(inst_in.load_vector_element()); + break; + case pb::Instruction::KindCase::kLoop: + inst_out = CreateInstructionLoop(inst_in.loop()); + break; + case pb::Instruction::KindCase::kNextIteration: + inst_out = CreateInstructionNextIteration(inst_in.next_iteration()); + break; + case pb::Instruction::KindCase::kReturn: + inst_out = CreateInstructionReturn(inst_in.return_()); + break; + case pb::Instruction::KindCase::kStore: + inst_out = CreateInstructionStore(inst_in.store()); + break; + case pb::Instruction::KindCase::kStoreVectorElement: + inst_out = CreateInstructionStoreVectorElement(inst_in.store_vector_element()); + break; + case pb::Instruction::KindCase::kSwizzle: + inst_out = CreateInstructionSwizzle(inst_in.swizzle()); + break; + case pb::Instruction::KindCase::kSwitch: + inst_out = CreateInstructionSwitch(inst_in.switch_()); + break; + case pb::Instruction::KindCase::kUnary: + inst_out = CreateInstructionUnary(inst_in.unary()); + break; + case pb::Instruction::KindCase::kUserCall: + inst_out = CreateInstructionUserCall(inst_in.user_call()); + break; + case pb::Instruction::KindCase::kVar: + inst_out = CreateInstructionVar(inst_in.var()); + break; + case pb::Instruction::KindCase::kUnreachable: + inst_out = CreateInstructionUnreachable(inst_in.unreachable()); + break; + case pb::Instruction::KindCase::KIND_NOT_SET: + break; + } + if (!inst_out) { + err_ << "invalid Instruction.kind: " << std::to_string(inst_in.kind_case()) << "\n"; + return b.Let(mod_out_.Types().invalid()); + } + + TINT_ASSERT(inst_out); + + Vector operands; + for (auto id : inst_in.operands()) { + operands.Push(Value(id)); + } + inst_out->SetOperands(std::move(operands)); + + Vector results; + for (auto id : inst_in.results()) { + results.Push(ValueAs(id)); + } + inst_out->SetResults(std::move(results)); + + if (inst_in.has_break_if()) { + auto num_next_iter_values = inst_in.break_if().num_next_iter_values(); + bool is_valid = + inst_out->Operands().Length() >= num_next_iter_values + BreakIf::kArgsOperandOffset; + if (DAWN_LIKELY(is_valid)) { + static_cast(inst_out)->SetNumNextIterValues( + inst_in.break_if().num_next_iter_values()); + } else { + err_ << "invalid value for num_next_iter_values()\n"; + } + } + + return inst_out; + } + + ir::Access* CreateInstructionAccess(const pb::InstructionAccess&) { + return mod_out_.CreateInstruction(); + } + + ir::CoreBinary* CreateInstructionBinary(const pb::InstructionBinary& binary_in) { + if (!BinaryOp_IsValid(binary_in.op())) { + err_ << "invalid binary op, " << std::to_string(binary_in.op()) << "\n"; + return nullptr; + } + + auto* binary_out = mod_out_.CreateInstruction(); + binary_out->SetOp(BinaryOp(binary_in.op())); + return binary_out; + } + + ir::Bitcast* CreateInstructionBitcast(const pb::InstructionBitcast&) { + return mod_out_.CreateInstruction(); + } + + ir::BreakIf* CreateInstructionBreakIf(const pb::InstructionBreakIf&) { + auto* break_if_out = mod_out_.CreateInstruction(); + break_ifs_.Push(break_if_out); + return break_if_out; + } + + ir::CoreBuiltinCall* CreateInstructionBuiltinCall(const pb::InstructionBuiltinCall& call_in) { + auto* call_out = mod_out_.CreateInstruction(); + call_out->SetFunc(BuiltinFn(call_in.builtin())); + Vector params; + for (auto param : call_in.explicit_template_params()) { + params.Push(Type(param)); + } + call_out->SetExplicitTemplateParams(params); + return call_out; + } + + ir::Construct* CreateInstructionConstruct(const pb::InstructionConstruct&) { + return mod_out_.CreateInstruction(); + } + + ir::Continue* CreateInstructionContinue(const pb::InstructionContinue&) { + auto* continue_ = mod_out_.CreateInstruction(); + continues_.Push(continue_); + return continue_; + } + + ir::Convert* CreateInstructionConvert(const pb::InstructionConvert&) { + return mod_out_.CreateInstruction(); + } + + ir::ExitIf* CreateInstructionExitIf(const pb::InstructionExitIf&) { + auto* exit_out = mod_out_.CreateInstruction(); + exit_ifs_.Push(exit_out); + return exit_out; + } + + ir::ExitLoop* CreateInstructionExitLoop(const pb::InstructionExitLoop&) { + auto* exit_out = mod_out_.CreateInstruction(); + exit_loops_.Push(exit_out); + return exit_out; + } + + ir::ExitSwitch* CreateInstructionExitSwitch(const pb::InstructionExitSwitch&) { + auto* exit_out = mod_out_.CreateInstruction(); + exit_switches_.Push(exit_out); + return exit_out; + } + + ir::Discard* CreateInstructionDiscard(const pb::InstructionDiscard&) { + return mod_out_.CreateInstruction(); + } + + ir::If* CreateInstructionIf(const pb::InstructionIf& if_in) { + auto* if_out = mod_out_.CreateInstruction(); + if_out->SetTrue(if_in.has_true_() ? Block(if_in.true_()) : b.Block()); + if_out->SetFalse(if_in.has_false_() ? Block(if_in.false_()) : b.Block()); + return if_out; + } + + ir::Let* CreateInstructionLet(const pb::InstructionLet&) { + return mod_out_.CreateInstruction(); + } + + ir::Load* CreateInstructionLoad(const pb::InstructionLoad&) { + return mod_out_.CreateInstruction(); + } + + ir::LoadVectorElement* CreateInstructionLoadVectorElement( + const pb::InstructionLoadVectorElement&) { + return mod_out_.CreateInstruction(); + } + + ir::Loop* CreateInstructionLoop(const pb::InstructionLoop& loop_in) { + auto* loop_out = mod_out_.CreateInstruction(); + if (loop_in.has_initializer()) { + loop_out->SetInitializer(Block(loop_in.initializer())); + } else { + loop_out->SetInitializer(b.Block()); + } + loop_out->SetBody(BlockAs(loop_in.body())); + if (loop_in.has_continuing()) { + loop_out->SetContinuing(BlockAs(loop_in.continuing())); + } else { + loop_out->SetContinuing(b.MultiInBlock()); + } + return loop_out; + } + + ir::NextIteration* CreateInstructionNextIteration(const pb::InstructionNextIteration&) { + auto* next_it_out = mod_out_.CreateInstruction(); + next_iterations_.Push(next_it_out); + return next_it_out; + } + + ir::Return* CreateInstructionReturn(const pb::InstructionReturn&) { + return mod_out_.CreateInstruction(); + } + + ir::Store* CreateInstructionStore(const pb::InstructionStore&) { + return mod_out_.CreateInstruction(); + } + + ir::StoreVectorElement* CreateInstructionStoreVectorElement( + const pb::InstructionStoreVectorElement&) { + return mod_out_.CreateInstruction(); + } + + ir::Swizzle* CreateInstructionSwizzle(const pb::InstructionSwizzle& swizzle_in) { + auto* swizzle_out = mod_out_.CreateInstruction(); + Vector indices; + for (auto idx : swizzle_in.indices()) { + indices.Push(idx); + } + swizzle_out->SetIndices(indices); + return swizzle_out; + } + + ir::Switch* CreateInstructionSwitch(const pb::InstructionSwitch& switch_in) { + auto* switch_out = mod_out_.CreateInstruction(); + for (auto& case_in : switch_in.cases()) { + ir::Switch::Case case_out{}; + case_out.block = Block(case_in.block()); + case_out.block->SetParent(switch_out); + for (auto selector_in : case_in.selectors()) { + ir::Switch::CaseSelector selector_out{}; + selector_out.val = Constant(selector_in); + case_out.selectors.Push(std::move(selector_out)); + } + if (case_in.is_default()) { + ir::Switch::CaseSelector selector_out{}; + case_out.selectors.Push(std::move(selector_out)); + } + switch_out->Cases().Push(std::move(case_out)); + } + return switch_out; + } + + ir::CoreUnary* CreateInstructionUnary(const pb::InstructionUnary& unary_in) { + if (!UnaryOp_IsValid(unary_in.op())) { + err_ << "invalid unary op, " << std::to_string(unary_in.op()) << "\n"; + return nullptr; + } + auto* unary_out = mod_out_.CreateInstruction(); + unary_out->SetOp(UnaryOp(unary_in.op())); + return unary_out; + } + + ir::UserCall* CreateInstructionUserCall(const pb::InstructionUserCall&) { + return mod_out_.CreateInstruction(); + } + + ir::Var* CreateInstructionVar(const pb::InstructionVar& var_in) { + auto* var_out = mod_out_.CreateInstruction(); + if (var_in.has_binding_point()) { + auto& bp_in = var_in.binding_point(); + var_out->SetBindingPoint(bp_in.group(), bp_in.binding()); + } + if (var_in.has_input_attachment_index()) { + var_out->SetInputAttachmentIndex(var_in.input_attachment_index()); + } + return var_out; + } + + ir::Unreachable* CreateInstructionUnreachable(const pb::InstructionUnreachable&) { + return b.Unreachable(); + } + + //////////////////////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////////////////////// + const type::Type* CreateType(const pb::Type type_in) { + switch (type_in.kind_case()) { + case pb::Type::KindCase::kBasic: + return CreateTypeBasic(type_in.basic()); + case pb::Type::KindCase::kVector: + return CreateTypeVector(type_in.vector()); + case pb::Type::KindCase::kMatrix: + return CreateTypeMatrix(type_in.matrix()); + case pb::Type::KindCase::kPointer: + return CreateTypePointer(type_in.pointer()); + case pb::Type::KindCase::kStruct: + return CreateTypeStruct(type_in.struct_()); + case pb::Type::KindCase::kAtomic: + return CreateTypeAtomic(type_in.atomic()); + case pb::Type::KindCase::kArray: + return CreateTypeArray(type_in.array()); + case pb::Type::KindCase::kBindingArray: + return CreateTypeBindingArray(type_in.binding_array()); + case pb::Type::KindCase::kTexelBuffer: + return CreateTypeTexelBuffer(type_in.texel_buffer()); + case pb::Type::KindCase::kDepthTexture: + return CreateTypeDepthTexture(type_in.depth_texture()); + case pb::Type::KindCase::kSampledTexture: + return CreateTypeSampledTexture(type_in.sampled_texture()); + case pb::Type::KindCase::kMultisampledTexture: + return CreateTypeMultisampledTexture(type_in.multisampled_texture()); + case pb::Type::KindCase::kDepthMultisampledTexture: + return CreateTypeDepthMultisampledTexture(type_in.depth_multisampled_texture()); + case pb::Type::KindCase::kStorageTexture: + return CreateTypeStorageTexture(type_in.storage_texture()); + case pb::Type::KindCase::kExternalTexture: + return CreateTypeExternalTexture(type_in.external_texture()); + case pb::Type::KindCase::kSampler: + return CreateTypeSampler(type_in.sampler()); + case pb::Type::KindCase::kInputAttachment: + return CreateTypeInputAttachment(type_in.input_attachment()); + case pb::Type::KindCase::kSubgroupMatrixLeft: + return CreateTypeSubgroupMatrix(SubgroupMatrixKind::kLeft, + type_in.subgroup_matrix_left()); + case pb::Type::KindCase::kSubgroupMatrixRight: + return CreateTypeSubgroupMatrix(SubgroupMatrixKind::kRight, + type_in.subgroup_matrix_right()); + case pb::Type::KindCase::kSubgroupMatrixResult: + return CreateTypeSubgroupMatrix(SubgroupMatrixKind::kResult, + type_in.subgroup_matrix_result()); + case pb::Type::KindCase::kBuiltinStruct: + return CreateTypeBuiltinStruct(type_in.builtin_struct()); + case pb::Type::KindCase::kBuffer: + return CreateTypeBuffer(type_in.buffer()); + case pb::Type::KindCase::KIND_NOT_SET: + break; + } + + err_ << "invalid Type.kind: " << std::to_string(type_in.kind_case()) << "\n"; + return mod_out_.Types().invalid(); + } + + const type::Type* CreateTypeBasic(pb::TypeBasic basic_in) { + if (!TypeBasic_IsValid(basic_in)) { + err_ << "invalid basic type, " << std::to_string(basic_in) << "\n"; + return mod_out_.Types().invalid(); + } + + switch (basic_in) { + case pb::TypeBasic::void_: + return mod_out_.Types().void_(); + case pb::TypeBasic::bool_: + return mod_out_.Types().bool_(); + case pb::TypeBasic::i32: + return mod_out_.Types().i32(); + case pb::TypeBasic::u32: + return mod_out_.Types().u32(); + case pb::TypeBasic::f32: + return mod_out_.Types().f32(); + case pb::TypeBasic::f16: + return mod_out_.Types().f16(); + case pb::TypeBasic::i8: + return mod_out_.Types().i8(); + case pb::TypeBasic::u8: + return mod_out_.Types().u8(); + + case pb::TypeBasic::TypeBasic_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::TypeBasic::TypeBasic_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + + err_ << "invalid TypeBasic: " << std::to_string(basic_in) << "\n"; + return mod_out_.Types().invalid(); + } + + const type::Type* CreateTypeVector(const pb::TypeVector& vector_in) { + const auto width = vector_in.width(); + if (DAWN_UNLIKELY(width < 2 || width > 4)) { + err_ << "invalid vector width\n"; + return mod_out_.Types().invalid(); + } + auto* el_ty = Type(vector_in.element_type()); + if (el_ty == nullptr) { + err_ << "vector element type is invalid\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().vec(el_ty, vector_in.width()); + } + + const type::Type* CreateTypeMatrix(const pb::TypeMatrix& matrix_in) { + const auto rows = matrix_in.num_rows(); + const auto cols = matrix_in.num_columns(); + if (DAWN_UNLIKELY(rows < 2 || rows > 4 || cols < 2 || cols > 4)) { + err_ << "invalid matrix dimensions\n"; + return mod_out_.Types().invalid(); + } + auto* el_ty = Type(matrix_in.element_type()); + if (el_ty == nullptr) { + err_ << "matrix element type is invalid\n"; + return mod_out_.Types().invalid(); + } + auto* column_ty = mod_out_.Types().vec(el_ty, matrix_in.num_rows()); + return mod_out_.Types().mat(column_ty, matrix_in.num_columns()); + } + + const type::Type* CreateTypePointer(const pb::TypePointer& pointer_in) { + auto address_space = AddressSpace(pointer_in.address_space()); + auto* store_ty = Type(pointer_in.store_type()); + if (!store_ty) { + err_ << "pointer must have a store type\n"; + return mod_out_.Types().invalid(); + } + + auto access = AccessControl(pointer_in.access()); + return mod_out_.Types().ptr(address_space, store_ty, access); + } + + const type::Type* CreateTypeStruct(const pb::TypeStruct& struct_in) { + auto struct_name = struct_in.name(); + if (DAWN_UNLIKELY(struct_name.empty())) { + err_ << "struct must have a name\n"; + return mod_out_.Types().invalid(); + } + + if (!CheckName(struct_name, "struct name")) { + return mod_out_.Types().invalid(); + } + + if (!struct_names_.Add(struct_name)) { + err_ << "duplicate struct name: " << struct_name << "\n"; + return mod_out_.Types().invalid(); + } + + Vector members_out; + uint32_t offset = 0; + for (auto& member_in : struct_in.member()) { + auto member_name = member_in.name(); + if (DAWN_UNLIKELY(member_name.empty())) { + err_ << "struct member must have a name\n"; + return mod_out_.Types().invalid(); + } + + if (!CheckName(member_name, "member name")) { + return mod_out_.Types().invalid(); + } + + auto symbol = mod_out_.symbols.Register(member_name); + auto* type = Type(member_in.type()); + if (type == nullptr) { + err_ << "struct member '" << member_name << "' type is invalid\n"; + return mod_out_.Types().invalid(); + } + + auto index = static_cast(members_out.Length()); + auto align = member_in.align(); + auto size = member_in.size(); + core::IOAttributes attributes_out{}; + if (member_in.has_attributes()) { + auto& attributes_in = member_in.attributes(); + if (attributes_in.has_location()) { + attributes_out.location = attributes_in.location(); + } + if (attributes_in.has_blend_src()) { + attributes_out.blend_src = attributes_in.blend_src(); + } + if (attributes_in.has_color()) { + attributes_out.color = attributes_in.color(); + } + if (attributes_in.has_builtin()) { + attributes_out.builtin = BuiltinValue(attributes_in.builtin()); + } + if (attributes_in.has_interpolation()) { + auto& interpolation_in = attributes_in.interpolation(); + attributes_out.interpolation = Interpolation(interpolation_in); + } + attributes_out.invariant = attributes_in.invariant(); + } + offset = RoundUp(align, offset); + auto* member_out = mod_out_.Types().Get( + symbol, type, index, offset, align, size, std::move(attributes_out)); + offset += size; + members_out.Push(member_out); + } + if (DAWN_UNLIKELY(members_out.IsEmpty())) { + err_ << "struct requires at least one member\n"; + return mod_out_.Types().invalid(); + } + auto name = mod_out_.symbols.Register(struct_name); + return mod_out_.Types().Struct(name, std::move(members_out)); + } + + const type::Type* CreateTypeAtomic(const pb::TypeAtomic& atomic_in) { + const auto* el_ty = Type(atomic_in.type()); + if (el_ty == nullptr) { + err_ << "invalid atomic element type\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().atomic(el_ty); + } + + const type::Type* CreateTypeArray(const pb::TypeArray& array_in) { + auto* element = Type(array_in.element()); + uint32_t count = array_in.count(); + if (count >= internal_limits::kMaxArrayElementCount) { + err_ << "array count (" << count << ") must be less than " + << internal_limits::kMaxArrayElementCount << "\n"; + return mod_out_.Types().invalid(); + } + if (element == nullptr) { + err_ << "array element type is invalid\n"; + return mod_out_.Types().invalid(); + } + + return count > 0 ? mod_out_.Types().array(element, count) + : mod_out_.Types().runtime_array(element); + } + + const type::Type* CreateTypeBindingArray(const pb::TypeBindingArray& array_in) { + auto* element = Type(array_in.element()); + uint32_t count = array_in.count(); + + if (count >= internal_limits::kMaxArrayElementCount) { + err_ << "binding_array count (" << count << ") must be less than " + << internal_limits::kMaxArrayElementCount << "\n"; + return mod_out_.Types().invalid(); + } + if (element == nullptr) { + err_ << "binding array element type is invalid\n"; + return mod_out_.Types().invalid(); + } + + return mod_out_.Types().binding_array(element, count); + } + + const type::Type* CreateTypeDepthTexture(const pb::TypeDepthTexture& texture_in) { + auto dimension = TextureDimension(texture_in.dimension()); + if (!type::DepthTexture::IsValidDimension(dimension)) { + err_ << "invalid DepthTexture dimension\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().depth_texture(dimension); + } + + const type::Type* CreateTypeSampledTexture(const pb::TypeSampledTexture& texture_in) { + auto dimension = TextureDimension(texture_in.dimension()); + auto sub_type = Type(texture_in.sub_type()); + if (!sub_type) { + err_ << "invalid Sampled texture subtype\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().sampled_texture(dimension, sub_type); + } + + const type::Type* CreateTypeMultisampledTexture(const pb::TypeMultisampledTexture& texture_in) { + auto dimension = TextureDimension(texture_in.dimension()); + auto sub_type = Type(texture_in.sub_type()); + if (!sub_type) { + err_ << "invalid Multisampled texture subtype\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().multisampled_texture(dimension, sub_type); + } + + const type::Type* CreateTypeDepthMultisampledTexture( + const pb::TypeDepthMultisampledTexture& texture_in) { + auto dimension = TextureDimension(texture_in.dimension()); + if (!type::DepthMultisampledTexture::IsValidDimension(dimension)) { + err_ << "invalid DepthMultisampledTexture dimension\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().depth_multisampled_texture(dimension); + } + + const type::Type* CreateTypeStorageTexture(const pb::TypeStorageTexture& texture_in) { + auto dimension = TextureDimension(texture_in.dimension()); + auto texel_format = TexelFormat(texture_in.texel_format()); + auto sub_ty = mod_out_.Types().SubtypeFor(texel_format); + if (!sub_ty) { + err_ << "unable to create a sub-type for " << texel_format << "\n"; + return mod_out_.Types().invalid(); + } + + auto access = AccessControl(texture_in.access()); + return mod_out_.Types().storage_texture(dimension, texel_format, access); + } + + const type::Type* CreateTypeTexelBuffer(const pb::TypeTexelBuffer& buffer_in) { + auto texel_format = TexelFormat(buffer_in.texel_format()); + auto sub_ty = mod_out_.Types().SubtypeFor(texel_format); + if (!sub_ty) { + err_ << "unable to create a sub-type for " << texel_format << "\n"; + return mod_out_.Types().invalid(); + } + + auto access = AccessControl(buffer_in.access()); + return mod_out_.Types().texel_buffer(texel_format, access); + } + + const type::ExternalTexture* CreateTypeExternalTexture(const pb::TypeExternalTexture&) { + return mod_out_.Types().external_texture(); + } + + const type::Sampler* CreateTypeSampler(const pb::TypeSampler& sampler_in) { + if (!SamplerKind_IsValid(sampler_in.kind())) { + err_ << "invalid sampler kind, " << std::to_string(sampler_in.kind()) << "\n"; + return nullptr; + } + auto kind = SamplerKind(sampler_in.kind()); + return mod_out_.Types().Get(kind); + } + + const type::Type* CreateTypeInputAttachment(const pb::TypeInputAttachment& input_in) { + auto sub_type = Type(input_in.sub_type()); + if (!sub_type) { + err_ << "invalid Input attachment subtype\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().input_attachment(sub_type); + } + + const type::Type* CreateTypeSubgroupMatrix(SubgroupMatrixKind kind, + const pb::TypeSubgroupMatrix& subgroup_matrix) { + const auto el_ty = Type(subgroup_matrix.sub_type()); + if (el_ty == nullptr) { + err_ << "invalid subtype for subgroup matrix\n"; + return mod_out_.Types().invalid(); + } + return mod_out_.Types().subgroup_matrix(kind, el_ty, subgroup_matrix.columns(), + subgroup_matrix.rows()); + } + + const type::Type* CreateTypeBuffer(const pb::TypeBuffer&) { + err_ << "buffer types are not supported\n"; + return mod_out_.Types().invalid(); + } + + const type::Type* CreateTypeBuiltinStruct(pb::TypeBuiltinStruct builtin_struct_in) { + if (!TypeBuiltinStruct_IsValid(builtin_struct_in)) { + err_ << "invalid builtin struct type, " << std::to_string(builtin_struct_in) << "\n"; + return mod_out_.Types().invalid(); + } + + auto& ty = mod_out_.Types(); + const core::type::Struct* res = nullptr; + switch (builtin_struct_in) { + case pb::TypeBuiltinStruct::AtomicCompareExchangeResultI32: + res = type::CreateAtomicCompareExchangeResult(ty, mod_out_.symbols, ty.i32()); + break; + case pb::TypeBuiltinStruct::AtomicCompareExchangeResultU32: + res = type::CreateAtomicCompareExchangeResult(ty, mod_out_.symbols, ty.u32()); + break; + case pb::TypeBuiltinStruct::FrexpResultF16: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.f16()); + break; + case pb::TypeBuiltinStruct::FrexpResultF32: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.f32()); + break; + case pb::TypeBuiltinStruct::FrexpResultVec2F16: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.vec2h()); + break; + case pb::TypeBuiltinStruct::FrexpResultVec2F32: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.vec2f()); + break; + case pb::TypeBuiltinStruct::FrexpResultVec3F16: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.vec3h()); + break; + case pb::TypeBuiltinStruct::FrexpResultVec3F32: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.vec3f()); + break; + case pb::TypeBuiltinStruct::FrexpResultVec4F16: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.vec4h()); + break; + case pb::TypeBuiltinStruct::FrexpResultVec4F32: + res = type::CreateFrexpResult(ty, mod_out_.symbols, ty.vec4f()); + break; + case pb::TypeBuiltinStruct::ModfResultF16: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.f16()); + break; + case pb::TypeBuiltinStruct::ModfResultF32: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.f32()); + break; + case pb::TypeBuiltinStruct::ModfResultVec2F16: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.vec2h()); + break; + case pb::TypeBuiltinStruct::ModfResultVec2F32: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.vec2f()); + break; + case pb::TypeBuiltinStruct::ModfResultVec3F16: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.vec2h()); + break; + case pb::TypeBuiltinStruct::ModfResultVec3F32: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.vec3f()); + break; + case pb::TypeBuiltinStruct::ModfResultVec4F16: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.vec2h()); + break; + case pb::TypeBuiltinStruct::ModfResultVec4F32: + res = type::CreateModfResult(ty, mod_out_.symbols, ty.vec4f()); + break; + + case pb::TypeBuiltinStruct::TypeBuiltinStruct_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::TypeBuiltinStruct::TypeBuiltinStruct_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + + if (!res) { + err_ << "invalid TypeBuiltinStruct: " << std::to_string(builtin_struct_in) << "\n"; + return mod_out_.Types().invalid(); + } + + // Make sure this struct name wasn't already used by another struct in the module. + auto struct_name = res->Name().Name(); + if (!struct_names_.Add(struct_name)) { + err_ << "duplicate struct name: " << struct_name << "\n"; + return mod_out_.Types().invalid(); + } + return res; + } + + const type::Type* Type(size_t id) { + if (DAWN_UNLIKELY(id >= types_.Length())) { + err_ << "type id " << id << " out of range\n"; + return mod_out_.Types().invalid(); + } + return types_[id]; + } + + //////////////////////////////////////////////////////////////////////////// + // Values + //////////////////////////////////////////////////////////////////////////// + ir::Value* CreateValue(const pb::Value& value_in) { + ir::Value* value_out = nullptr; + switch (value_in.kind_case()) { + case pb::Value::KindCase::kFunction: + value_out = Function(value_in.function()); + break; + case pb::Value::KindCase::kInstructionResult: + value_out = InstructionResult(value_in.instruction_result()); + break; + case pb::Value::KindCase::kFunctionParameter: + value_out = FunctionParameter(value_in.function_parameter()); + break; + case pb::Value::KindCase::kBlockParameter: + value_out = BlockParameter(value_in.block_parameter()); + break; + case pb::Value::KindCase::kConstant: + value_out = Constant(value_in.constant()); + break; + case pb::Value::KindCase::KIND_NOT_SET: + break; + } + + if (!value_out) { + err_ << "invalid value kind: " << std::to_string(value_in.kind_case()) << "\n"; + return b.InvalidConstant(); + } + + return value_out; + } + + ir::InstructionResult* InstructionResult(const pb::InstructionResult& res_in) { + auto* type = Type(res_in.type()); + if (type == nullptr || type->Is()) { + err_ << "result '" << res_in.name() << "' has invalid type\n"; + return nullptr; + } + auto* res_out = b.InstructionResult(type); + if (!res_in.name().empty()) { + if (!CheckName(res_in.name(), "result name")) { + return nullptr; + } + mod_out_.SetName(res_out, res_in.name()); + } + return res_out; + } + + ir::FunctionParam* FunctionParameter(const pb::FunctionParameter& param_in) { + auto* type = Type(param_in.type()); + if (type == nullptr || type->Is()) { + err_ << "param '" << param_in.name() << "' has invalid type\n"; + return nullptr; + } + auto* param_out = b.FunctionParam(type); + if (!param_in.name().empty()) { + if (!CheckName(param_in.name(), "param name")) { + return nullptr; + } + mod_out_.SetName(param_out, param_in.name()); + } + + if (param_in.has_attributes()) { + auto& attrs_in = param_in.attributes(); + if (attrs_in.has_binding_point()) { + auto& bp_in = attrs_in.binding_point(); + param_out->SetBindingPoint(bp_in.group(), bp_in.binding()); + } + if (attrs_in.has_location()) { + param_out->SetLocation(attrs_in.location()); + } + if (attrs_in.has_color()) { + param_out->SetColor(attrs_in.color()); + } + if (attrs_in.has_interpolation()) { + param_out->SetInterpolation(Interpolation(attrs_in.interpolation())); + } + if (attrs_in.has_builtin()) { + param_out->SetBuiltin(BuiltinValue(attrs_in.builtin())); + } + if (attrs_in.invariant()) { + param_out->SetInvariant(true); + } + } + + return param_out; + } + + ir::BlockParam* BlockParameter(const pb::BlockParameter& param_in) { + auto* type = Type(param_in.type()); + if (type == nullptr || type->Is()) { + err_ << "block parameter '" << param_in.name() << "' has invalid type\n"; + return nullptr; + } + auto* param_out = b.BlockParam(type); + if (!param_in.name().empty()) { + if (!CheckName(param_in.name(), "param name")) { + return nullptr; + } + mod_out_.SetName(param_out, param_in.name()); + } + return param_out; + } + + ir::Constant* Constant(uint32_t value_id) { return b.Constant(ConstantValue(value_id)); } + + ir::Value* Value(uint32_t id) { + if (DAWN_UNLIKELY(id > values_.Length())) { + err_ << "value id " << id << " out of range\n"; + return nullptr; + } + return id > 0 ? values_[id - 1] : nullptr; + } + + template + T* ValueAs(uint32_t id) { + auto* value = Value(id); + if (auto cast = As(value); DAWN_LIKELY(cast)) { + return cast; + } + err_ << "value " << id << " is " << (value ? value->TypeInfo().name : "") + << " expected " << TypeInfo::Of().name << "\n"; + return nullptr; + } + + //////////////////////////////////////////////////////////////////////////// + // ConstantValues + //////////////////////////////////////////////////////////////////////////// + const core::constant::Value* CreateConstantValue(const pb::ConstantValue& value_in) { + switch (value_in.kind_case()) { + case pb::ConstantValue::KindCase::kScalar: + return CreateConstantScalar(value_in.scalar()); + case pb::ConstantValue::KindCase::kComposite: + return CreateConstantComposite(value_in.composite()); + case pb::ConstantValue::KindCase::kSplat: + return CreateConstantSplat(value_in.splat()); + case pb::ConstantValue::KindCase::KIND_NOT_SET: + break; + } + err_ << "invalid ConstantValue.kind: " << std::to_string(value_in.kind_case()) << "\n"; + return b.InvalidConstant()->Value(); + } + + const core::constant::Value* CreateConstantScalar(const pb::ConstantValueScalar& value_in) { + switch (value_in.kind_case()) { + case pb::ConstantValueScalar::KindCase::kBool: + return b.ConstantValue(value_in.bool_()); + case pb::ConstantValueScalar::KindCase::kI32: + return b.ConstantValue(i32(value_in.i32())); + case pb::ConstantValueScalar::KindCase::kU32: + return b.ConstantValue(u32(value_in.u32())); + case pb::ConstantValueScalar::KindCase::kF32: + return b.ConstantValue(CheckFinite(f32(value_in.f32()))); + case pb::ConstantValueScalar::KindCase::kF16: + return b.ConstantValue(CheckFinite(f16(value_in.f16()))); + case pb::ConstantValueScalar::KindCase::KIND_NOT_SET: + break; + } + err_ << "invalid ConstantValueScalar.kind: " << std::to_string(value_in.kind_case()) + << "\n"; + return b.InvalidConstant()->Value(); + } + + const core::constant::Value* CreateConstantComposite( + const pb::ConstantValueComposite& composite_in) { + auto* type = Type(composite_in.type()); + if (!type) { + err_ << "invalid type for constant composite\n"; + return b.InvalidConstant()->Value(); + } + + auto type_elements = type->Elements(); + size_t num_values = static_cast(composite_in.elements().size()); + if (DAWN_UNLIKELY(type_elements.count == 0)) { + err_ << "cannot create a composite of type " << type->FriendlyName() << "\n"; + return b.InvalidConstant()->Value(); + } + if (DAWN_UNLIKELY(type_elements.count != num_values)) { + err_ << "constant composite type " << type->FriendlyName() << " expects " + << type_elements.count << " elements, but " << num_values << " values encoded\n"; + return b.InvalidConstant()->Value(); + } + Vector elements_out; + for (auto element_id : composite_in.elements()) { + uint32_t i = static_cast(elements_out.Length()); + auto* value = ConstantValue(element_id); + if (auto* el_type = type->Element(i); DAWN_UNLIKELY(value->Type() != el_type)) { + if (!el_type) { + err_ << "constant composite has a null element type\n"; + } else { + err_ << "constant composite element value type " + << value->Type()->FriendlyName() << " does not match element type " + << el_type->FriendlyName() << "\n"; + } + return b.InvalidConstant()->Value(); + } + elements_out.Push(value); + } + return mod_out_.constant_values.Composite(type, std::move(elements_out)); + } + + const core::constant::Value* CreateConstantSplat(const pb::ConstantValueSplat& splat_in) { + auto* type = Type(splat_in.type()); + if (!type) { + err_ << "invalid type for constant splat\n"; + return b.InvalidConstant()->Value(); + } + + uint32_t num_elements = type->Elements().count; + if (DAWN_UNLIKELY(num_elements == 0)) { + err_ << "cannot create a splat of type " << type->FriendlyName() << "\n"; + return b.InvalidConstant()->Value(); + } + if (DAWN_UNLIKELY(num_elements > internal_limits::kMaxArrayConstructorElements)) { + err_ << "array constructor has excessive number of elements (>" + << internal_limits::kMaxArrayConstructorElements << ")\n"; + return b.InvalidConstant()->Value(); + } + auto* value = ConstantValue(splat_in.elements()); + for (uint32_t i = 0; i < num_elements; i++) { + auto* el_type = type->Element(i); + if (DAWN_UNLIKELY(el_type != value->Type())) { + err_ << "constant splat element value type " << value->Type()->FriendlyName() + << " does not match element " << i << " type " << el_type->FriendlyName() + << "\n"; + return b.InvalidConstant()->Value(); + } + } + return mod_out_.constant_values.Splat(type, value); + } + + const core::constant::Value* ConstantValue(uint32_t id) { + if (DAWN_UNLIKELY(id >= constant_values_.Length())) { + err_ << "constant value id " << id << " out of range\n"; + return b.InvalidConstant()->Value(); + } + return constant_values_[id]; + } + + //////////////////////////////////////////////////////////////////////////// + // Attributes + //////////////////////////////////////////////////////////////////////////// + core::Interpolation Interpolation(const pb::Interpolation& interpolation_in) { + core::Interpolation interpolation_out{}; + interpolation_out.type = InterpolationType(interpolation_in.type()); + if (interpolation_in.has_sampling()) { + interpolation_out.sampling = InterpolationSampling(interpolation_in.sampling()); + } + return interpolation_out; + } + + //////////////////////////////////////////////////////////////////////////// + // Enums + //////////////////////////////////////////////////////////////////////////// + core::AddressSpace AddressSpace(pb::AddressSpace in) { + if (!AddressSpace_IsValid(in)) { + err_ << "invalid address space, " << std::to_string(in) << "\n"; + return core::AddressSpace::kUndefined; + } + + switch (in) { + case pb::AddressSpace::function: + return core::AddressSpace::kFunction; + case pb::AddressSpace::handle: + return core::AddressSpace::kHandle; + case pb::AddressSpace::pixel_local: + return core::AddressSpace::kPixelLocal; + case pb::AddressSpace::private_: + return core::AddressSpace::kPrivate; + case pb::AddressSpace::immediate: + return core::AddressSpace::kImmediate; + case pb::AddressSpace::storage: + return core::AddressSpace::kStorage; + case pb::AddressSpace::uniform: + return core::AddressSpace::kUniform; + case pb::AddressSpace::workgroup: + return core::AddressSpace::kWorkgroup; + + case pb::AddressSpace::AddressSpace_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::AddressSpace::AddressSpace_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid AddressSpace: " << in; + } + + core::Access AccessControl(pb::AccessControl in) { + if (!AccessControl_IsValid(in)) { + err_ << "invalid access control, " << std::to_string(in) << "\n"; + return core::Access::kUndefined; + } + + switch (in) { + case pb::AccessControl::read: + return core::Access::kRead; + case pb::AccessControl::write: + return core::Access::kWrite; + case pb::AccessControl::read_write: + return core::Access::kReadWrite; + + case pb::AccessControl::AccessControl_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::AccessControl::AccessControl_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid Access: " << in; + } + + core::UnaryOp UnaryOp(pb::UnaryOp in) { + switch (in) { + case pb::UnaryOp::complement: + return core::UnaryOp::kComplement; + case pb::UnaryOp::negation: + return core::UnaryOp::kNegation; + case pb::UnaryOp::address_of: + return core::UnaryOp::kAddressOf; + case pb::UnaryOp::indirection: + return core::UnaryOp::kIndirection; + case pb::UnaryOp::not_: + return core::UnaryOp::kNot; + + case pb::UnaryOp::UnaryOp_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::UnaryOp::UnaryOp_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid UnaryOp: " << in; + } + + core::BinaryOp BinaryOp(pb::BinaryOp in) { + switch (in) { + case pb::BinaryOp::add_: + return core::BinaryOp::kAdd; + case pb::BinaryOp::subtract: + return core::BinaryOp::kSubtract; + case pb::BinaryOp::multiply: + return core::BinaryOp::kMultiply; + case pb::BinaryOp::divide: + return core::BinaryOp::kDivide; + case pb::BinaryOp::modulo: + return core::BinaryOp::kModulo; + case pb::BinaryOp::and_: + return core::BinaryOp::kAnd; + case pb::BinaryOp::or_: + return core::BinaryOp::kOr; + case pb::BinaryOp::xor_: + return core::BinaryOp::kXor; + case pb::BinaryOp::equal: + return core::BinaryOp::kEqual; + case pb::BinaryOp::not_equal: + return core::BinaryOp::kNotEqual; + case pb::BinaryOp::less_than: + return core::BinaryOp::kLessThan; + case pb::BinaryOp::greater_than: + return core::BinaryOp::kGreaterThan; + case pb::BinaryOp::less_than_equal: + return core::BinaryOp::kLessThanEqual; + case pb::BinaryOp::greater_than_equal: + return core::BinaryOp::kGreaterThanEqual; + case pb::BinaryOp::shift_left: + return core::BinaryOp::kShiftLeft; + case pb::BinaryOp::shift_right: + return core::BinaryOp::kShiftRight; + case pb::BinaryOp::logical_and: + return core::BinaryOp::kLogicalAnd; + case pb::BinaryOp::logical_or: + return core::BinaryOp::kLogicalOr; + + case pb::BinaryOp::BinaryOp_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::BinaryOp::BinaryOp_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid BinaryOp: " << in; + } + + core::type::TextureDimension TextureDimension(pb::TextureDimension in) { + if (!TextureDimension_IsValid(in)) { + err_ << "invalid texture dimension, " << std::to_string(in) << "\n"; + return core::type::TextureDimension::kNone; + } + + switch (in) { + case pb::TextureDimension::_1d: + return core::type::TextureDimension::k1d; + case pb::TextureDimension::_2d: + return core::type::TextureDimension::k2d; + case pb::TextureDimension::_2d_array: + return core::type::TextureDimension::k2dArray; + case pb::TextureDimension::_3d: + return core::type::TextureDimension::k3d; + case pb::TextureDimension::cube: + return core::type::TextureDimension::kCube; + case pb::TextureDimension::cube_array: + return core::type::TextureDimension::kCubeArray; + + case pb::TextureDimension::TextureDimension_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::TextureDimension::TextureDimension_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + + TINT_ICE() << "invalid TextureDimension: " << in; + } + + core::TexelFormat TexelFormat(pb::TexelFormat in) { + if (!TexelFormat_IsValid(in)) { + err_ << "invalid texel format, " << std::to_string(in) << "\n"; + return core::TexelFormat::kUndefined; + } + + switch (in) { + case pb::TexelFormat::bgra8_unorm: + return core::TexelFormat::kBgra8Unorm; + case pb::TexelFormat::r8_unorm: + return core::TexelFormat::kR8Unorm; + case pb::TexelFormat::r32_float: + return core::TexelFormat::kR32Float; + case pb::TexelFormat::r32_sint: + return core::TexelFormat::kR32Sint; + case pb::TexelFormat::r32_uint: + return core::TexelFormat::kR32Uint; + case pb::TexelFormat::rg32_float: + return core::TexelFormat::kRg32Float; + case pb::TexelFormat::rg32_sint: + return core::TexelFormat::kRg32Sint; + case pb::TexelFormat::rg32_uint: + return core::TexelFormat::kRg32Uint; + case pb::TexelFormat::rgba16_float: + return core::TexelFormat::kRgba16Float; + case pb::TexelFormat::rgba16_sint: + return core::TexelFormat::kRgba16Sint; + case pb::TexelFormat::rgba16_uint: + return core::TexelFormat::kRgba16Uint; + case pb::TexelFormat::rgba32_float: + return core::TexelFormat::kRgba32Float; + case pb::TexelFormat::rgba32_sint: + return core::TexelFormat::kRgba32Sint; + case pb::TexelFormat::rgba32_uint: + return core::TexelFormat::kRgba32Uint; + case pb::TexelFormat::rgba8_sint: + return core::TexelFormat::kRgba8Sint; + case pb::TexelFormat::rgba8_snorm: + return core::TexelFormat::kRgba8Snorm; + case pb::TexelFormat::rgba8_uint: + return core::TexelFormat::kRgba8Uint; + case pb::TexelFormat::rgba8_unorm: + return core::TexelFormat::kRgba8Unorm; + case pb::TexelFormat::r8_snorm: + return core::TexelFormat::kR8Snorm; + case pb::TexelFormat::r8_uint: + return core::TexelFormat::kR8Uint; + case pb::TexelFormat::r8_sint: + return core::TexelFormat::kR8Sint; + case pb::TexelFormat::rg8_unorm: + return core::TexelFormat::kRg8Unorm; + case pb::TexelFormat::rg8_snorm: + return core::TexelFormat::kRg8Snorm; + case pb::TexelFormat::rg8_uint: + return core::TexelFormat::kRg8Uint; + case pb::TexelFormat::rg8_sint: + return core::TexelFormat::kRg8Sint; + case pb::TexelFormat::r16_uint: + return core::TexelFormat::kR16Uint; + case pb::TexelFormat::r16_sint: + return core::TexelFormat::kR16Sint; + case pb::TexelFormat::r16_float: + return core::TexelFormat::kR16Float; + case pb::TexelFormat::rg16_uint: + return core::TexelFormat::kRg16Uint; + case pb::TexelFormat::rg16_sint: + return core::TexelFormat::kRg16Sint; + case pb::TexelFormat::rg16_float: + return core::TexelFormat::kRg16Float; + case pb::TexelFormat::rgb10a2_uint: + return core::TexelFormat::kRgb10A2Uint; + case pb::TexelFormat::rgb10a2_unorm: + return core::TexelFormat::kRgb10A2Unorm; + case pb::TexelFormat::rg11b10_ufloat: + return core::TexelFormat::kRg11B10Ufloat; + case pb::TexelFormat::r16_unorm: + return core::TexelFormat::kR16Unorm; + case pb::TexelFormat::r16_snorm: + return core::TexelFormat::kR16Snorm; + case pb::TexelFormat::rg16_unorm: + return core::TexelFormat::kRg16Unorm; + case pb::TexelFormat::rg16_snorm: + return core::TexelFormat::kRg16Snorm; + case pb::TexelFormat::rgba16_unorm: + return core::TexelFormat::kRgba16Unorm; + case pb::TexelFormat::rgba16_snorm: + return core::TexelFormat::kRgba16Snorm; + + case pb::TexelFormat::TexelFormat_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::TexelFormat::TexelFormat_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + + TINT_ICE() << "invalid TexelFormat: " << in; + } + + core::type::SamplerKind SamplerKind(pb::SamplerKind in) { + switch (in) { + case pb::SamplerKind::sampler: + return core::type::SamplerKind::kSampler; + case pb::SamplerKind::comparison: + return core::type::SamplerKind::kComparisonSampler; + + case pb::SamplerKind::SamplerKind_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::SamplerKind::SamplerKind_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + + TINT_ICE() << "invalid SamplerKind: " << in; + } + + core::InterpolationType InterpolationType(pb::InterpolationType in) { + if (!InterpolationType_IsValid(in)) { + err_ << "invalid interpolation type, " << std::to_string(in) << "\n"; + return core::InterpolationType::kUndefined; + } + + switch (in) { + case pb::InterpolationType::flat: + return core::InterpolationType::kFlat; + case pb::InterpolationType::linear: + return core::InterpolationType::kLinear; + case pb::InterpolationType::perspective: + return core::InterpolationType::kPerspective; + + case pb::InterpolationType::InterpolationType_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::InterpolationType::InterpolationType_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid InterpolationType: " << in; + } + + core::InterpolationSampling InterpolationSampling(pb::InterpolationSampling in) { + if (!InterpolationSampling_IsValid(in)) { + err_ << "invalid interpolation sampling, " << std::to_string(in) << "\n"; + return core::InterpolationSampling::kUndefined; + } + + switch (in) { + case pb::InterpolationSampling::center: + return core::InterpolationSampling::kCenter; + case pb::InterpolationSampling::centroid: + return core::InterpolationSampling::kCentroid; + case pb::InterpolationSampling::sample: + return core::InterpolationSampling::kSample; + case pb::InterpolationSampling::first: + return core::InterpolationSampling::kFirst; + case pb::InterpolationSampling::either: + return core::InterpolationSampling::kEither; + + case pb::InterpolationSampling::InterpolationSampling_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::InterpolationSampling::InterpolationSampling_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid InterpolationSampling: " << in; + } + + core::BuiltinValue BuiltinValue(pb::BuiltinValue in) { + if (!BuiltinValue_IsValid(in)) { + err_ << "invalid builtin value, " << std::to_string(in) << "\n"; + return core::BuiltinValue::kUndefined; + } + + switch (in) { + case pb::BuiltinValue::point_size: + return core::BuiltinValue::kPointSize; + case pb::BuiltinValue::cull_distance: + return core::BuiltinValue::kCullDistance; + case pb::BuiltinValue::frag_depth: + return core::BuiltinValue::kFragDepth; + case pb::BuiltinValue::front_facing: + return core::BuiltinValue::kFrontFacing; + case pb::BuiltinValue::global_invocation_id: + return core::BuiltinValue::kGlobalInvocationId; + case pb::BuiltinValue::instance_index: + return core::BuiltinValue::kInstanceIndex; + case pb::BuiltinValue::local_invocation_id: + return core::BuiltinValue::kLocalInvocationId; + case pb::BuiltinValue::local_invocation_index: + return core::BuiltinValue::kLocalInvocationIndex; + case pb::BuiltinValue::num_workgroups: + return core::BuiltinValue::kNumWorkgroups; + case pb::BuiltinValue::position: + return core::BuiltinValue::kPosition; + case pb::BuiltinValue::sample_index: + return core::BuiltinValue::kSampleIndex; + case pb::BuiltinValue::sample_mask: + return core::BuiltinValue::kSampleMask; + case pb::BuiltinValue::subgroup_id: + return core::BuiltinValue::kSubgroupId; + case pb::BuiltinValue::subgroup_invocation_id: + return core::BuiltinValue::kSubgroupInvocationId; + case pb::BuiltinValue::subgroup_size: + return core::BuiltinValue::kSubgroupSize; + case pb::BuiltinValue::num_subgroups: + return core::BuiltinValue::kNumSubgroups; + case pb::BuiltinValue::vertex_index: + return core::BuiltinValue::kVertexIndex; + case pb::BuiltinValue::workgroup_id: + return core::BuiltinValue::kWorkgroupId; + case pb::BuiltinValue::clip_distances: + return core::BuiltinValue::kClipDistances; + case pb::BuiltinValue::primitive_index: + return core::BuiltinValue::kPrimitiveIndex; + case pb::BuiltinValue::barycentric_coord: + return core::BuiltinValue::kBarycentricCoord; + case pb::BuiltinValue::BuiltinValue_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::BuiltinValue::BuiltinValue_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid BuiltinValue: " << in; + } + + core::BuiltinFn BuiltinFn(pb::BuiltinFn in) { + if (!BuiltinFn_IsValid(in)) { + err_ << "invalid builtin function, " << std::to_string(in) << "\n"; + return core::BuiltinFn::kNone; + } + + switch (in) { + case pb::BuiltinFn::abs: + return core::BuiltinFn::kAbs; + case pb::BuiltinFn::acos: + return core::BuiltinFn::kAcos; + case pb::BuiltinFn::acosh: + return core::BuiltinFn::kAcosh; + case pb::BuiltinFn::all: + return core::BuiltinFn::kAll; + case pb::BuiltinFn::any: + return core::BuiltinFn::kAny; + case pb::BuiltinFn::array_length: + return core::BuiltinFn::kArrayLength; + case pb::BuiltinFn::asin: + return core::BuiltinFn::kAsin; + case pb::BuiltinFn::asinh: + return core::BuiltinFn::kAsinh; + case pb::BuiltinFn::atan: + return core::BuiltinFn::kAtan; + case pb::BuiltinFn::atan2: + return core::BuiltinFn::kAtan2; + case pb::BuiltinFn::atanh: + return core::BuiltinFn::kAtanh; + case pb::BuiltinFn::ceil: + return core::BuiltinFn::kCeil; + case pb::BuiltinFn::clamp: + return core::BuiltinFn::kClamp; + case pb::BuiltinFn::cos: + return core::BuiltinFn::kCos; + case pb::BuiltinFn::cosh: + return core::BuiltinFn::kCosh; + case pb::BuiltinFn::count_leading_zeros: + return core::BuiltinFn::kCountLeadingZeros; + case pb::BuiltinFn::count_one_bits: + return core::BuiltinFn::kCountOneBits; + case pb::BuiltinFn::count_trailing_zeros: + return core::BuiltinFn::kCountTrailingZeros; + case pb::BuiltinFn::cross: + return core::BuiltinFn::kCross; + case pb::BuiltinFn::degrees: + return core::BuiltinFn::kDegrees; + case pb::BuiltinFn::determinant: + return core::BuiltinFn::kDeterminant; + case pb::BuiltinFn::distance: + return core::BuiltinFn::kDistance; + case pb::BuiltinFn::dot: + return core::BuiltinFn::kDot; + case pb::BuiltinFn::dot4i8_packed: + return core::BuiltinFn::kDot4I8Packed; + case pb::BuiltinFn::dot4u8_packed: + return core::BuiltinFn::kDot4U8Packed; + case pb::BuiltinFn::dpdx: + return core::BuiltinFn::kDpdx; + case pb::BuiltinFn::dpdx_coarse: + return core::BuiltinFn::kDpdxCoarse; + case pb::BuiltinFn::dpdx_fine: + return core::BuiltinFn::kDpdxFine; + case pb::BuiltinFn::dpdy: + return core::BuiltinFn::kDpdy; + case pb::BuiltinFn::dpdy_coarse: + return core::BuiltinFn::kDpdyCoarse; + case pb::BuiltinFn::dpdy_fine: + return core::BuiltinFn::kDpdyFine; + case pb::BuiltinFn::exp: + return core::BuiltinFn::kExp; + case pb::BuiltinFn::exp2: + return core::BuiltinFn::kExp2; + case pb::BuiltinFn::extract_bits: + return core::BuiltinFn::kExtractBits; + case pb::BuiltinFn::face_forward: + return core::BuiltinFn::kFaceForward; + case pb::BuiltinFn::first_leading_bit: + return core::BuiltinFn::kFirstLeadingBit; + case pb::BuiltinFn::first_trailing_bit: + return core::BuiltinFn::kFirstTrailingBit; + case pb::BuiltinFn::floor: + return core::BuiltinFn::kFloor; + case pb::BuiltinFn::fma: + return core::BuiltinFn::kFma; + case pb::BuiltinFn::fract: + return core::BuiltinFn::kFract; + case pb::BuiltinFn::frexp: + return core::BuiltinFn::kFrexp; + case pb::BuiltinFn::fwidth: + return core::BuiltinFn::kFwidth; + case pb::BuiltinFn::fwidth_coarse: + return core::BuiltinFn::kFwidthCoarse; + case pb::BuiltinFn::fwidth_fine: + return core::BuiltinFn::kFwidthFine; + case pb::BuiltinFn::insert_bits: + return core::BuiltinFn::kInsertBits; + case pb::BuiltinFn::inverse_sqrt: + return core::BuiltinFn::kInverseSqrt; + case pb::BuiltinFn::ldexp: + return core::BuiltinFn::kLdexp; + case pb::BuiltinFn::length: + return core::BuiltinFn::kLength; + case pb::BuiltinFn::log: + return core::BuiltinFn::kLog; + case pb::BuiltinFn::log2: + return core::BuiltinFn::kLog2; + case pb::BuiltinFn::max: + return core::BuiltinFn::kMax; + case pb::BuiltinFn::min: + return core::BuiltinFn::kMin; + case pb::BuiltinFn::mix: + return core::BuiltinFn::kMix; + case pb::BuiltinFn::modf: + return core::BuiltinFn::kModf; + case pb::BuiltinFn::normalize: + return core::BuiltinFn::kNormalize; + case pb::BuiltinFn::pack2x16_float: + return core::BuiltinFn::kPack2X16Float; + case pb::BuiltinFn::pack2x16_snorm: + return core::BuiltinFn::kPack2X16Snorm; + case pb::BuiltinFn::pack2x16_unorm: + return core::BuiltinFn::kPack2X16Unorm; + case pb::BuiltinFn::pack4x8_snorm: + return core::BuiltinFn::kPack4X8Snorm; + case pb::BuiltinFn::pack4x8_unorm: + return core::BuiltinFn::kPack4X8Unorm; + case pb::BuiltinFn::pack4xi8: + return core::BuiltinFn::kPack4XI8; + case pb::BuiltinFn::pack4xu8: + return core::BuiltinFn::kPack4XU8; + case pb::BuiltinFn::pack4xi8_clamp: + return core::BuiltinFn::kPack4XI8Clamp; + case pb::BuiltinFn::pack4xu8_clamp: + return core::BuiltinFn::kPack4XU8Clamp; + case pb::BuiltinFn::pow: + return core::BuiltinFn::kPow; + case pb::BuiltinFn::quantize_to_f16: + return core::BuiltinFn::kQuantizeToF16; + case pb::BuiltinFn::radians: + return core::BuiltinFn::kRadians; + case pb::BuiltinFn::reflect: + return core::BuiltinFn::kReflect; + case pb::BuiltinFn::refract: + return core::BuiltinFn::kRefract; + case pb::BuiltinFn::reverse_bits: + return core::BuiltinFn::kReverseBits; + case pb::BuiltinFn::round: + return core::BuiltinFn::kRound; + case pb::BuiltinFn::saturate: + return core::BuiltinFn::kSaturate; + case pb::BuiltinFn::select: + return core::BuiltinFn::kSelect; + case pb::BuiltinFn::sign: + return core::BuiltinFn::kSign; + case pb::BuiltinFn::sin: + return core::BuiltinFn::kSin; + case pb::BuiltinFn::sinh: + return core::BuiltinFn::kSinh; + case pb::BuiltinFn::smoothstep: + return core::BuiltinFn::kSmoothstep; + case pb::BuiltinFn::sqrt: + return core::BuiltinFn::kSqrt; + case pb::BuiltinFn::step: + return core::BuiltinFn::kStep; + case pb::BuiltinFn::storage_barrier: + return core::BuiltinFn::kStorageBarrier; + case pb::BuiltinFn::tan: + return core::BuiltinFn::kTan; + case pb::BuiltinFn::tanh: + return core::BuiltinFn::kTanh; + case pb::BuiltinFn::transpose: + return core::BuiltinFn::kTranspose; + case pb::BuiltinFn::trunc: + return core::BuiltinFn::kTrunc; + case pb::BuiltinFn::unpack2x16_float: + return core::BuiltinFn::kUnpack2X16Float; + case pb::BuiltinFn::unpack2x16_snorm: + return core::BuiltinFn::kUnpack2X16Snorm; + case pb::BuiltinFn::unpack2x16_unorm: + return core::BuiltinFn::kUnpack2X16Unorm; + case pb::BuiltinFn::unpack4x8_snorm: + return core::BuiltinFn::kUnpack4X8Snorm; + case pb::BuiltinFn::unpack4x8_unorm: + return core::BuiltinFn::kUnpack4X8Unorm; + case pb::BuiltinFn::unpack4xi8: + return core::BuiltinFn::kUnpack4XI8; + case pb::BuiltinFn::unpack4xu8: + return core::BuiltinFn::kUnpack4XU8; + case pb::BuiltinFn::workgroup_barrier: + return core::BuiltinFn::kWorkgroupBarrier; + case pb::BuiltinFn::texture_barrier: + return core::BuiltinFn::kTextureBarrier; + case pb::BuiltinFn::texture_dimensions: + return core::BuiltinFn::kTextureDimensions; + case pb::BuiltinFn::texture_gather: + return core::BuiltinFn::kTextureGather; + case pb::BuiltinFn::texture_gather_compare: + return core::BuiltinFn::kTextureGatherCompare; + case pb::BuiltinFn::texture_num_layers: + return core::BuiltinFn::kTextureNumLayers; + case pb::BuiltinFn::texture_num_levels: + return core::BuiltinFn::kTextureNumLevels; + case pb::BuiltinFn::texture_num_samples: + return core::BuiltinFn::kTextureNumSamples; + case pb::BuiltinFn::texture_sample: + return core::BuiltinFn::kTextureSample; + case pb::BuiltinFn::texture_sample_bias: + return core::BuiltinFn::kTextureSampleBias; + case pb::BuiltinFn::texture_sample_compare: + return core::BuiltinFn::kTextureSampleCompare; + case pb::BuiltinFn::texture_sample_compare_level: + return core::BuiltinFn::kTextureSampleCompareLevel; + case pb::BuiltinFn::texture_sample_grad: + return core::BuiltinFn::kTextureSampleGrad; + case pb::BuiltinFn::texture_sample_level: + return core::BuiltinFn::kTextureSampleLevel; + case pb::BuiltinFn::texture_sample_base_clamp_to_edge: + return core::BuiltinFn::kTextureSampleBaseClampToEdge; + case pb::BuiltinFn::texture_store: + return core::BuiltinFn::kTextureStore; + case pb::BuiltinFn::texture_load: + return core::BuiltinFn::kTextureLoad; + case pb::BuiltinFn::atomic_load: + return core::BuiltinFn::kAtomicLoad; + case pb::BuiltinFn::atomic_store: + return core::BuiltinFn::kAtomicStore; + case pb::BuiltinFn::atomic_add: + return core::BuiltinFn::kAtomicAdd; + case pb::BuiltinFn::atomic_sub: + return core::BuiltinFn::kAtomicSub; + case pb::BuiltinFn::atomic_max: + return core::BuiltinFn::kAtomicMax; + case pb::BuiltinFn::atomic_min: + return core::BuiltinFn::kAtomicMin; + case pb::BuiltinFn::atomic_and: + return core::BuiltinFn::kAtomicAnd; + case pb::BuiltinFn::atomic_or: + return core::BuiltinFn::kAtomicOr; + case pb::BuiltinFn::atomic_xor: + return core::BuiltinFn::kAtomicXor; + case pb::BuiltinFn::atomic_exchange: + return core::BuiltinFn::kAtomicExchange; + case pb::BuiltinFn::atomic_compare_exchange_weak: + return core::BuiltinFn::kAtomicCompareExchangeWeak; + case pb::BuiltinFn::subgroup_ballot: + return core::BuiltinFn::kSubgroupBallot; + case pb::BuiltinFn::subgroup_elect: + return core::BuiltinFn::kSubgroupElect; + case pb::BuiltinFn::subgroup_broadcast: + return core::BuiltinFn::kSubgroupBroadcast; + case pb::BuiltinFn::subgroup_broadcast_first: + return core::BuiltinFn::kSubgroupBroadcastFirst; + case pb::BuiltinFn::subgroup_shuffle: + return core::BuiltinFn::kSubgroupShuffle; + case pb::BuiltinFn::subgroup_shuffle_xor: + return core::BuiltinFn::kSubgroupShuffleXor; + case pb::BuiltinFn::subgroup_shuffle_up: + return core::BuiltinFn::kSubgroupShuffleUp; + case pb::BuiltinFn::subgroup_shuffle_down: + return core::BuiltinFn::kSubgroupShuffleDown; + case pb::BuiltinFn::input_attachment_load: + return core::BuiltinFn::kInputAttachmentLoad; + case pb::BuiltinFn::subgroup_add: + return core::BuiltinFn::kSubgroupAdd; + case pb::BuiltinFn::subgroup_inclusive_add: + return core::BuiltinFn::kSubgroupInclusiveAdd; + case pb::BuiltinFn::subgroup_exclusive_add: + return core::BuiltinFn::kSubgroupExclusiveAdd; + case pb::BuiltinFn::subgroup_mul: + return core::BuiltinFn::kSubgroupMul; + case pb::BuiltinFn::subgroup_inclusive_mul: + return core::BuiltinFn::kSubgroupInclusiveMul; + case pb::BuiltinFn::subgroup_exclusive_mul: + return core::BuiltinFn::kSubgroupExclusiveMul; + case pb::BuiltinFn::subgroup_and: + return core::BuiltinFn::kSubgroupAnd; + case pb::BuiltinFn::subgroup_or: + return core::BuiltinFn::kSubgroupOr; + case pb::BuiltinFn::subgroup_xor: + return core::BuiltinFn::kSubgroupXor; + case pb::BuiltinFn::subgroup_min: + return core::BuiltinFn::kSubgroupMin; + case pb::BuiltinFn::subgroup_max: + return core::BuiltinFn::kSubgroupMax; + case pb::BuiltinFn::subgroup_all: + return core::BuiltinFn::kSubgroupAll; + case pb::BuiltinFn::subgroup_any: + return core::BuiltinFn::kSubgroupAny; + case pb::BuiltinFn::quad_broadcast: + return core::BuiltinFn::kQuadBroadcast; + case pb::BuiltinFn::quad_swap_x: + return core::BuiltinFn::kQuadSwapX; + case pb::BuiltinFn::quad_swap_y: + return core::BuiltinFn::kQuadSwapY; + case pb::BuiltinFn::quad_swap_diagonal: + return core::BuiltinFn::kQuadSwapDiagonal; + case pb::BuiltinFn::subgroup_matrix_load: + return core::BuiltinFn::kSubgroupMatrixLoad; + case pb::BuiltinFn::subgroup_matrix_store: + return core::BuiltinFn::kSubgroupMatrixStore; + case pb::BuiltinFn::subgroup_matrix_multiply: + return core::BuiltinFn::kSubgroupMatrixMultiply; + case pb::BuiltinFn::subgroup_matrix_multiply_accumulate: + return core::BuiltinFn::kSubgroupMatrixMultiplyAccumulate; + case pb::BuiltinFn::subgroup_matrix_scalar_add: + return core::BuiltinFn::kSubgroupMatrixScalarAdd; + case pb::BuiltinFn::subgroup_matrix_scalar_multiply: + return core::BuiltinFn::kSubgroupMatrixScalarMultiply; + case pb::BuiltinFn::subgroup_matrix_scalar_subtract: + return core::BuiltinFn::kSubgroupMatrixScalarSubtract; + case pb::BuiltinFn::print: + return core::BuiltinFn::kPrint; + case pb::BuiltinFn::has_resource: + return core::BuiltinFn::kHasResource; + case pb::BuiltinFn::get_resource: + return core::BuiltinFn::kGetResource; + case pb::BuiltinFn::buffer_view: + return core::BuiltinFn::kBufferView; + case pb::BuiltinFn::buffer_length: + return core::BuiltinFn::kBufferLength; + + case pb::BuiltinFn::BuiltinFn_INT_MIN_SENTINEL_DO_NOT_USE_: + case pb::BuiltinFn::BuiltinFn_INT_MAX_SENTINEL_DO_NOT_USE_: + break; + } + TINT_ICE() << "invalid BuiltinFn: " << in; + } +}; + +} // namespace + +Result Decode(std::span encoded) { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + pb::Module mod_in; + if (!mod_in.ParseFromArray(encoded.data(), static_cast(encoded.size()))) { + return Failure{"failed to deserialize protobuf"}; + } + + return Decode(mod_in); +} + +Result Decode(const pb::Module& mod_in) { + return Decoder{mod_in}.Decode(); +} + +} // namespace tint::core::ir::binary diff --git a/3rdparty/dawn/src/tint/lang/core/ir/binary/decode.h b/3rdparty/dawn/src/tint/lang/core/ir/binary/decode.h new file mode 100644 index 000000000..38cac7f5d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/binary/decode.h @@ -0,0 +1,53 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BINARY_DECODE_H_ +#define SRC_TINT_LANG_CORE_IR_BINARY_DECODE_H_ + +#include + +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir +namespace tint::core::ir::binary::pb { +class Module; +} // namespace tint::core::ir::binary::pb + +namespace tint::core::ir::binary { + +/// @returns the decoded Module from the serialized protobuf. +Result Decode(std::span encoded); + +/// @returns the decoded Module from the protobuf. +Result Decode(const pb::Module& module); + +} // namespace tint::core::ir::binary + +#endif // SRC_TINT_LANG_CORE_IR_BINARY_DECODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/binary/encode.cc b/3rdparty/dawn/src/tint/lang/core/ir/binary/encode.cc new file mode 100644 index 000000000..41cd678cf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/binary/encode.cc @@ -0,0 +1,1462 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/binary/encode.h" + +#include +#include +#include + +#include "src/tint/lang/core/constant/composite.h" +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/constant/splat.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/break_if.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/continue.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_binary.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/core_unary.h" +#include "src/tint/lang/core/ir/discard.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/function_param.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/load_vector_element.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/store_vector_element.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/unreachable.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/utils/internal_limits.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/rtti/switch.h" + +TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS(); +#include "src/tint/utils/protos/ir/ir.pb.h" +TINT_END_DISABLE_PROTOBUF_WARNINGS(); + +namespace tint::core::ir::binary { +namespace { +struct Encoder { + const Module& mod_in_; + pb::Module& mod_out_; + + Hashmap functions_{}; + Hashmap blocks_{}; + Hashmap types_{}; + Hashmap values_{}; + Hashmap constant_values_{}; + + std::stringstream err_{}; + + Result Encode() { + // Encode all user-declared structures first. This is to ensure that the IR disassembly + // (which prints structure types first) does not reorder after encoding and decoding. + for (auto* ty : mod_in_.Types()) { + if (auto* str = ty->As()) { + Type(str); + } + } + Vector fns_out; + for (auto& fn_in : mod_in_.functions) { + uint32_t id = static_cast(mod_out_.functions().size()); + fns_out.Push(mod_out_.add_functions()); + functions_.Add(fn_in, id); + } + for (size_t i = 0, n = mod_in_.functions.Length(); i < n; i++) { + PopulateFunction(fns_out[i], mod_in_.functions[i]); + } + mod_out_.set_root_block(Block(mod_in_.root_block)); + + auto err = err_.str(); + if (!err.empty()) { + return Failure{err}; + } + return Success; + } + + //////////////////////////////////////////////////////////////////////////// + // Functions + //////////////////////////////////////////////////////////////////////////// + void PopulateFunction(pb::Function* fn_out, const ir::Function* fn_in) { + if (auto name = mod_in_.NameOf(fn_in)) { + fn_out->set_name(name.Name()); + } + fn_out->set_return_type(Type(fn_in->ReturnType())); + if (fn_in->Stage() != Function::PipelineStage::kUndefined) { + fn_out->set_pipeline_stage(PipelineStage(fn_in->Stage())); + } + if (auto wg_size_in = fn_in->WorkgroupSize()) { + auto& wg_size_out = *fn_out->mutable_workgroup_size(); + wg_size_out.set_x(Value((*wg_size_in)[0])); + wg_size_out.set_y(Value((*wg_size_in)[1])); + wg_size_out.set_z(Value((*wg_size_in)[2])); + } + if (auto subgroup_size_in = fn_in->SubgroupSize()) { + fn_out->set_subgroup_size(Value(*subgroup_size_in)); + } + for (auto* param_in : fn_in->Params()) { + fn_out->add_parameters(Value(param_in)); + } + if (auto ret_loc_in = fn_in->ReturnLocation()) { + fn_out->set_return_location(*ret_loc_in); + } + if (auto ret_interp_in = fn_in->ReturnInterpolation()) { + auto& ret_interp_out = *fn_out->mutable_return_interpolation(); + Interpolation(ret_interp_out, *ret_interp_in); + } + if (auto builtin_in = fn_in->ReturnBuiltin()) { + fn_out->set_return_builtin(BuiltinValue(*builtin_in)); + } + if (fn_in->ReturnInvariant()) { + fn_out->set_return_invariant(true); + } + fn_out->set_block(Block(fn_in->Block())); + } + + uint32_t Function(const ir::Function* fn_in) { return *functions_.Get(fn_in); } + + pb::PipelineStage PipelineStage(Function::PipelineStage stage) { + switch (stage) { + case Function::PipelineStage::kCompute: + return pb::PipelineStage::Compute; + case Function::PipelineStage::kFragment: + return pb::PipelineStage::Fragment; + case Function::PipelineStage::kVertex: + return pb::PipelineStage::Vertex; + case Function::PipelineStage::kUndefined: + break; + } + TINT_ICE() << "unhandled PipelineStage: " << stage; + } + + //////////////////////////////////////////////////////////////////////////// + // Blocks + //////////////////////////////////////////////////////////////////////////// + uint32_t Block(const ir::Block* block_in) { + TINT_ASSERT(block_in != nullptr); + + return blocks_.GetOrAdd(block_in, [&]() -> uint32_t { + auto id = static_cast(mod_out_.blocks().size()); + auto& block_out = *mod_out_.add_blocks(); + for (auto* inst : *block_in) { + Instruction(*block_out.add_instructions(), inst); + } + if (auto* mib = block_in->As()) { + block_out.set_is_multi_in(true); + for (auto* param : mib->Params()) { + block_out.add_parameters(Value(param)); + } + } + return id; + }); + } + + //////////////////////////////////////////////////////////////////////////// + // Instructions + //////////////////////////////////////////////////////////////////////////// + void Instruction(pb::Instruction& inst_out, const ir::Instruction* inst_in) { + tint::Switch( + inst_in, // + [&](const ir::Access* i) { InstructionAccess(*inst_out.mutable_access(), i); }, + [&](const ir::Bitcast* i) { InstructionBitcast(*inst_out.mutable_bitcast(), i); }, + [&](const ir::BreakIf* i) { InstructionBreakIf(*inst_out.mutable_break_if(), i); }, + [&](const ir::CoreBinary* i) { InstructionBinary(*inst_out.mutable_binary(), i); }, + [&](const ir::CoreBuiltinCall* i) { + InstructionBuiltinCall(*inst_out.mutable_builtin_call(), i); + }, + [&](const ir::CoreUnary* i) { InstructionUnary(*inst_out.mutable_unary(), i); }, + [&](const ir::Construct* i) { InstructionConstruct(*inst_out.mutable_construct(), i); }, + [&](const ir::Continue* i) { InstructionContinue(*inst_out.mutable_continue_(), i); }, + [&](const ir::Convert* i) { InstructionConvert(*inst_out.mutable_convert(), i); }, + [&](const ir::Discard* i) { InstructionDiscard(*inst_out.mutable_discard(), i); }, + [&](const ir::ExitIf* i) { InstructionExitIf(*inst_out.mutable_exit_if(), i); }, + [&](const ir::ExitLoop* i) { InstructionExitLoop(*inst_out.mutable_exit_loop(), i); }, + [&](const ir::ExitSwitch* i) { + InstructionExitSwitch(*inst_out.mutable_exit_switch(), i); + }, + [&](const ir::If* i) { InstructionIf(*inst_out.mutable_if_(), i); }, + [&](const ir::Let* i) { InstructionLet(*inst_out.mutable_let(), i); }, + [&](const ir::Load* i) { InstructionLoad(*inst_out.mutable_load(), i); }, + [&](const ir::LoadVectorElement* i) { + InstructionLoadVectorElement(*inst_out.mutable_load_vector_element(), i); + }, + [&](const ir::Loop* i) { InstructionLoop(*inst_out.mutable_loop(), i); }, + [&](const ir::NextIteration* i) { + InstructionNextIteration(*inst_out.mutable_next_iteration(), i); + }, + [&](const ir::Return* i) { InstructionReturn(*inst_out.mutable_return_(), i); }, + [&](const ir::Store* i) { InstructionStore(*inst_out.mutable_store(), i); }, + [&](const ir::StoreVectorElement* i) { + InstructionStoreVectorElement(*inst_out.mutable_store_vector_element(), i); + }, + [&](const ir::Switch* i) { InstructionSwitch(*inst_out.mutable_switch_(), i); }, + [&](const ir::Swizzle* i) { InstructionSwizzle(*inst_out.mutable_swizzle(), i); }, + [&](const ir::UserCall* i) { InstructionUserCall(*inst_out.mutable_user_call(), i); }, + [&](const ir::Var* i) { InstructionVar(*inst_out.mutable_var(), i); }, + [&](const ir::Unreachable* i) { + InstructionUnreachable(*inst_out.mutable_unreachable(), i); + }, + TINT_ICE_ON_NO_MATCH); + for (auto* operand : inst_in->Operands()) { + inst_out.add_operands(Value(operand)); + } + for (auto* result : inst_in->Results()) { + inst_out.add_results(Value(result)); + } + } + + void InstructionAccess(pb::InstructionAccess&, const ir::Access*) {} + + void InstructionBinary(pb::InstructionBinary& binary_out, const ir::CoreBinary* binary_in) { + binary_out.set_op(BinaryOp(binary_in->Op())); + } + + void InstructionBitcast(pb::InstructionBitcast&, const ir::Bitcast*) {} + + void InstructionBreakIf(pb::InstructionBreakIf& breakif_out, const ir::BreakIf* breakif_in) { + auto num_next_iter_values = static_cast(breakif_in->NextIterValues().size()); + breakif_out.set_num_next_iter_values(num_next_iter_values); + } + + void InstructionBuiltinCall(pb::InstructionBuiltinCall& call_out, + const ir::CoreBuiltinCall* call_in) { + call_out.set_builtin(BuiltinFn(call_in->Func())); + for (auto* param : call_in->ExplicitTemplateParams()) { + call_out.add_explicit_template_params(Type(param)); + } + } + + void InstructionConstruct(pb::InstructionConstruct&, const ir::Construct*) {} + + void InstructionContinue(pb::InstructionContinue&, const ir::Continue*) {} + + void InstructionConvert(pb::InstructionConvert&, const ir::Convert*) {} + + void InstructionIf(pb::InstructionIf& if_out, const ir::If* if_in) { + if (auto* block = if_in->True()) { + if_out.set_true_(Block(block)); + } + if (auto* block = if_in->False()) { + if_out.set_false_(Block(block)); + } + } + + void InstructionDiscard(pb::InstructionDiscard&, const ir::Discard*) {} + + void InstructionExitIf(pb::InstructionExitIf&, const ir::ExitIf*) {} + + void InstructionExitLoop(pb::InstructionExitLoop&, const ir::ExitLoop*) {} + + void InstructionExitSwitch(pb::InstructionExitSwitch&, const ir::ExitSwitch*) {} + + void InstructionLet(pb::InstructionLet&, const ir::Let*) {} + + void InstructionLoad(pb::InstructionLoad&, const ir::Load*) {} + + void InstructionLoadVectorElement(pb::InstructionLoadVectorElement&, + const ir::LoadVectorElement*) {} + + void InstructionLoop(pb::InstructionLoop& loop_out, const ir::Loop* loop_in) { + if (loop_in->HasInitializer()) { + loop_out.set_initializer(Block(loop_in->Initializer())); + } + loop_out.set_body(Block(loop_in->Body())); + if (loop_in->HasContinuing()) { + loop_out.set_continuing(Block(loop_in->Continuing())); + } + } + + void InstructionNextIteration(pb::InstructionNextIteration&, const ir::NextIteration*) {} + + void InstructionReturn(pb::InstructionReturn&, const ir::Return*) {} + + void InstructionStore(pb::InstructionStore&, const ir::Store*) {} + + void InstructionStoreVectorElement(pb::InstructionStoreVectorElement&, + const ir::StoreVectorElement*) {} + + void InstructionSwizzle(pb::InstructionSwizzle& swizzle_out, const ir::Swizzle* swizzle_in) { + for (auto idx : swizzle_in->Indices()) { + swizzle_out.add_indices(idx); + } + } + + void InstructionSwitch(pb::InstructionSwitch& switch_out, const ir::Switch* switch_in) { + for (auto& case_in : switch_in->Cases()) { + auto& case_out = *switch_out.add_cases(); + case_out.set_block(Block(case_in.block)); + for (auto& selector_in : case_in.selectors) { + if (selector_in.IsDefault()) { + case_out.set_is_default(true); + } else { + case_out.add_selectors(ConstantValue(selector_in.val->Value())); + } + } + } + } + + void InstructionUnary(pb::InstructionUnary& unary_out, const ir::CoreUnary* unary_in) { + unary_out.set_op(UnaryOp(unary_in->Op())); + } + + void InstructionUserCall(pb::InstructionUserCall&, const ir::UserCall*) {} + + void InstructionVar(pb::InstructionVar& var_out, const ir::Var* var_in) { + if (auto bp_in = var_in->BindingPoint()) { + auto& bp_out = *var_out.mutable_binding_point(); + BindingPoint(bp_out, *bp_in); + } + if (auto iidx_in = var_in->InputAttachmentIndex()) { + var_out.set_input_attachment_index(iidx_in.value()); + } + } + + void InstructionUnreachable(pb::InstructionUnreachable&, const ir::Unreachable*) {} + + //////////////////////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////////////////////// + uint32_t Type(const core::type::Type* type_in) { + TINT_ASSERT(type_in != nullptr); + return types_.GetOrAdd(type_in, [&]() -> uint32_t { + pb::Type type_out; + tint::Switch( + type_in, // + [&](const core::type::Void*) { type_out.set_basic(pb::TypeBasic::void_); }, + [&](const core::type::Bool*) { type_out.set_basic(pb::TypeBasic::bool_); }, + [&](const core::type::I32*) { type_out.set_basic(pb::TypeBasic::i32); }, + [&](const core::type::U32*) { type_out.set_basic(pb::TypeBasic::u32); }, + [&](const core::type::F32*) { type_out.set_basic(pb::TypeBasic::f32); }, + [&](const core::type::F16*) { type_out.set_basic(pb::TypeBasic::f16); }, + [&](const core::type::I8*) { type_out.set_basic((pb::TypeBasic::i8)); }, + [&](const core::type::U8*) { type_out.set_basic((pb::TypeBasic::u8)); }, + [&](const core::type::Vector* v) { TypeVector(*type_out.mutable_vector(), v); }, + [&](const core::type::Matrix* m) { TypeMatrix(*type_out.mutable_matrix(), m); }, + [&](const core::type::Pointer* m) { TypePointer(*type_out.mutable_pointer(), m); }, + [&](const core::type::Struct* s) { TypeStruct(*type_out.mutable_struct_(), s); }, + [&](const core::type::Atomic* a) { TypeAtomic(*type_out.mutable_atomic(), a); }, + [&](const core::type::Array* m) { TypeArray(*type_out.mutable_array(), m); }, + [&](const core::type::BindingArray* a) { + TypeBindingArray(*type_out.mutable_binding_array(), a); + }, + [&](const core::type::DepthTexture* t) { + TypeDepthTexture(*type_out.mutable_depth_texture(), t); + }, + [&](const core::type::SampledTexture* t) { + TypeSampledTexture(*type_out.mutable_sampled_texture(), t); + }, + [&](const core::type::MultisampledTexture* t) { + TypeMultisampledTexture(*type_out.mutable_multisampled_texture(), t); + }, + [&](const core::type::DepthMultisampledTexture* t) { + TypeDepthMultisampledTexture(*type_out.mutable_depth_multisampled_texture(), t); + }, + [&](const core::type::StorageTexture* t) { + TypeStorageTexture(*type_out.mutable_storage_texture(), t); + }, + [&](const core::type::TexelBuffer* t) { + TypeTexelBuffer(*type_out.mutable_texel_buffer(), t); + }, + [&](const core::type::ExternalTexture* t) { + TypeExternalTexture(*type_out.mutable_external_texture(), t); + }, + [&](const core::type::Sampler* s) { TypeSampler(*type_out.mutable_sampler(), s); }, + [&](const core::type::InputAttachment* i) { + TypeInputAttachment(*type_out.mutable_input_attachment(), i); + }, + [&]([[maybe_unused]] const core::type::SubgroupMatrix* s) { + switch (s->Kind()) { + case core::SubgroupMatrixKind::kLeft: + TypeSubgroupMatrix(*type_out.mutable_subgroup_matrix_left(), s); + break; + case core::SubgroupMatrixKind::kRight: + TypeSubgroupMatrix(*type_out.mutable_subgroup_matrix_right(), s); + break; + case core::SubgroupMatrixKind::kResult: + TypeSubgroupMatrix(*type_out.mutable_subgroup_matrix_result(), s); + break; + default: + TINT_ICE() << "invalid subgroup matrix kind: " << ToString(s->Kind()); + } + }, + [&](const core::type::Buffer* b) { TypeBuffer(*type_out.mutable_buffer(), b); }, + TINT_ICE_ON_NO_MATCH); + + mod_out_.mutable_types()->Add(std::move(type_out)); + return static_cast(mod_out_.types().size() - 1); + }); + } + + void TypeVector(pb::TypeVector& vector_out, const core::type::Vector* vector_in) { + vector_out.set_width(vector_in->Width()); + vector_out.set_element_type(Type(vector_in->Type())); + } + + void TypeMatrix(pb::TypeMatrix& matrix_out, const core::type::Matrix* matrix_in) { + matrix_out.set_num_columns(matrix_in->Columns()); + matrix_out.set_num_rows(matrix_in->Rows()); + matrix_out.set_element_type(Type(matrix_in->Type())); + } + + void TypePointer(pb::TypePointer& pointer_out, const core::type::Pointer* pointer_in) { + pointer_out.set_address_space(AddressSpace(pointer_in->AddressSpace())); + pointer_out.set_store_type(Type(pointer_in->StoreType())); + pointer_out.set_access(AccessControl(pointer_in->Access())); + } + + void TypeStruct(pb::TypeStruct& struct_out, const core::type::Struct* struct_in) { + struct_out.set_name(struct_in->Name().Name()); + for (auto* member_in : struct_in->Members()) { + auto& member_out = *struct_out.add_member(); + member_out.set_name(member_in->Name().Name()); + member_out.set_type(Type(member_in->Type())); + member_out.set_size(member_in->Size()); + member_out.set_align(member_in->Align()); + + auto& attrs_in = member_in->Attributes(); + if (attrs_in.location) { + member_out.mutable_attributes()->set_location(*attrs_in.location); + } + if (attrs_in.blend_src) { + member_out.mutable_attributes()->set_blend_src(*attrs_in.blend_src); + } + if (attrs_in.color) { + member_out.mutable_attributes()->set_color(*attrs_in.color); + } + if (attrs_in.builtin) { + member_out.mutable_attributes()->set_builtin(BuiltinValue(*attrs_in.builtin)); + } + if (auto& interpolation_in = attrs_in.interpolation) { + auto& interpolation_out = *member_out.mutable_attributes()->mutable_interpolation(); + Interpolation(interpolation_out, *interpolation_in); + } + if (attrs_in.invariant) { + member_out.mutable_attributes()->set_invariant(true); + } + } + } + + void TypeAtomic(pb::TypeAtomic& atomic_out, const core::type::Atomic* atomic_in) { + atomic_out.set_type(Type(atomic_in->Type())); + } + + void TypeArray(pb::TypeArray& array_out, const core::type::Array* array_in) { + array_out.set_element(Type(array_in->ElemType())); + tint::Switch( + array_in->Count(), // + [&](const core::type::ConstantArrayCount* c) { + array_out.set_count(c->value); + if (c->value >= internal_limits::kMaxArrayElementCount) { + err_ << "array count (" << c->value << ") must be less than " + << internal_limits::kMaxArrayElementCount << "\n"; + } + }, + [&](const core::type::RuntimeArrayCount*) { array_out.set_count(0); }, + TINT_ICE_ON_NO_MATCH); + } + + void TypeBindingArray(pb::TypeBindingArray& array_out, + const core::type::BindingArray* array_in) { + array_out.set_element(Type(array_in->ElemType())); + tint::Switch( + array_in->Count(), // + [&](const core::type::ConstantArrayCount* c) { + array_out.set_count(c->value); + if (c->value >= internal_limits::kMaxArrayElementCount) { + err_ << "binding_array count (" << c->value << ") must be less than " + << internal_limits::kMaxArrayElementCount << "\n"; + } + }, + TINT_ICE_ON_NO_MATCH); + } + + void TypeDepthTexture(pb::TypeDepthTexture& texture_out, + const core::type::DepthTexture* texture_in) { + texture_out.set_dimension(TextureDimension(texture_in->Dim())); + } + + void TypeSampledTexture(pb::TypeSampledTexture& texture_out, + const core::type::SampledTexture* texture_in) { + texture_out.set_dimension(TextureDimension(texture_in->Dim())); + texture_out.set_sub_type(Type(texture_in->Type())); + } + + void TypeMultisampledTexture(pb::TypeMultisampledTexture& texture_out, + const core::type::MultisampledTexture* texture_in) { + texture_out.set_dimension(TextureDimension(texture_in->Dim())); + texture_out.set_sub_type(Type(texture_in->Type())); + } + + void TypeDepthMultisampledTexture(pb::TypeDepthMultisampledTexture& texture_out, + const core::type::DepthMultisampledTexture* texture_in) { + texture_out.set_dimension(TextureDimension(texture_in->Dim())); + } + + void TypeStorageTexture(pb::TypeStorageTexture& texture_out, + const core::type::StorageTexture* texture_in) { + texture_out.set_dimension(TextureDimension(texture_in->Dim())); + texture_out.set_texel_format(TexelFormat(texture_in->TexelFormat())); + texture_out.set_access(AccessControl(texture_in->Access())); + } + + void TypeTexelBuffer(pb::TypeTexelBuffer& buffer_out, + const core::type::TexelBuffer* buffer_in) { + buffer_out.set_texel_format(TexelFormat(buffer_in->TexelFormat())); + buffer_out.set_access(AccessControl(buffer_in->Access())); + } + + void TypeExternalTexture(pb::TypeExternalTexture&, const core::type::ExternalTexture*) {} + + void TypeInputAttachment(pb::TypeInputAttachment& input_attachment_out, + const core::type::InputAttachment* input_attachment_in) { + input_attachment_out.set_sub_type(Type(input_attachment_in->Type())); + } + + void TypeSampler(pb::TypeSampler& sampler_out, const core::type::Sampler* sampler_in) { + sampler_out.set_kind(SamplerKind(sampler_in->Kind())); + } + + void TypeSubgroupMatrix(pb::TypeSubgroupMatrix& subgroup_matrix_out, + const core::type::SubgroupMatrix* subgroup_matrix_in) { + subgroup_matrix_out.set_sub_type(Type(subgroup_matrix_in->Type())); + subgroup_matrix_out.set_columns(subgroup_matrix_in->Columns()); + subgroup_matrix_out.set_rows(subgroup_matrix_in->Rows()); + } + + void TypeBuffer(pb::TypeBuffer& buffer_out, const core::type::Buffer* buffer_in) { + tint::Switch( + buffer_in->Count(), // + [&](const core::type::ConstantArrayCount* c) { + buffer_out.set_count(c->value); + if (c->value >= internal_limits::kMaxArrayElementCount) { + err_ << "array count (" << c->value << ") must be less than " + << internal_limits::kMaxArrayElementCount << "\n"; + } + }, + [&](const core::type::RuntimeArrayCount*) { buffer_out.set_count(0); }, + TINT_ICE_ON_NO_MATCH); + } + + [[maybe_unused]] void TypeBuitinStruct(pb::Type& builtin_struct_out, + const core::type::Struct* builtin_struct_in) { + auto name = builtin_struct_in->Name().NameView(); + auto builtin = ParseBuiltinType(name); + switch (builtin) { + case BuiltinType::kAtomicCompareExchangeResultI32: + builtin_struct_out.set_builtin_struct( + pb::TypeBuiltinStruct::AtomicCompareExchangeResultI32); + break; + case BuiltinType::kAtomicCompareExchangeResultU32: + builtin_struct_out.set_builtin_struct( + pb::TypeBuiltinStruct::AtomicCompareExchangeResultU32); + break; + case BuiltinType::kFrexpResultF16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultF16); + break; + case BuiltinType::kFrexpResultF32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultF32); + break; + case BuiltinType::kFrexpResultVec2F16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultVec2F16); + break; + case BuiltinType::kFrexpResultVec2F32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultVec2F32); + break; + case BuiltinType::kFrexpResultVec3F16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultVec3F16); + break; + case BuiltinType::kFrexpResultVec3F32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultVec3F32); + break; + case BuiltinType::kFrexpResultVec4F16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultVec4F16); + break; + case BuiltinType::kFrexpResultVec4F32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::FrexpResultVec4F32); + break; + case BuiltinType::kModfResultF16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultF16); + break; + case BuiltinType::kModfResultF32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultF32); + break; + case BuiltinType::kModfResultVec2F16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultVec2F16); + break; + case BuiltinType::kModfResultVec2F32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultVec2F32); + break; + case BuiltinType::kModfResultVec3F16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultVec3F16); + break; + case BuiltinType::kModfResultVec3F32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultVec3F32); + break; + case BuiltinType::kModfResultVec4F16: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultVec4F16); + break; + case BuiltinType::kModfResultVec4F32: + builtin_struct_out.set_builtin_struct(pb::TypeBuiltinStruct::ModfResultVec4F32); + break; + default: + TINT_ICE() << "unhandled builtin struct " << name; + } + } + + //////////////////////////////////////////////////////////////////////////// + // Values + //////////////////////////////////////////////////////////////////////////// + uint32_t Value(const ir::Value* value_in) { + if (!value_in) { + return 0; + } + return values_.GetOrAdd(value_in, [&] { + auto& value_out = *mod_out_.add_values(); + auto id = static_cast(mod_out_.values().size()); + + tint::Switch( + value_in, + [&](const ir::InstructionResult* v) { + InstructionResult(*value_out.mutable_instruction_result(), v); + }, + [&](const ir::FunctionParam* v) { + FunctionParameter(*value_out.mutable_function_parameter(), v); + }, + [&](const ir::BlockParam* v) { + BlockParameter(*value_out.mutable_block_parameter(), v); + }, + [&](const ir::Function* v) { value_out.set_function(Function(v)); }, + [&](const ir::Constant* v) { value_out.set_constant(ConstantValue(v->Value())); }, + TINT_ICE_ON_NO_MATCH); + + return id; + }); + } + + void InstructionResult(pb::InstructionResult& res_out, const ir::InstructionResult* res_in) { + res_out.set_type(Type(res_in->Type())); + if (auto name = mod_in_.NameOf(res_in); name.IsValid()) { + res_out.set_name(name.Name()); + } + } + + void FunctionParameter(pb::FunctionParameter& param_out, const ir::FunctionParam* param_in) { + param_out.set_type(Type(param_in->Type())); + if (auto name = mod_in_.NameOf(param_in); name.IsValid()) { + param_out.set_name(name.Name()); + } + if (auto bp_in = param_in->BindingPoint()) { + auto& bp_out = *param_out.mutable_attributes()->mutable_binding_point(); + BindingPoint(bp_out, *bp_in); + } + if (auto location_in = param_in->Location()) { + param_out.mutable_attributes()->set_location(*location_in); + } + if (auto color_in = param_in->Color()) { + param_out.mutable_attributes()->set_color(*color_in); + } + if (auto interpolation_in = param_in->Interpolation()) { + auto& interpolation_out = *param_out.mutable_attributes()->mutable_interpolation(); + Interpolation(interpolation_out, *interpolation_in); + } + if (auto builtin_in = param_in->Builtin()) { + param_out.mutable_attributes()->set_builtin(BuiltinValue(*builtin_in)); + } + if (param_in->Invariant()) { + param_out.mutable_attributes()->set_invariant(true); + } + } + + void BlockParameter(pb::BlockParameter& param_out, const ir::BlockParam* param_in) { + param_out.set_type(Type(param_in->Type())); + if (auto name = mod_in_.NameOf(param_in); name.IsValid()) { + param_out.set_name(name.Name()); + } + } + + //////////////////////////////////////////////////////////////////////////// + // ConstantValues + //////////////////////////////////////////////////////////////////////////// + uint32_t ConstantValue(const core::constant::Value* constant_in) { + TINT_ASSERT(constant_in != nullptr); + return constant_values_.GetOrAdd(constant_in, [&] { + pb::ConstantValue constant_out; + tint::Switch( + constant_in, // + [&](const core::constant::Scalar* b) { + constant_out.mutable_scalar()->set_bool_(b->value); + }, + [&](const core::constant::Scalar* i32) { + constant_out.mutable_scalar()->set_i32(i32->value); + }, + [&](const core::constant::Scalar* u32) { + constant_out.mutable_scalar()->set_u32(u32->value); + }, + [&](const core::constant::Scalar* f32) { + constant_out.mutable_scalar()->set_f32(f32->value); + }, + [&](const core::constant::Scalar* f16) { + constant_out.mutable_scalar()->set_f16(f16->value); + }, + [&](const core::constant::Composite* composite) { + ConstantValueComposite(*constant_out.mutable_composite(), composite); + }, + [&](const core::constant::Splat* splat) { + ConstantValueSplat(*constant_out.mutable_splat(), splat); + }, + TINT_ICE_ON_NO_MATCH); + + mod_out_.mutable_constant_values()->Add(std::move(constant_out)); + return static_cast(mod_out_.constant_values().size() - 1); + }); + } + + void ConstantValueComposite(pb::ConstantValueComposite& composite_out, + const core::constant::Composite* composite_in) { + composite_out.set_type(Type(composite_in->type)); + for (auto* el : composite_in->elements) { + composite_out.add_elements(ConstantValue(el)); + } + } + + void ConstantValueSplat(pb::ConstantValueSplat& splat_out, + const core::constant::Splat* splat_in) { + splat_out.set_type(Type(splat_in->type)); + if (DAWN_UNLIKELY(splat_in->count > internal_limits::kMaxArrayConstructorElements)) { + err_ << "array constructor has excessive number of elements (>" + << internal_limits::kMaxArrayConstructorElements << ")\n"; + } + splat_out.set_elements(ConstantValue(splat_in->el)); + splat_out.set_count(static_cast(splat_in->count)); + } + + //////////////////////////////////////////////////////////////////////////// + // Attributes + //////////////////////////////////////////////////////////////////////////// + void Interpolation(pb::Interpolation& interpolation_out, + const core::Interpolation& interpolation_in) { + interpolation_out.set_type(InterpolationType(interpolation_in.type)); + if (interpolation_in.sampling != InterpolationSampling::kUndefined) { + interpolation_out.set_sampling(InterpolationSampling(interpolation_in.sampling)); + } + } + + void BindingPoint(pb::BindingPoint& binding_point_out, const BindingPoint& binding_point_in) { + binding_point_out.set_group(binding_point_in.group); + binding_point_out.set_binding(binding_point_in.binding); + } + + //////////////////////////////////////////////////////////////////////////// + // Enums + //////////////////////////////////////////////////////////////////////////// + pb::AddressSpace AddressSpace(core::AddressSpace in) { + switch (in) { + case core::AddressSpace::kFunction: + return pb::AddressSpace::function; + case core::AddressSpace::kHandle: + return pb::AddressSpace::handle; + case core::AddressSpace::kPixelLocal: + return pb::AddressSpace::pixel_local; + case core::AddressSpace::kPrivate: + return pb::AddressSpace::private_; + case core::AddressSpace::kImmediate: + return pb::AddressSpace::immediate; + case core::AddressSpace::kStorage: + return pb::AddressSpace::storage; + case core::AddressSpace::kUniform: + return pb::AddressSpace::uniform; + case core::AddressSpace::kWorkgroup: + return pb::AddressSpace::workgroup; + + case core::AddressSpace::kUndefined: + case core::AddressSpace::kIn: + case core::AddressSpace::kOut: + break; + } + TINT_ICE() << "invalid AddressSpace: " << in; + } + + pb::AccessControl AccessControl(core::Access in) { + switch (in) { + case core::Access::kRead: + return pb::AccessControl::read; + case core::Access::kWrite: + return pb::AccessControl::write; + case core::Access::kReadWrite: + return pb::AccessControl::read_write; + case core::Access::kUndefined: + break; + } + TINT_ICE() << "invalid Access: " << in; + } + + pb::UnaryOp UnaryOp(core::UnaryOp in) { + switch (in) { + case core::UnaryOp::kComplement: + return pb::UnaryOp::complement; + case core::UnaryOp::kNegation: + return pb::UnaryOp::negation; + case core::UnaryOp::kAddressOf: + return pb::UnaryOp::address_of; + case core::UnaryOp::kIndirection: + return pb::UnaryOp::indirection; + case core::UnaryOp::kNot: + return pb::UnaryOp::not_; + } + TINT_ICE() << "invalid UnaryOp: " << in; + } + + pb::BinaryOp BinaryOp(core::BinaryOp in) { + switch (in) { + case core::BinaryOp::kAdd: + return pb::BinaryOp::add_; + case core::BinaryOp::kSubtract: + return pb::BinaryOp::subtract; + case core::BinaryOp::kMultiply: + return pb::BinaryOp::multiply; + case core::BinaryOp::kDivide: + return pb::BinaryOp::divide; + case core::BinaryOp::kModulo: + return pb::BinaryOp::modulo; + case core::BinaryOp::kAnd: + return pb::BinaryOp::and_; + case core::BinaryOp::kOr: + return pb::BinaryOp::or_; + case core::BinaryOp::kXor: + return pb::BinaryOp::xor_; + case core::BinaryOp::kEqual: + return pb::BinaryOp::equal; + case core::BinaryOp::kNotEqual: + return pb::BinaryOp::not_equal; + case core::BinaryOp::kLessThan: + return pb::BinaryOp::less_than; + case core::BinaryOp::kGreaterThan: + return pb::BinaryOp::greater_than; + case core::BinaryOp::kLessThanEqual: + return pb::BinaryOp::less_than_equal; + case core::BinaryOp::kGreaterThanEqual: + return pb::BinaryOp::greater_than_equal; + case core::BinaryOp::kShiftLeft: + return pb::BinaryOp::shift_left; + case core::BinaryOp::kShiftRight: + return pb::BinaryOp::shift_right; + case core::BinaryOp::kLogicalAnd: + return pb::BinaryOp::logical_and; + case core::BinaryOp::kLogicalOr: + return pb::BinaryOp::logical_or; + } + + TINT_ICE() << "invalid BinaryOp: " << in; + } + + pb::TextureDimension TextureDimension(core::type::TextureDimension in) { + switch (in) { + case core::type::TextureDimension::k1d: + return pb::TextureDimension::_1d; + case core::type::TextureDimension::k2d: + return pb::TextureDimension::_2d; + case core::type::TextureDimension::k2dArray: + return pb::TextureDimension::_2d_array; + case core::type::TextureDimension::k3d: + return pb::TextureDimension::_3d; + case core::type::TextureDimension::kCube: + return pb::TextureDimension::cube; + case core::type::TextureDimension::kCubeArray: + return pb::TextureDimension::cube_array; + case core::type::TextureDimension::kNone: + break; + } + + TINT_ICE() << "invalid TextureDimension: " << in; + } + + pb::TexelFormat TexelFormat(core::TexelFormat in) { + switch (in) { + case core::TexelFormat::kBgra8Unorm: + return pb::TexelFormat::bgra8_unorm; + case core::TexelFormat::kR32Float: + return pb::TexelFormat::r32_float; + case core::TexelFormat::kR32Sint: + return pb::TexelFormat::r32_sint; + case core::TexelFormat::kR32Uint: + return pb::TexelFormat::r32_uint; + case core::TexelFormat::kR8Unorm: + return pb::TexelFormat::r8_unorm; + case core::TexelFormat::kRg32Float: + return pb::TexelFormat::rg32_float; + case core::TexelFormat::kRg32Sint: + return pb::TexelFormat::rg32_sint; + case core::TexelFormat::kRg32Uint: + return pb::TexelFormat::rg32_uint; + case core::TexelFormat::kRgba16Float: + return pb::TexelFormat::rgba16_float; + case core::TexelFormat::kRgba16Sint: + return pb::TexelFormat::rgba16_sint; + case core::TexelFormat::kRgba16Uint: + return pb::TexelFormat::rgba16_uint; + case core::TexelFormat::kRgba32Float: + return pb::TexelFormat::rgba32_float; + case core::TexelFormat::kRgba32Sint: + return pb::TexelFormat::rgba32_sint; + case core::TexelFormat::kRgba32Uint: + return pb::TexelFormat::rgba32_uint; + case core::TexelFormat::kRgba8Sint: + return pb::TexelFormat::rgba8_sint; + case core::TexelFormat::kRgba8Snorm: + return pb::TexelFormat::rgba8_snorm; + case core::TexelFormat::kRgba8Uint: + return pb::TexelFormat::rgba8_uint; + case core::TexelFormat::kRgba8Unorm: + return pb::TexelFormat::rgba8_unorm; + case core::TexelFormat::kR8Snorm: + return pb::TexelFormat::r8_snorm; + case core::TexelFormat::kR8Uint: + return pb::TexelFormat::r8_uint; + case core::TexelFormat::kR8Sint: + return pb::TexelFormat::r8_sint; + case core::TexelFormat::kRg8Unorm: + return pb::TexelFormat::rg8_unorm; + case core::TexelFormat::kRg8Snorm: + return pb::TexelFormat::rg8_snorm; + case core::TexelFormat::kRg8Uint: + return pb::TexelFormat::rg8_uint; + case core::TexelFormat::kRg8Sint: + return pb::TexelFormat::rg8_sint; + case core::TexelFormat::kR16Uint: + return pb::TexelFormat::r16_uint; + case core::TexelFormat::kR16Sint: + return pb::TexelFormat::r16_sint; + case core::TexelFormat::kR16Float: + return pb::TexelFormat::r16_float; + case core::TexelFormat::kRg16Uint: + return pb::TexelFormat::rg16_uint; + case core::TexelFormat::kRg16Sint: + return pb::TexelFormat::rg16_sint; + case core::TexelFormat::kRg16Float: + return pb::TexelFormat::rg16_float; + case core::TexelFormat::kRgb10A2Uint: + return pb::TexelFormat::rgb10a2_uint; + case core::TexelFormat::kRgb10A2Unorm: + return pb::TexelFormat::rgb10a2_unorm; + case core::TexelFormat::kRg11B10Ufloat: + return pb::TexelFormat::rg11b10_ufloat; + case core::TexelFormat::kR16Unorm: + return pb::TexelFormat::r16_unorm; + case core::TexelFormat::kR16Snorm: + return pb::TexelFormat::r16_snorm; + case core::TexelFormat::kRg16Unorm: + return pb::TexelFormat::rg16_unorm; + case core::TexelFormat::kRg16Snorm: + return pb::TexelFormat::rg16_snorm; + case core::TexelFormat::kRgba16Unorm: + return pb::TexelFormat::rgba16_unorm; + case core::TexelFormat::kRgba16Snorm: + return pb::TexelFormat::rgba16_snorm; + case core::TexelFormat::kUndefined: + break; + } + + TINT_ICE() << "invalid TexelFormat: " << in; + } + + pb::SamplerKind SamplerKind(core::type::SamplerKind in) { + switch (in) { + case core::type::SamplerKind::kSampler: + return pb::SamplerKind::sampler; + case core::type::SamplerKind::kComparisonSampler: + return pb::SamplerKind::comparison; + } + + TINT_ICE() << "invalid SamplerKind: " << in; + } + + pb::InterpolationType InterpolationType(core::InterpolationType in) { + switch (in) { + case core::InterpolationType::kFlat: + return pb::InterpolationType::flat; + case core::InterpolationType::kLinear: + return pb::InterpolationType::linear; + case core::InterpolationType::kPerspective: + return pb::InterpolationType::perspective; + case core::InterpolationType::kUndefined: + break; + } + TINT_ICE() << "invalid InterpolationType: " << in; + } + + pb::InterpolationSampling InterpolationSampling(core::InterpolationSampling in) { + switch (in) { + case core::InterpolationSampling::kCenter: + return pb::InterpolationSampling::center; + case core::InterpolationSampling::kCentroid: + return pb::InterpolationSampling::centroid; + case core::InterpolationSampling::kSample: + return pb::InterpolationSampling::sample; + case core::InterpolationSampling::kFirst: + return pb::InterpolationSampling::first; + case core::InterpolationSampling::kEither: + return pb::InterpolationSampling::either; + case core::InterpolationSampling::kUndefined: + break; + } + TINT_ICE() << "invalid InterpolationSampling: " << in; + } + + pb::BuiltinValue BuiltinValue(core::BuiltinValue in) { + switch (in) { + case core::BuiltinValue::kPointSize: + return pb::BuiltinValue::point_size; + case core::BuiltinValue::kCullDistance: + return pb::BuiltinValue::cull_distance; + case core::BuiltinValue::kFragDepth: + return pb::BuiltinValue::frag_depth; + case core::BuiltinValue::kFrontFacing: + return pb::BuiltinValue::front_facing; + case core::BuiltinValue::kGlobalInvocationId: + return pb::BuiltinValue::global_invocation_id; + case core::BuiltinValue::kInstanceIndex: + return pb::BuiltinValue::instance_index; + case core::BuiltinValue::kLocalInvocationId: + return pb::BuiltinValue::local_invocation_id; + case core::BuiltinValue::kLocalInvocationIndex: + return pb::BuiltinValue::local_invocation_index; + case core::BuiltinValue::kNumWorkgroups: + return pb::BuiltinValue::num_workgroups; + case core::BuiltinValue::kPosition: + return pb::BuiltinValue::position; + case core::BuiltinValue::kSampleIndex: + return pb::BuiltinValue::sample_index; + case core::BuiltinValue::kSampleMask: + return pb::BuiltinValue::sample_mask; + case core::BuiltinValue::kSubgroupId: + return pb::BuiltinValue::subgroup_id; + case core::BuiltinValue::kSubgroupInvocationId: + return pb::BuiltinValue::subgroup_invocation_id; + case core::BuiltinValue::kSubgroupSize: + return pb::BuiltinValue::subgroup_size; + case core::BuiltinValue::kNumSubgroups: + return pb::BuiltinValue::num_subgroups; + case core::BuiltinValue::kVertexIndex: + return pb::BuiltinValue::vertex_index; + case core::BuiltinValue::kWorkgroupId: + return pb::BuiltinValue::workgroup_id; + case core::BuiltinValue::kClipDistances: + return pb::BuiltinValue::clip_distances; + case core::BuiltinValue::kPrimitiveIndex: + return pb::BuiltinValue::primitive_index; + case core::BuiltinValue::kBarycentricCoord: + return pb::BuiltinValue::barycentric_coord; + case core::BuiltinValue::kUndefined: + break; + } + TINT_ICE() << "invalid BuiltinValue: " << in; + } + + pb::BuiltinFn BuiltinFn(core::BuiltinFn in) { + switch (in) { + case core::BuiltinFn::kAbs: + return pb::BuiltinFn::abs; + case core::BuiltinFn::kAcos: + return pb::BuiltinFn::acos; + case core::BuiltinFn::kAcosh: + return pb::BuiltinFn::acosh; + case core::BuiltinFn::kAll: + return pb::BuiltinFn::all; + case core::BuiltinFn::kAny: + return pb::BuiltinFn::any; + case core::BuiltinFn::kArrayLength: + return pb::BuiltinFn::array_length; + case core::BuiltinFn::kAsin: + return pb::BuiltinFn::asin; + case core::BuiltinFn::kAsinh: + return pb::BuiltinFn::asinh; + case core::BuiltinFn::kAtan: + return pb::BuiltinFn::atan; + case core::BuiltinFn::kAtan2: + return pb::BuiltinFn::atan2; + case core::BuiltinFn::kAtanh: + return pb::BuiltinFn::atanh; + case core::BuiltinFn::kCeil: + return pb::BuiltinFn::ceil; + case core::BuiltinFn::kClamp: + return pb::BuiltinFn::clamp; + case core::BuiltinFn::kCos: + return pb::BuiltinFn::cos; + case core::BuiltinFn::kCosh: + return pb::BuiltinFn::cosh; + case core::BuiltinFn::kCountLeadingZeros: + return pb::BuiltinFn::count_leading_zeros; + case core::BuiltinFn::kCountOneBits: + return pb::BuiltinFn::count_one_bits; + case core::BuiltinFn::kCountTrailingZeros: + return pb::BuiltinFn::count_trailing_zeros; + case core::BuiltinFn::kCross: + return pb::BuiltinFn::cross; + case core::BuiltinFn::kDegrees: + return pb::BuiltinFn::degrees; + case core::BuiltinFn::kDeterminant: + return pb::BuiltinFn::determinant; + case core::BuiltinFn::kDistance: + return pb::BuiltinFn::distance; + case core::BuiltinFn::kDot: + return pb::BuiltinFn::dot; + case core::BuiltinFn::kDot4I8Packed: + return pb::BuiltinFn::dot4i8_packed; + case core::BuiltinFn::kDot4U8Packed: + return pb::BuiltinFn::dot4u8_packed; + case core::BuiltinFn::kDpdx: + return pb::BuiltinFn::dpdx; + case core::BuiltinFn::kDpdxCoarse: + return pb::BuiltinFn::dpdx_coarse; + case core::BuiltinFn::kDpdxFine: + return pb::BuiltinFn::dpdx_fine; + case core::BuiltinFn::kDpdy: + return pb::BuiltinFn::dpdy; + case core::BuiltinFn::kDpdyCoarse: + return pb::BuiltinFn::dpdy_coarse; + case core::BuiltinFn::kDpdyFine: + return pb::BuiltinFn::dpdy_fine; + case core::BuiltinFn::kExp: + return pb::BuiltinFn::exp; + case core::BuiltinFn::kExp2: + return pb::BuiltinFn::exp2; + case core::BuiltinFn::kExtractBits: + return pb::BuiltinFn::extract_bits; + case core::BuiltinFn::kFaceForward: + return pb::BuiltinFn::face_forward; + case core::BuiltinFn::kFirstLeadingBit: + return pb::BuiltinFn::first_leading_bit; + case core::BuiltinFn::kFirstTrailingBit: + return pb::BuiltinFn::first_trailing_bit; + case core::BuiltinFn::kFloor: + return pb::BuiltinFn::floor; + case core::BuiltinFn::kFma: + return pb::BuiltinFn::fma; + case core::BuiltinFn::kFract: + return pb::BuiltinFn::fract; + case core::BuiltinFn::kFrexp: + return pb::BuiltinFn::frexp; + case core::BuiltinFn::kFwidth: + return pb::BuiltinFn::fwidth; + case core::BuiltinFn::kFwidthCoarse: + return pb::BuiltinFn::fwidth_coarse; + case core::BuiltinFn::kFwidthFine: + return pb::BuiltinFn::fwidth_fine; + case core::BuiltinFn::kInsertBits: + return pb::BuiltinFn::insert_bits; + case core::BuiltinFn::kInverseSqrt: + return pb::BuiltinFn::inverse_sqrt; + case core::BuiltinFn::kLdexp: + return pb::BuiltinFn::ldexp; + case core::BuiltinFn::kLength: + return pb::BuiltinFn::length; + case core::BuiltinFn::kLog: + return pb::BuiltinFn::log; + case core::BuiltinFn::kLog2: + return pb::BuiltinFn::log2; + case core::BuiltinFn::kMax: + return pb::BuiltinFn::max; + case core::BuiltinFn::kMin: + return pb::BuiltinFn::min; + case core::BuiltinFn::kMix: + return pb::BuiltinFn::mix; + case core::BuiltinFn::kModf: + return pb::BuiltinFn::modf; + case core::BuiltinFn::kNormalize: + return pb::BuiltinFn::normalize; + case core::BuiltinFn::kPack2X16Float: + return pb::BuiltinFn::pack2x16_float; + case core::BuiltinFn::kPack2X16Snorm: + return pb::BuiltinFn::pack2x16_snorm; + case core::BuiltinFn::kPack2X16Unorm: + return pb::BuiltinFn::pack2x16_unorm; + case core::BuiltinFn::kPack4X8Snorm: + return pb::BuiltinFn::pack4x8_snorm; + case core::BuiltinFn::kPack4X8Unorm: + return pb::BuiltinFn::pack4x8_unorm; + case core::BuiltinFn::kPack4XI8: + return pb::BuiltinFn::pack4xi8; + case core::BuiltinFn::kPack4XU8: + return pb::BuiltinFn::pack4xu8; + case core::BuiltinFn::kPack4XI8Clamp: + return pb::BuiltinFn::pack4xi8_clamp; + case core::BuiltinFn::kPack4XU8Clamp: + return pb::BuiltinFn::pack4xu8_clamp; + case core::BuiltinFn::kPow: + return pb::BuiltinFn::pow; + case core::BuiltinFn::kQuantizeToF16: + return pb::BuiltinFn::quantize_to_f16; + case core::BuiltinFn::kRadians: + return pb::BuiltinFn::radians; + case core::BuiltinFn::kReflect: + return pb::BuiltinFn::reflect; + case core::BuiltinFn::kRefract: + return pb::BuiltinFn::refract; + case core::BuiltinFn::kReverseBits: + return pb::BuiltinFn::reverse_bits; + case core::BuiltinFn::kRound: + return pb::BuiltinFn::round; + case core::BuiltinFn::kSaturate: + return pb::BuiltinFn::saturate; + case core::BuiltinFn::kSelect: + return pb::BuiltinFn::select; + case core::BuiltinFn::kSign: + return pb::BuiltinFn::sign; + case core::BuiltinFn::kSin: + return pb::BuiltinFn::sin; + case core::BuiltinFn::kSinh: + return pb::BuiltinFn::sinh; + case core::BuiltinFn::kSmoothstep: + return pb::BuiltinFn::smoothstep; + case core::BuiltinFn::kSqrt: + return pb::BuiltinFn::sqrt; + case core::BuiltinFn::kStep: + return pb::BuiltinFn::step; + case core::BuiltinFn::kStorageBarrier: + return pb::BuiltinFn::storage_barrier; + case core::BuiltinFn::kTan: + return pb::BuiltinFn::tan; + case core::BuiltinFn::kTanh: + return pb::BuiltinFn::tanh; + case core::BuiltinFn::kTranspose: + return pb::BuiltinFn::transpose; + case core::BuiltinFn::kTrunc: + return pb::BuiltinFn::trunc; + case core::BuiltinFn::kUnpack2X16Float: + return pb::BuiltinFn::unpack2x16_float; + case core::BuiltinFn::kUnpack2X16Snorm: + return pb::BuiltinFn::unpack2x16_snorm; + case core::BuiltinFn::kUnpack2X16Unorm: + return pb::BuiltinFn::unpack2x16_unorm; + case core::BuiltinFn::kUnpack4X8Snorm: + return pb::BuiltinFn::unpack4x8_snorm; + case core::BuiltinFn::kUnpack4X8Unorm: + return pb::BuiltinFn::unpack4x8_unorm; + case core::BuiltinFn::kUnpack4XI8: + return pb::BuiltinFn::unpack4xi8; + case core::BuiltinFn::kUnpack4XU8: + return pb::BuiltinFn::unpack4xu8; + case core::BuiltinFn::kWorkgroupBarrier: + return pb::BuiltinFn::workgroup_barrier; + case core::BuiltinFn::kTextureBarrier: + return pb::BuiltinFn::texture_barrier; + case core::BuiltinFn::kTextureDimensions: + return pb::BuiltinFn::texture_dimensions; + case core::BuiltinFn::kTextureGather: + return pb::BuiltinFn::texture_gather; + case core::BuiltinFn::kTextureGatherCompare: + return pb::BuiltinFn::texture_gather_compare; + case core::BuiltinFn::kTextureNumLayers: + return pb::BuiltinFn::texture_num_layers; + case core::BuiltinFn::kTextureNumLevels: + return pb::BuiltinFn::texture_num_levels; + case core::BuiltinFn::kTextureNumSamples: + return pb::BuiltinFn::texture_num_samples; + case core::BuiltinFn::kTextureSample: + return pb::BuiltinFn::texture_sample; + case core::BuiltinFn::kTextureSampleBias: + return pb::BuiltinFn::texture_sample_bias; + case core::BuiltinFn::kTextureSampleCompare: + return pb::BuiltinFn::texture_sample_compare; + case core::BuiltinFn::kTextureSampleCompareLevel: + return pb::BuiltinFn::texture_sample_compare_level; + case core::BuiltinFn::kTextureSampleGrad: + return pb::BuiltinFn::texture_sample_grad; + case core::BuiltinFn::kTextureSampleLevel: + return pb::BuiltinFn::texture_sample_level; + case core::BuiltinFn::kTextureSampleBaseClampToEdge: + return pb::BuiltinFn::texture_sample_base_clamp_to_edge; + case core::BuiltinFn::kTextureStore: + return pb::BuiltinFn::texture_store; + case core::BuiltinFn::kTextureLoad: + return pb::BuiltinFn::texture_load; + case core::BuiltinFn::kAtomicLoad: + return pb::BuiltinFn::atomic_load; + case core::BuiltinFn::kAtomicStore: + return pb::BuiltinFn::atomic_store; + case core::BuiltinFn::kAtomicAdd: + return pb::BuiltinFn::atomic_add; + case core::BuiltinFn::kAtomicSub: + return pb::BuiltinFn::atomic_sub; + case core::BuiltinFn::kAtomicMax: + return pb::BuiltinFn::atomic_max; + case core::BuiltinFn::kAtomicMin: + return pb::BuiltinFn::atomic_min; + case core::BuiltinFn::kAtomicAnd: + return pb::BuiltinFn::atomic_and; + case core::BuiltinFn::kAtomicOr: + return pb::BuiltinFn::atomic_or; + case core::BuiltinFn::kAtomicXor: + return pb::BuiltinFn::atomic_xor; + case core::BuiltinFn::kAtomicExchange: + return pb::BuiltinFn::atomic_exchange; + case core::BuiltinFn::kAtomicCompareExchangeWeak: + return pb::BuiltinFn::atomic_compare_exchange_weak; + case core::BuiltinFn::kSubgroupBallot: + return pb::BuiltinFn::subgroup_ballot; + case core::BuiltinFn::kSubgroupElect: + return pb::BuiltinFn::subgroup_elect; + case core::BuiltinFn::kSubgroupBroadcast: + return pb::BuiltinFn::subgroup_broadcast; + case core::BuiltinFn::kSubgroupBroadcastFirst: + return pb::BuiltinFn::subgroup_broadcast_first; + case core::BuiltinFn::kSubgroupShuffle: + return pb::BuiltinFn::subgroup_shuffle; + case core::BuiltinFn::kSubgroupShuffleXor: + return pb::BuiltinFn::subgroup_shuffle_xor; + case core::BuiltinFn::kSubgroupShuffleUp: + return pb::BuiltinFn::subgroup_shuffle_up; + case core::BuiltinFn::kSubgroupShuffleDown: + return pb::BuiltinFn::subgroup_shuffle_down; + case core::BuiltinFn::kInputAttachmentLoad: + return pb::BuiltinFn::input_attachment_load; + case core::BuiltinFn::kSubgroupAdd: + return pb::BuiltinFn::subgroup_add; + case core::BuiltinFn::kSubgroupInclusiveAdd: + return pb::BuiltinFn::subgroup_inclusive_add; + case core::BuiltinFn::kSubgroupExclusiveAdd: + return pb::BuiltinFn::subgroup_exclusive_add; + case core::BuiltinFn::kSubgroupMul: + return pb::BuiltinFn::subgroup_mul; + case core::BuiltinFn::kSubgroupInclusiveMul: + return pb::BuiltinFn::subgroup_inclusive_mul; + case core::BuiltinFn::kSubgroupExclusiveMul: + return pb::BuiltinFn::subgroup_exclusive_mul; + case core::BuiltinFn::kSubgroupAnd: + return pb::BuiltinFn::subgroup_and; + case core::BuiltinFn::kSubgroupOr: + return pb::BuiltinFn::subgroup_or; + case core::BuiltinFn::kSubgroupXor: + return pb::BuiltinFn::subgroup_xor; + case core::BuiltinFn::kSubgroupMin: + return pb::BuiltinFn::subgroup_min; + case core::BuiltinFn::kSubgroupMax: + return pb::BuiltinFn::subgroup_max; + case core::BuiltinFn::kSubgroupAll: + return pb::BuiltinFn::subgroup_all; + case core::BuiltinFn::kSubgroupAny: + return pb::BuiltinFn::subgroup_any; + case core::BuiltinFn::kQuadBroadcast: + return pb::BuiltinFn::quad_broadcast; + case core::BuiltinFn::kQuadSwapX: + return pb::BuiltinFn::quad_swap_x; + case core::BuiltinFn::kQuadSwapY: + return pb::BuiltinFn::quad_swap_y; + case core::BuiltinFn::kQuadSwapDiagonal: + return pb::BuiltinFn::quad_swap_diagonal; + case core::BuiltinFn::kSubgroupMatrixLoad: + return pb::BuiltinFn::subgroup_matrix_load; + case core::BuiltinFn::kSubgroupMatrixStore: + return pb::BuiltinFn::subgroup_matrix_store; + case core::BuiltinFn::kSubgroupMatrixMultiply: + return pb::BuiltinFn::subgroup_matrix_multiply; + case core::BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + return pb::BuiltinFn::subgroup_matrix_multiply_accumulate; + case core::BuiltinFn::kSubgroupMatrixScalarAdd: + return pb::BuiltinFn::subgroup_matrix_scalar_add; + case core::BuiltinFn::kSubgroupMatrixScalarSubtract: + return pb::BuiltinFn::subgroup_matrix_scalar_subtract; + case core::BuiltinFn::kSubgroupMatrixScalarMultiply: + return pb::BuiltinFn::subgroup_matrix_scalar_multiply; + case core::BuiltinFn::kPrint: + return pb::BuiltinFn::print; + case core::BuiltinFn::kHasResource: + return pb::BuiltinFn::has_resource; + case core::BuiltinFn::kGetResource: + return pb::BuiltinFn::get_resource; + case core::BuiltinFn::kBufferView: + return pb::BuiltinFn::buffer_view; + case core::BuiltinFn::kBufferLength: + return pb::BuiltinFn::buffer_length; + case core::BuiltinFn::kNone: + break; + } + TINT_ICE() << "invalid BuiltinFn: " << in; + } +}; + +} // namespace + +Result> EncodeToProto(const Module& mod_in) { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + pb::Module mod_out; + TINT_CHECK_RESULT((Encoder{mod_in, mod_out}.Encode())); + + return std::make_unique(mod_out); +} + +Result> EncodeToBinary(const Module& mod_in) { + TINT_CHECK_RESULT_UNWRAP(mod_out, EncodeToProto(mod_in)); + + Vector buffer; + size_t len = mod_out->ByteSizeLong(); + buffer.Resize(len); + if (len > 0) { + if (!mod_out->SerializeToArray(&buffer[0], static_cast(len))) { + return Failure{"failed to serialize protobuf"}; + } + } + return buffer; +} + +} // namespace tint::core::ir::binary diff --git a/3rdparty/dawn/src/tint/lang/core/ir/binary/encode.h b/3rdparty/dawn/src/tint/lang/core/ir/binary/encode.h new file mode 100644 index 000000000..fa2028594 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/binary/encode.h @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BINARY_ENCODE_H_ +#define SRC_TINT_LANG_CORE_IR_BINARY_ENCODE_H_ + +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::binary::pb { +class Module; +} + +namespace tint::core::ir::binary { + +// Encode the module into a proto representation. +Result> EncodeToProto(const Module& module); + +// Encode the module into a binary representation. +Result> EncodeToBinary(const Module& module); + +} // namespace tint::core::ir::binary + +#endif // SRC_TINT_LANG_CORE_IR_BINARY_ENCODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/bitcast.cc b/3rdparty/dawn/src/tint/lang/core/ir/bitcast.cc new file mode 100644 index 000000000..ad8cad6d2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/bitcast.cc @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/bitcast.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Bitcast); + +namespace tint::core::ir { + +Bitcast::Bitcast(Id id) : Base(id) {} + +Bitcast::Bitcast(Id id, InstructionResult* result, Value* val) : Base(id) { + AddOperand(Bitcast::kValueOperandOffset, val); + AddResult(result); +} + +Bitcast::~Bitcast() = default; + +Bitcast* Bitcast::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* val = ctx.Remap(Val()); + return ctx.ir.CreateInstruction(new_result, val); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/bitcast.h b/3rdparty/dawn/src/tint/lang/core/ir/bitcast.h new file mode 100644 index 000000000..f75d007a8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/bitcast.h @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BITCAST_H_ +#define SRC_TINT_LANG_CORE_IR_BITCAST_H_ + +#include + +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A bitcast instruction in the IR. +class Bitcast final : public Castable { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands expected for this instruction + static constexpr size_t kNumOperands = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Bitcast(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param val the value being bitcast + Bitcast(Id id, InstructionResult* result, Value* val); + + ~Bitcast() override; + + /// @copydoc Instruction::Clone() + Bitcast* Clone(CloneContext& ctx) override; + + /// @returns the operand value + Value* Val() { return Operand(kValueOperandOffset); } + + /// @returns the operand value + const Value* Val() const { return Operand(kValueOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "bitcast"; } + + /// @returns an empty access as the bitcast neither loads nor stores. + Accesses GetSideEffects() const override { return Accesses{}; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BITCAST_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/block.cc b/3rdparty/dawn/src/tint/lang/core/ir/block.cc new file mode 100644 index 000000000..6d4a80377 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/block.cc @@ -0,0 +1,207 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/block.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Block); + +namespace tint::core::ir { + +Block::Block() : Base() {} + +Block::~Block() = default; + +Block* Block::Clone(CloneContext&) { + TINT_UNREACHABLE() << "blocks must be cloned with CloneInto"; +} + +void Block::CloneInto(CloneContext& ctx, Block* out) { + // Note, the `parent_` is not cloned here. Doing so can end up in infinite loops as we try to + // clone a control instruction and the blocks inside of it. The `parent_` pointer should be set + // by the control instructions constructor. + + for (auto* inst_in : *this) { + auto* inst_out = inst_in->Clone(ctx); + auto results_out = inst_out->Results(); + auto results_in = inst_in->Results(); + TINT_ASSERT(results_out.Length() == results_in.Length()); + + size_t len = results_out.Length(); + for (size_t i = 0; i < len; ++i) { + ctx.Replace(results_in[i], results_out[i]); + } + out->Append(inst_out); + } +} + +Instruction* Block::Prepend(Instruction* inst) { + TINT_ASSERT(inst); + TINT_ASSERT(inst->Block() == nullptr); + + inst->SetBlock(this); + instructions_.count += 1; + + if (instructions_.first == nullptr) { + instructions_.first = inst; + instructions_.last = inst; + } else { + inst->next = instructions_.first; + instructions_.first->prev = inst; + instructions_.first = inst; + } + + return inst; +} + +Instruction* Block::Append(Instruction* inst) { + TINT_ASSERT(inst); + TINT_ASSERT(inst->Block() == nullptr); + + inst->SetBlock(this); + instructions_.count += 1; + + if (instructions_.first == nullptr) { + instructions_.first = inst; + instructions_.last = inst; + } else { + inst->prev = instructions_.last; + instructions_.last->next = inst; + instructions_.last = inst; + } + + return inst; +} + +void Block::InsertBefore(Instruction* before, Instruction* inst) { + TINT_ASSERT(before); + TINT_ASSERT(inst); + TINT_ASSERT(before->Block() == this); + TINT_ASSERT(inst->Block() == nullptr); + + inst->SetBlock(this); + instructions_.count += 1; + + inst->next = before; + inst->prev = before->prev; + before->prev = inst; + + if (inst->prev) { + inst->prev->next = inst; + } + + if (before == instructions_.first) { + instructions_.first = inst; + } +} + +void Block::InsertAfter(Instruction* after, Instruction* inst) { + TINT_ASSERT(after); + TINT_ASSERT(inst); + TINT_ASSERT(after->Block() == this); + TINT_ASSERT(inst->Block() == nullptr); + + inst->SetBlock(this); + instructions_.count += 1; + + inst->prev = after; + inst->next = after->next; + after->next = inst; + + if (inst->next) { + inst->next->prev = inst; + } + if (after == instructions_.last) { + instructions_.last = inst; + } +} + +void Block::Replace(Instruction* target, Instruction* inst) { + TINT_ASSERT(target); + TINT_ASSERT(inst); + TINT_ASSERT(target->Block() == this); + TINT_ASSERT(inst->Block() == nullptr); + + inst->SetBlock(this); + target->SetBlock(nullptr); + + inst->next = target->next; + inst->prev = target->prev; + + target->next = nullptr; + target->prev = nullptr; + + if (inst->next) { + inst->next->prev = inst; + } + if (inst->prev) { + inst->prev->next = inst; + } + + if (target == instructions_.first) { + instructions_.first = inst; + } + if (target == instructions_.last) { + instructions_.last = inst; + } +} + +void Block::Remove(Instruction* inst) { + TINT_ASSERT(inst); + TINT_ASSERT(inst->Block() == this); + + inst->SetBlock(nullptr); + instructions_.count -= 1; + + if (inst->prev) { + inst->prev->next = inst->next; + } + if (inst->next) { + inst->next->prev = inst->prev; + } + if (inst == instructions_.first) { + instructions_.first = inst->next; + } + if (inst == instructions_.last) { + instructions_.last = inst->prev; + } + + inst->prev = nullptr; + inst->next = nullptr; +} + +void Block::Destroy() { + while (instructions_.first) { + instructions_.first->Destroy(); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/block.h b/3rdparty/dawn/src/tint/lang/core/ir/block.h new file mode 100644 index 000000000..5869aee3f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/block.h @@ -0,0 +1,194 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BLOCK_H_ +#define SRC_TINT_LANG_CORE_IR_BLOCK_H_ + +#include + +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/terminator.h" +#include "src/tint/utils/containers/vector.h" + +// Forward declarations +namespace tint::core::ir { +class ControlInstruction; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A block of statements. The instructions in the block are a linear list of instructions to +/// execute. The block will terminate with a Terminator instruction at the end. +/// The instructions are held in a doubly-linked list with explicit first and last pointer, +/// and with an explicit count. +class Block : public Castable { + public: + /// Constructor + Block(); + ~Block() override; + + /// @param ctx the CloneContext used to clone this block + /// @returns a clone of this block + virtual Block* Clone(CloneContext& ctx); + + /// Clones the block contents into the given block + /// @param ctx the CloneContext used to clone + /// @param out the block to clone into + virtual void CloneInto(CloneContext& ctx, Block* out); + + /// @return the terminator instruction for this block, or nullptr if this block does not end in + /// a terminator. + ir::Terminator* Terminator() { return tint::As(instructions_.last); } + + /// @return the terminator instruction for this block, or nullptr if this block does not end in + /// a terminator. + const ir::Terminator* Terminator() const { + return tint::As(instructions_.last); + } + + /// @returns the instructions in the block + Instruction* Instructions() { return instructions_.first; } + + /// @returns the instructions in the block + const Instruction* Instructions() const { return instructions_.first; } + + /// Iterator for the instructions inside a block + template + class Iterator { + public: + /// Constructor + /// @param inst the instruction to start iterating from + explicit Iterator(T* inst) : inst_(inst) {} + ~Iterator() = default; + + /// Dereference operator + /// @returns the instruction for this iterator + T* operator*() const { return inst_; } + + /// Comparison operator + /// @param itr to compare against + /// @returns true if this iterator and @p itr point to the same instruction + bool operator==(const Iterator& itr) const { return itr.inst_ == inst_; } + + /// Not equal operator + /// @param itr to compare against + /// @returns true if this iterator and @p itr point to different instructions + bool operator!=(const Iterator& itr) const { return !(*this == itr); } + + /// Increment operator + /// @returns this iterator advanced to the next element + Iterator& operator++() { + inst_ = inst_->next; + return *this; + } + + private: + T* inst_ = nullptr; + }; + + /// @returns the iterator pointing to the start of the instruction list + Iterator begin() { return Iterator{instructions_.first}; } + + /// @returns the ending iterator + Iterator end() { return Iterator{nullptr}; } + + /// @returns the iterator pointing to the start of the instruction list + Iterator begin() const { + return Iterator{instructions_.first}; + } + + /// @returns the ending iterator + Iterator end() const { return Iterator{nullptr}; } + + /// @returns the first instruction in the instruction list + Instruction* Front() { return instructions_.first; } + + /// @returns the first instruction in the instruction list + const Instruction* Front() const { return instructions_.first; } + + /// @returns the last instruction in the instruction list + Instruction* Back() { return instructions_.last; } + + /// @returns the last instruction in the instruction list + const Instruction* Back() const { return instructions_.last; } + + /// Adds the instruction to the beginning of the block + /// @param inst the instruction to add + /// @returns the instruction to allow calls to be chained + Instruction* Prepend(Instruction* inst); + /// Adds the instruction to the end of the block + /// @param inst the instruction to add + /// @returns the instruction to allow calls to be chained + Instruction* Append(Instruction* inst); + /// Adds the new instruction before the given instruction + /// @param before the instruction to insert before + /// @param inst the instruction to insert + void InsertBefore(Instruction* before, Instruction* inst); + /// Adds the new instruction after the given instruction + /// @param after the instruction to insert after + /// @param inst the instruction to insert + void InsertAfter(Instruction* after, Instruction* inst); + /// Replaces the target instruction with the new instruction + /// @param target the instruction to replace + /// @param inst the instruction to insert + void Replace(Instruction* target, Instruction* inst); + /// Removes the target instruction + /// @param inst the instruction to remove + void Remove(Instruction* inst); + + /// @returns true if the block contains no instructions + bool IsEmpty() const { return Length() == 0; } + + /// @returns the number of instructions in the block + size_t Length() const { return instructions_.count; } + + /// @return the parent instruction that owns this block + ControlInstruction* Parent() { return parent_; } + + /// @return the parent instruction that owns this block + const ControlInstruction* Parent() const { return parent_; } + + /// @param parent the parent instruction that owns this block + void SetParent(ControlInstruction* parent) { parent_ = parent; } + + /// Destroys the block and all of its instructions. + void Destroy(); + + private: + // The first and last pointers are null if and only if the list is empty. + struct { + Instruction* first = nullptr; + Instruction* last = nullptr; + size_t count = 0; + } instructions_; + + ControlInstruction* parent_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BLOCK_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/block_param.cc b/3rdparty/dawn/src/tint/lang/core/ir/block_param.cc new file mode 100644 index 000000000..9ea1bb3d6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/block_param.cc @@ -0,0 +1,54 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/block_param.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::BlockParam); + +namespace tint::core::ir { + +BlockParam::BlockParam(const core::type::Type* ty) : Base(ty) { + TINT_ASSERT(ty != nullptr); +} + +BlockParam::~BlockParam() = default; + +BlockParam* BlockParam::Clone(CloneContext& ctx) { + auto* new_bp = ctx.ir.CreateValue(Type()); + + auto name = ctx.ir.NameOf(this); + if (name.IsValid()) { + ctx.ir.SetName(new_bp, ctx.ir.NameOf(this).Name()); + } + return new_bp; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/block_param.h b/3rdparty/dawn/src/tint/lang/core/ir/block_param.h new file mode 100644 index 000000000..0d0ee82d7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/block_param.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BLOCK_PARAM_H_ +#define SRC_TINT_LANG_CORE_IR_BLOCK_PARAM_H_ + +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class MultiInBlock; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A block parameter in the IR. +class BlockParam : public Castable { + public: + /// Constructor + /// @param type the type of the parameter + explicit BlockParam(const core::type::Type* type); + ~BlockParam() override; + + /// Sets the block that this parameter belongs to. + /// @param block the block + void SetBlock(MultiInBlock* block) { block_ = block; } + + /// @returns the block that this parameter belongs to, or nullptr + MultiInBlock* Block() { return block_; } + + /// @returns the block that this parameter belongs to, or nullptr + const MultiInBlock* Block() const { return block_; } + + /// @copydoc Instruction::Clone() + BlockParam* Clone(CloneContext& ctx) override; + + private: + /// the block that the parameter belongs to + MultiInBlock* block_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BLOCK_PARAM_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/break_if.cc b/3rdparty/dawn/src/tint/lang/core/ir/break_if.cc new file mode 100644 index 000000000..9ab1be773 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/break_if.cc @@ -0,0 +1,90 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/break_if.h" + +#include + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::BreakIf); + +namespace tint::core::ir { + +BreakIf::BreakIf(Id id) : Base(id) {} + +BreakIf::BreakIf(Id id, + Value* condition, + ir::Loop* loop, + VectorRef next_iter_values /* = tint::Empty */, + VectorRef exit_values /* = tint::Empty */) + : Base(id), loop_(loop), num_next_iter_values_(next_iter_values.Length()) { + TINT_ASSERT(loop_); + + AddOperand(BreakIf::kConditionOperandOffset, condition); + AddOperands(BreakIf::kArgsOperandOffset, std::move(next_iter_values)); + AddOperands(BreakIf::kArgsOperandOffset + num_next_iter_values_, std::move(exit_values)); + + if (loop_) { + loop_->Body()->AddInboundSiblingBranch(this); + SetControlInstruction(loop_); + } +} + +BreakIf::~BreakIf() = default; + +void BreakIf::Destroy() { + if (loop_) { + loop_->Body()->RemoveInboundSiblingBranch(this); + } + Instruction::Destroy(); +} + +BreakIf* BreakIf::Clone(CloneContext& ctx) { + auto* loop = ctx.Remap(loop_); + auto* cond = ctx.Remap(Condition()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(cond, loop, args); +} + +void BreakIf::SetLoop(ir::Loop* loop) { + if (loop_ && loop_->Body()) { + loop_->Body()->RemoveInboundSiblingBranch(this); + } + loop_ = loop; + SetControlInstruction(loop); + if (loop) { + loop->Body()->AddInboundSiblingBranch(this); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/break_if.h b/3rdparty/dawn/src/tint/lang/core/ir/break_if.h new file mode 100644 index 000000000..cb56b13f6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/break_if.h @@ -0,0 +1,138 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BREAK_IF_H_ +#define SRC_TINT_LANG_CORE_IR_BREAK_IF_H_ + +#include +#include + +#include "src/tint/lang/core/ir/exit.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Loop; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A break-if terminator instruction. +class BreakIf final : public Castable { + 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 (no operands, no loop) + /// @param id the instruction id + explicit BreakIf(Id id); + + /// Constructor + /// @param id the instruction id + /// @param condition the break condition + /// @param loop the loop containing the break-if + /// @param next_iter_values the arguments passed to the loop body MultiInBlock, if the break + /// condition evaluates to `false`. + /// @param exit_values the values returned by the loop, if the break condition evaluates to + /// `true`. + BreakIf(Id id, + Value* condition, + ir::Loop* loop, + VectorRef next_iter_values = tint::Empty, + VectorRef exit_values = tint::Empty); + + ~BreakIf() override; + + /// @copydoc Instruction::Destroy() + void Destroy() override; + + /// @copydoc Instruction::Clone() + BreakIf* Clone(CloneContext& ctx) override; + + /// @returns the offset of the arguments in Operands() + size_t ArgsOperandOffset() const override { return kArgsOperandOffset; } + + /// @returns the break condition + Value* Condition() { return Operand(kConditionOperandOffset); } + + /// @returns the break condition + const Value* Condition() const { return Operand(kConditionOperandOffset); } + + /// @returns the loop containing the break-if + ir::Loop* Loop() { return loop_; } + + /// @returns the loop containing the break-if + const ir::Loop* Loop() const { return loop_; } + + /// @param loop the new loop containing the continue + void SetLoop(ir::Loop* loop); + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "break_if"; } + + /// @returns the arguments passed to the loop body MultiInBlock, if the break condition + /// evaluates to `false`. + std::span NextIterValues() { + return operands_.AsSpan().subspan(kArgsOperandOffset, num_next_iter_values_); + } + + /// @returns the arguments passed to the loop body MultiInBlock, if the break condition + /// evaluates to `false`. + std::span NextIterValues() const { + return operands_.AsSpan().subspan(kArgsOperandOffset, num_next_iter_values_); + } + + /// @returns the values returned by the loop, if the break condition evaluates to `true`. + std::span ExitValues() { + return operands_.AsSpan().subspan(kArgsOperandOffset + num_next_iter_values_); + } + + /// @returns the values returned by the loop, if the break condition evaluates to `true`. + std::span ExitValues() const { + return operands_.AsSpan().subspan(kArgsOperandOffset + num_next_iter_values_); + } + + /// Sets the number of operands used as the next iterator values. + /// The first @p num operands after kArgsOperandOffset are used as next iterator values, + /// subsequent operators are used as exit values. + void SetNumNextIterValues(size_t num) { + TINT_ASSERT(operands_.Length() >= num + kArgsOperandOffset); + num_next_iter_values_ = num; + } + + private: + ir::Loop* loop_ = nullptr; + size_t num_next_iter_values_ = 0; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BREAK_IF_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/builder.cc b/3rdparty/dawn/src/tint/lang/core/ir/builder.cc new file mode 100644 index 000000000..31c562547 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/builder.cc @@ -0,0 +1,154 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/builder.h" + +#include + +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/type/function.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::core::ir { + +Builder::Builder(Module& mod) : ir(mod) {} + +Builder::Builder(Module& mod, ir::Block* block) + : insertion_point_(InsertionPoints::AppendToBlock{block}), ir(mod) {} + +Builder::~Builder() = default; + +Block* Builder::Block() { + return ir.blocks.Create(); +} + +MultiInBlock* Builder::MultiInBlock() { + return ir.blocks.Create(); +} + +Function* Builder::Function(const core::type::Type* return_type, Function::PipelineStage stage) { + auto* ir_func = ir.CreateValue(ir.Types().function(), return_type, stage); + ir_func->SetBlock(Block()); + ir.functions.Push(ir_func); + return ir_func; +} + +Function* Builder::Function(std::string_view name, + const core::type::Type* return_type, + Function::PipelineStage stage) { + auto* ir_func = Function(return_type, stage); + ir.SetName(ir_func, name); + return ir_func; +} + +ir::Loop* Builder::Loop() { + return Append(ir.CreateInstruction(Block(), MultiInBlock(), MultiInBlock())); +} + +Block* Builder::Case(ir::Switch* s, VectorRef values) { + auto* block = Block(); + + Switch::Case c; + c.block = block; + for (auto* value : values) { + c.selectors.Push(Switch::CaseSelector{value}); + } + s->Cases().Push(std::move(c)); + block->SetParent(s); + return block; +} + +Block* Builder::DefaultCase(ir::Switch* s) { + return Case(s, Vector{nullptr}); +} + +Block* Builder::Case(ir::Switch* s, std::initializer_list selectors) { + return Case(s, Vector(selectors)); +} + +ir::Discard* Builder::Discard() { + return Append(ir.CreateInstruction()); +} + +ir::Var* Builder::Var(const core::type::MemoryView* type) { + return Append(ir.CreateInstruction(InstructionResult(type))); +} + +ir::Var* Builder::Var(std::string_view name, const core::type::MemoryView* type) { + auto* var = Var(type); + ir.SetName(var, name); + return var; +} + +ir::BlockParam* Builder::BlockParam(const core::type::Type* type) { + return ir.CreateValue(type); +} + +ir::BlockParam* Builder::BlockParam(std::string_view name, const core::type::Type* type) { + auto* param = ir.CreateValue(type); + ir.SetName(param, name); + return param; +} + +ir::FunctionParam* Builder::FunctionParam(const core::type::Type* type) { + return ir.CreateValue(type); +} + +ir::FunctionParam* Builder::FunctionParam(std::string_view name, const core::type::Type* type) { + auto* param = ir.CreateValue(type); + ir.SetName(param, name); + return param; +} + +ir::TerminateInvocation* Builder::TerminateInvocation() { + return Append(ir.CreateInstruction()); +} + +ir::Unreachable* Builder::Unreachable() { + return Append(ir.CreateInstruction()); +} + +ir::Unused* Builder::Unused() { + return ir.CreateValue(); +} + +const core::type::Type* Builder::VectorPtrElementType(const core::type::Type* type) { + auto* vec_ptr_ty = type->As(); + TINT_ASSERT(vec_ptr_ty); + if (DAWN_LIKELY(vec_ptr_ty)) { + auto* vec_ty = vec_ptr_ty->StoreType()->As(); + TINT_ASSERT(vec_ty); + if (DAWN_LIKELY(vec_ty)) { + return vec_ty->Type(); + } + } + return ir.Types().i32(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/builder.h b/3rdparty/dawn/src/tint/lang/core/ir/builder.h new file mode 100644 index 000000000..988d62959 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/builder.h @@ -0,0 +1,1978 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BUILDER_H_ +#define SRC_TINT_LANG_CORE_IR_BUILDER_H_ + +#include + +#include "src/tint/lang/core/constant/scalar.h" // IWYU pragma: export +#include "src/tint/lang/core/constant/splat.h" // IWYU pragma: export +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/block_param.h" +#include "src/tint/lang/core/ir/break_if.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/continue.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_binary.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/core_unary.h" +#include "src/tint/lang/core/ir/discard.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/function_param.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/load_vector_element.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/member_builtin_call.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/phony.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/store_vector_element.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/terminate_invocation.h" +#include "src/tint/lang/core/ir/unreachable.h" +#include "src/tint/lang/core/ir/unused.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/value.h" // IWYU pragma: export +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" // IWYU pragma: export +#include "src/tint/lang/core/type/bool.h" // IWYU pragma: export +#include "src/tint/lang/core/type/f16.h" // IWYU pragma: export +#include "src/tint/lang/core/type/f32.h" // IWYU pragma: export +#include "src/tint/lang/core/type/i32.h" // IWYU pragma: export +#include "src/tint/lang/core/type/i8.h" // IWYU pragma: export +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/memory_view.h" +#include "src/tint/lang/core/type/pointer.h" // IWYU pragma: export +#include "src/tint/lang/core/type/type.h" // IWYU pragma: export +#include "src/tint/lang/core/type/u32.h" // IWYU pragma: export +#include "src/tint/lang/core/type/u64.h" // IWYU pragma: export +#include "src/tint/lang/core/type/u8.h" // IWYU pragma: export +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/lang/core/type/void.h" // IWYU pragma: export +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/macros/scoped_assignment.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir { + +/// Evaluates to true if T is a non-reference instruction pointer. +template +concept IsNonRefInstPtr = + std::is_pointer_v && std::is_base_of_v>; + +/// Builds an ir::Module +class Builder { + /// static_assert()s that ARGS contains no more than one non-reference instruction pointer. + /// This is used to detect patterns where C++ non-deterministic evaluation order may cause + /// instruction ordering bugs. + template + static constexpr void CheckForNonDeterministicEvaluation() { + constexpr bool possibly_non_deterministic_eval = + ((IsNonRefInstPtr ? 1 : 0) + ...) > 1; + static_assert(!possibly_non_deterministic_eval, + "Detected possible non-deterministic ordering of instructions. " + "Consider hoisting Builder call arguments to separate statements."); + } + + /// A namespace for the various instruction insertion method + struct InsertionPoints { + /// Insertion point method that does no insertion + struct NoInsertion { + /// The insertion point function + void operator()(ir::Instruction*) {} + }; + /// Insertion point method that inserts the instruction to the end of #block + struct AppendToBlock { + /// The block to insert new instructions to the end of + ir::Block* block = nullptr; + /// The insertion point function + /// @param i the instruction to insert + void operator()(ir::Instruction* i) { block->Append(i); } + }; + /// Insertion point method that inserts the instruction after #after and updates the + /// insertion point to be after the inserted instruction. + struct InsertAfter { + /// The instruction to insert new instructions after + ir::Instruction* after = nullptr; + /// The insertion point function + /// @param i the instruction to insert + void operator()(ir::Instruction* i) { + i->InsertAfter(after); + after = i; + } + }; + /// Insertion point method that inserts the instruction before #before + struct InsertBefore { + /// The instruction to insert new instructions before + ir::Instruction* before = nullptr; + /// The insertion point function + /// @param i the instruction to insert + void operator()(ir::Instruction* i) { i->InsertBefore(before); } + }; + }; + + /// A variant of different instruction insertion methods + using InsertionPoint = std::variant; + + /// The insertion method used for new instructions. + InsertionPoint insertion_point_{InsertionPoints::NoInsertion{}}; + + 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 append to + Builder(Module& mod, ir::Block* block); + /// Destructor + ~Builder(); + + /// Creates a new builder that will append to the given block + /// @param b the block to append new instructions to + /// @returns the builder + Builder Append(ir::Block* b) { return Builder(ir, b); } + + /// Calls @p cb with the builder appending to block @p b + /// @param b the block to set as the block to append to + /// @param cb the function to call with the builder appending to block @p b + template + void Append(ir::Block* b, FUNCTION&& cb) { + TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::AppendToBlock{b}); + cb(); + } + + /// Calls @p cb with the builder inserting after @p ip + /// @param ip the insertion point for new instructions + /// @param cb the function to call with the builder inserting new instructions after @p ip + template + void InsertAfter(ir::Instruction* ip, FUNCTION&& cb) { + TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::InsertAfter{ip}); + cb(); + } + + /// Calls @p cb with the builder inserting before @p ip + /// @param ip the insertion point for new instructions + /// @param cb the function to call with the builder inserting new instructions before @p ip + template + void InsertBefore(ir::Instruction* ip, FUNCTION&& cb) { + TINT_SCOPED_ASSIGNMENT(insertion_point_, InsertionPoints::InsertBefore{ip}); + cb(); + } + + /// Calls @p cb with the builder inserting at the first block position after @p val. This means + /// if a `FunctionParam` or `BlockParam` are provided, the callback will insert into the _next_ + /// block seen after the parameters. + /// @param val the value used to determine which block to insert into + /// @param cb the function to call with the builder inserting new instructions in the first + /// block position after @p val + template + void InsertInBlockAfter(ir::Value* val, FUNCTION&& cb) { + tint::Switch( + val, + [&](core::ir::InstructionResult* result) { + const TINT_SCOPED_ASSIGNMENT(insertion_point_, + InsertionPoints::InsertAfter{result->Instruction()}); + cb(); + }, + [&](core::ir::FunctionParam* param) { + auto* body = param->Function()->Block(); + if (body->IsEmpty()) { + Append(body, cb); + } else { + InsertBefore(body->Front(), cb); + } + }, + [&](core::ir::BlockParam* param) { + auto* block = param->Block(); + if (block->IsEmpty()) { + Append(block, cb); + } else { + InsertBefore(block->Front(), cb); + } + }, + TINT_ICE_ON_NO_MATCH); + } + + /// Adds and returns the instruction @p instruction to the current insertion point. If there + /// is no current insertion point set, then @p instruction is just returned. + /// @param instruction the instruction to append + /// @returns the instruction + template + T* Append(T* instruction) { + std::visit([instruction](auto&& mode) { mode(instruction); }, insertion_point_); + return instruction; + } + + /// @returns a new block + ir::Block* Block(); + + /// @returns a new multi-in block + ir::MultiInBlock* MultiInBlock(); + + /// Creates an unnamed function + /// @param return_type the function return type + /// @param stage the function stage + /// @returns the function + ir::Function* Function(const core::type::Type* return_type, + Function::PipelineStage stage = Function::PipelineStage::kUndefined); + + /// Creates a function + /// @param name the function name + /// @param return_type the function return type + /// @param stage the function stage + /// @returns the function + ir::Function* Function(std::string_view name, + const core::type::Type* return_type, + Function::PipelineStage stage = Function::PipelineStage::kUndefined); + + /// Creates a compute function + /// @param name the function name + /// @returns the function + ir::Function* ComputeFunction(std::string_view name) { + return ComputeFunction(name, u32(1), u32(1), u32(1)); + } + + /// Creates an unnamed compute function + /// @param name the function name + /// @param x the x dimension + /// @param y the y dimension + /// @param z the z dimension + template + requires(!std::is_integral_v && !std::is_integral_v && !std::is_integral_v) + ir::Function* ComputeFunction(std::string_view name, X&& x, Y&& y, Z&& z) { + CheckForNonDeterministicEvaluation(); + auto* x_val = Value(std::forward(x)); + auto* y_val = Value(std::forward(y)); + auto* z_val = Value(std::forward(z)); + + auto* ir_func = Function(name, ir.Types().void_(), Function::PipelineStage::kCompute); + ir_func->SetWorkgroupSize({x_val, y_val, z_val}); + return ir_func; + } + + /// Creates a fragment function + /// @param name the function name + /// @returns the function + ir::Function* FragmentFunction(std::string_view name, const core::type::Type* return_type) { + return Function(name, return_type, Function::PipelineStage::kFragment); + } + + /// Creates an if instruction + /// @param condition the if condition + /// @returns the instruction + template + ir::If* If(T&& condition) { + auto* cond_val = Value(std::forward(condition)); + return Append(ir.CreateInstruction(cond_val, Block(), Block())); + } + + /// Creates an const expression if instruction + /// @param condition the const expression if condition + /// @returns the instruction + template + ir::ConstExprIf* ConstExprIf(T&& condition) { + auto* cond_val = Value(std::forward(condition)); + return Append(ir.CreateInstruction(cond_val, Block(), Block())); + } + + /// Creates a loop instruction + /// @returns the instruction + ir::Loop* Loop(); + + /// Creates a switch instruction + /// @param condition the switch condition + /// @returns the instruction + template + ir::Switch* Switch(T&& condition) { + auto* cond_val = Value(std::forward(condition)); + return Append(ir.CreateInstruction(cond_val)); + } + + /// Creates a default case for the switch @p s + /// @param s the switch to create the case into + /// @returns the start block for the case instruction + ir::Block* DefaultCase(ir::Switch* s); + + /// Creates a case for the switch @p s with the given selectors + /// @param s the switch to create the case into + /// @param values the case selector values for the case statement + /// @returns the start block for the case instruction + ir::Block* Case(ir::Switch* s, VectorRef values); + + /// Creates a case for the switch @p s with the given selectors + /// @param s the switch to create the case into + /// @param values the case selector values for the case statement + /// @returns the start block for the case instruction + ir::Block* Case(ir::Switch* s, std::initializer_list values); + + /// Creates a new ir::Constant + /// @param val the constant value + /// @returns the new constant + ir::Constant* Constant(const core::constant::Value* val) { + return ir.constants.GetOrAdd(val, [&] { return ir.CreateValue(val); }); + } + + /// Creates a ir::Constant for an i32 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::i32 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for an i8 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::i8 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for a u32 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::u32 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for a u64 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::u64 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for a u8 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::u8 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for a f32 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::f32 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for a f16 Scalar + /// @param v the value + /// @returns the new constant + ir::Constant* Constant(core::f16 v) { return Constant(ConstantValue(v)); } + + /// Creates a ir::Constant for a bool Scalar + /// @param v the value + /// @returns the new constant + template + requires(std::is_same_v) + ir::Constant* Constant(BOOL v) { + return Constant(ConstantValue(v)); + } + + /// Creates a new invalid ir::Constant + /// @returns the new constant + ir::Constant* InvalidConstant() { return Constant(ir.constant_values.Invalid()); } + + /// Retrieves the inner constant from an ir::Constant + /// @param constant the ir constant + /// @returns the core::constant::Value inside the constant + const core::constant::Value* ConstantValue(ir::Constant* constant) { return constant->Value(); } + + /// Creates a core::constant::Value for an i32 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::i32 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for an i8 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::i8 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for a u32 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::u32 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for a u64 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::u64 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for a u8 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::u8 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for a f32 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::f32 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for a f16 Scalar + /// @param v the value + /// @returns the new constant + const core::constant::Value* ConstantValue(core::f16 v) { return ir.constant_values.Get(v); } + + /// Creates a core::constant::Value for a bool Scalar + /// @param v the value + /// @returns the new constant + template + requires(std::is_same_v) + const core::constant::Value* ConstantValue(BOOL v) { + return ir.constant_values.Get(v); + } + + /// Return a constant that has the same number of vector components as `match`, each with + /// the `value`. If `match` is scalar just return `value` as a constant. + /// @param value the value + /// @param match the type to match + /// @returns the new constant + template + ir::Constant* MatchWidth(ARG&& value, const core::type::Type* match) { + auto* element = Constant(std::forward(value)); + if (match->Is()) { + return Splat(ir.Types().MatchWidth(element->Type(), match), element); + } + return element; + } + + /// Creates a new ir::Constant + /// @param ty the splat type + /// @param value the splat value + /// @returns the new constant + template + ir::Constant* Splat(const core::type::Type* ty, ARG&& value) { + return Constant(ir.constant_values.Splat(ty, ConstantValue(std::forward(value)))); + } + + /// Creates a new ir::Constant + /// @tparam TYPE the splat type + /// @param value the splat value + /// @returns the new constant + template + ir::Constant* Splat(ARG&& value) { + auto* type = ir.Types().Get(); + return Splat(type, std::forward(value)); + } + + /// Creates a new ir::Constant + /// @param ty the constant type + /// @param values the composite values + /// @returns the new constant + template + requires(!tint::IsVectorLike>>) + ir::Constant* Composite(const core::type::Type* ty, ARGS&&... values) { + return Constant( + ir.constant_values.Composite(ty, Vector{ConstantValue(std::forward(values))...})); + } + + /// Creates a new ir::Constant + /// @param ty the constant type + /// @param values the composite values + /// @returns the new constant + ir::Constant* Composite(const core::type::Type* ty, + VectorRef values) { + return Constant(ir.constant_values.Composite(ty, values)); + } + + /// Creates a new ir::Constant + /// @tparam TYPE the constant type + /// @param values the composite values + /// @returns the new constant + template + requires(!tint::IsVectorLike>>) + ir::Constant* Composite(ARGS&&... values) { + auto* type = ir.Types().Get(); + return Composite(type, std::forward(values)...); + } + + /// Creates a new zero-value ir::Constant + /// @tparam TYPE the constant type + /// @returns the new constant + template + ir::Constant* Zero() { + return Constant(ir.constant_values.Zero(ir.Types().Get())); + } + + /// Creates a new zero-value ir::Constant + /// @param ty the constant type + /// @returns the new constant + ir::Constant* Zero(const core::type::Type* ty) { return Constant(ir.constant_values.Zero(ty)); } + + /// @param in the input value. One of: nullptr, ir::Value*, ir::Instruction* or a numeric + /// value. + /// @returns an ir::Value* from the given argument. + template + ir::Value* Value(T&& in) { + using D = std::decay_t; + constexpr bool is_null = std::is_same_v; + constexpr bool is_ptr = std::is_pointer_v; + constexpr bool is_numeric = core::IsNumeric; + static_assert(is_null || is_ptr || is_numeric, "invalid argument type for Value()"); + + if constexpr (is_null) { + return nullptr; + } else if constexpr (is_ptr) { + using P = std::remove_pointer_t; + constexpr bool is_value = std::is_base_of_v; + constexpr bool is_instruction = std::is_base_of_v; + static_assert(is_value || is_instruction, "invalid pointer type for Value()"); + + if constexpr (is_value) { + return in; /// Pass-through + } else if constexpr (is_instruction) { + /// Extract the first result from the instruction + auto results = in->Results(); + TINT_ASSERT(results.Length() == 1); + return results[0]; + } + } else if constexpr (is_numeric) { + /// Creates a value from the given number + return Constant(in); + } + } + + /// Pass-through overload for Values() with vector-like argument + /// @param vec the vector of ir::Value* + /// @return @p vec + template + requires( + tint::IsVectorLike, void>>>) + auto Values(VEC&& vec) { + return std::forward(vec); + } + + template + auto Values(tint::Slice&&) { + static_assert(sizeof(T) != sizeof(T), // Condition must be type-dependent + "Cannot construct a Vector from a Slice as the size is not known at " + "compile-time. Use ToVector(Slice&&) instead."); + } + + /// Overload for Values() with tint::Empty argument + /// @return tint::Empty + tint::EmptyType Values(tint::EmptyType) { return tint::Empty; } + + /// Overload for Values() with no arguments + /// @return tint::Empty + tint::EmptyType Values() { return tint::Empty; } + + /// @param args the arguments to pass to Value() + /// @returns a vector of ir::Value* built from transforming the arguments with Value() + template + requires(!tint::IsVectorLike>>) + auto Values(ARGS&&... args) { + CheckForNonDeterministicEvaluation(); + return Vector{Value(std::forward(args))...}; + } + + /// Creates an op for `lhs kind rhs` + /// @param op the binary operator + /// @param type the result type of the binary expression + /// @param lhs the left-hand-side of the operation + /// @param rhs the right-hand-side of the operation + /// @returns the operation + template + ir::CoreBinary* Binary(BinaryOp op, const core::type::Type* type, LHS&& lhs, RHS&& rhs) { + return BinaryWithResult(InstructionResult(type), op, std::forward(lhs), + std::forward(rhs)); + } + + /// Creates an op for `lhs kind rhs` + /// @param op the binary operator + /// @param result the result of the binary expression + /// @param lhs the left-hand-side of the operation + /// @param rhs the right-hand-side of the operation + /// @returns the operation + template + ir::CoreBinary* BinaryWithResult(ir::InstructionResult* result, + BinaryOp op, + LHS&& lhs, + RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_val = Value(std::forward(lhs)); + auto* rhs_val = Value(std::forward(rhs)); + return Append(ir.CreateInstruction(result, op, lhs_val, rhs_val)); + } + + /// Creates an op for `lhs kind rhs` + /// @param op the binary operator + /// @param type the result type of the binary expression + /// @param lhs the left-hand-side of the operation + /// @param rhs the right-hand-side of the operation + /// @returns the operation + template + requires(tint::traits::IsTypeOrDerived) + KLASS* Binary(BinaryOp op, const core::type::Type* type, LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_val = Value(std::forward(lhs)); + auto* rhs_val = Value(std::forward(rhs)); + return Append(ir.CreateInstruction(InstructionResult(type), op, lhs_val, rhs_val)); + } + + /// Creates an op for `lhs kind rhs` + /// @param op the binary operator + /// @param result the result of the binary expression + /// @param lhs the left-hand-side of the operation + /// @param rhs the right-hand-side of the operation + /// @returns the operation + template + requires(tint::traits::IsTypeOrDerived) + KLASS* BinaryWithResult(ir::InstructionResult* result, BinaryOp op, LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_val = Value(std::forward(lhs)); + auto* rhs_val = Value(std::forward(rhs)); + return Append(ir.CreateInstruction(result, op, lhs_val, rhs_val)); + } + + /// Creates an And operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* And(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + TINT_ASSERT(lhs_value->Type() == rhs_value->Type()); + + return Append(ir.CreateInstruction(InstructionResult(lhs_value->Type()), + BinaryOp::kAnd, lhs_value, rhs_value)); + } + + /// Creates an Or operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* Or(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + TINT_ASSERT(lhs_value->Type() == rhs_value->Type()); + + return Append(ir.CreateInstruction(InstructionResult(lhs_value->Type()), + BinaryOp::kOr, lhs_value, rhs_value)); + } + + /// Creates an Xor operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* Xor(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + TINT_ASSERT(lhs_value->Type() == rhs_value->Type()); + + return Append(ir.CreateInstruction(InstructionResult(lhs_value->Type()), + BinaryOp::kXor, lhs_value, rhs_value)); + } + + /// Creates an Equal operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* Equal(LHS&& lhs, RHS&& rhs) { + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + auto* type = ir.Types().MatchWidth(ir.Types().bool_(), lhs_value->Type()); + return Append(ir.CreateInstruction(InstructionResult(type), + BinaryOp::kEqual, lhs_value, rhs_value)); + } + + /// Creates an NotEqual operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* NotEqual(LHS&& lhs, RHS&& rhs) { + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + auto* type = ir.Types().MatchWidth(ir.Types().bool_(), lhs_value->Type()); + return Append(ir.CreateInstruction( + InstructionResult(type), BinaryOp::kNotEqual, lhs_value, rhs_value)); + } + + /// Creates an LessThan operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* LessThan(LHS&& lhs, RHS&& rhs) { + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + auto* type = ir.Types().MatchWidth(ir.Types().bool_(), lhs_value->Type()); + return Append(ir.CreateInstruction( + InstructionResult(type), BinaryOp::kLessThan, lhs_value, rhs_value)); + } + + /// Creates an LessThan operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* GreaterThan(LHS&& lhs, RHS&& rhs) { + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + auto* type = ir.Types().MatchWidth(ir.Types().bool_(), lhs_value->Type()); + return Append(ir.CreateInstruction( + InstructionResult(type), BinaryOp::kGreaterThan, lhs_value, rhs_value)); + } + + /// Creates an LessThanEqual operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* LessThanEqual(LHS&& lhs, RHS&& rhs) { + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + auto* type = ir.Types().MatchWidth(ir.Types().bool_(), lhs_value->Type()); + return Append(ir.CreateInstruction( + InstructionResult(type), BinaryOp::kLessThanEqual, lhs_value, rhs_value)); + } + + /// Creates an GreaterThanEqual operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* GreaterThanEqual(LHS&& lhs, RHS&& rhs) { + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + auto* type = ir.Types().MatchWidth(ir.Types().bool_(), lhs_value->Type()); + return Append(ir.CreateInstruction( + InstructionResult(type), BinaryOp::kGreaterThanEqual, lhs_value, rhs_value)); + } + + /// Creates an ShiftLeft operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* ShiftLeft(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + return Append(ir.CreateInstruction( + InstructionResult(lhs_value->Type()), BinaryOp::kShiftLeft, lhs_value, rhs_value)); + } + + /// Creates an ShiftRight operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* ShiftRight(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + return Append(ir.CreateInstruction( + InstructionResult(lhs_value->Type()), BinaryOp::kShiftRight, lhs_value, rhs_value)); + } + + /// Creates an Add operation + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* Add(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + auto* lhs_type = lhs_value->Type(); + auto* rhs_type = rhs_value->Type(); + + const core::type::Type* result_type = nullptr; + if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else { + result_type = lhs_type; + } + + return Append(ir.CreateInstruction(InstructionResult(result_type), + BinaryOp::kAdd, lhs_value, rhs_value)); + } + + /// Creates an Add operation + /// @param result the result + /// @param lhs the lhs of the add + /// @param rhs the rhs of the add + /// @returns the operation + template + ir::CoreBinary* AddWithResult(ir::InstructionResult* result, LHS&& lhs, RHS&& rhs) { + return BinaryWithResult(result, BinaryOp::kAdd, std::forward(lhs), + std::forward(rhs)); + } + + /// Creates a Subtract operation + /// @param lhs the lhs of the subtract + /// @param rhs the rhs of the subtract + /// @returns the operation + template + ir::CoreBinary* Subtract(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + auto* lhs_type = lhs_value->Type(); + auto* rhs_type = rhs_value->Type(); + + const core::type::Type* result_type = nullptr; + if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else { + result_type = lhs_type; + } + + return Append(ir.CreateInstruction( + InstructionResult(result_type), BinaryOp::kSubtract, lhs_value, rhs_value)); + } + + /// Creates an Multiply operation + /// @param lhs the lhs of the multiply + /// @param rhs the rhs of the multiply + /// @returns the operation + template + ir::CoreBinary* Multiply(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + auto* lhs_type = lhs_value->Type(); + auto* rhs_type = rhs_value->Type(); + + const core::type::Type* result_type = nullptr; + if (auto* l = lhs_type->template As()) { + if (auto* r = rhs_type->template As()) { + result_type = ir.Types().mat(l->DeepestElement(), r->Columns(), l->Rows()); + } else if (rhs_type->template Is()) { + result_type = ir.Types().vec(l->DeepestElement(), l->Rows()); + } else { + TINT_ASSERT(rhs_type->IsScalar()); + result_type = lhs_type; + } + } else if (lhs_type->template Is()) { + if (auto* r = rhs_type->template As()) { + result_type = ir.Types().vec(r->DeepestElement(), r->Columns()); + } else { + TINT_ASSERT(rhs_type->IsNumericScalarOrVector()); + result_type = lhs_type; + } + } else if (rhs_type->template Is() || + rhs_type->template Is()) { + result_type = rhs_type; + TINT_ASSERT(lhs_type->IsScalar()); + } else { + TINT_ASSERT(lhs_type->IsScalar()); + TINT_ASSERT(rhs_type->IsScalar()); + result_type = lhs_type; + } + + return Append(ir.CreateInstruction( + InstructionResult(result_type), BinaryOp::kMultiply, lhs_value, rhs_value)); + } + + /// Creates an Divide operation + /// @param lhs the lhs of the divide + /// @param rhs the rhs of the divide + /// @returns the operation + template + ir::CoreBinary* Divide(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + auto* lhs_type = lhs_value->Type(); + auto* rhs_type = rhs_value->Type(); + + const core::type::Type* result_type = nullptr; + if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else { + result_type = lhs_type; + } + + return Append(ir.CreateInstruction( + InstructionResult(result_type), BinaryOp::kDivide, lhs_value, rhs_value)); + } + + /// Creates an Modulo operation + /// @param lhs the lhs of the modulo + /// @param rhs the rhs of the modulo + /// @returns the operation + template + ir::CoreBinary* Modulo(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + auto* lhs_type = lhs_value->Type(); + auto* rhs_type = rhs_value->Type(); + + const core::type::Type* result_type = nullptr; + if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else if (lhs_type->template Is()) { + result_type = lhs_type; + } else if (rhs_type->template Is()) { + result_type = rhs_type; + } else { + result_type = lhs_type; + } + + return Append(ir.CreateInstruction( + InstructionResult(result_type), BinaryOp::kModulo, lhs_value, rhs_value)); + } + + /// Creates a Min operation + /// @param lhs the lhs of the min + /// @param rhs the rhs of the min + /// @returns the operation + template + ir::CoreBuiltinCall* Min(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + return Call(lhs_value->Type(), core::BuiltinFn::kMin, lhs_value, rhs_value); + } + + /// Creates a Max operation + /// @param lhs the lhs of the max + /// @param rhs the rhs of the max + /// @returns the operation + template + ir::CoreBuiltinCall* Max(LHS&& lhs, RHS&& rhs) { + CheckForNonDeterministicEvaluation(); + auto* lhs_value = Value(std::forward(lhs)); + auto* rhs_value = Value(std::forward(rhs)); + TINT_ASSERT(lhs_value); + TINT_ASSERT(rhs_value); + + return Call(lhs_value->Type(), core::BuiltinFn::kMax, lhs_value, rhs_value); + } + + /// Creates a Clamp operation + /// @param val the value to clamp + /// @param min the min value + /// @param max the max value + /// @returns the operation + template + ir::CoreBuiltinCall* Clamp(VAL&& val, MIN&& min, MAX&& max) { + CheckForNonDeterministicEvaluation(); + auto* val_value = Value(std::forward(val)); + auto* min_value = Value(std::forward(min)); + auto* max_value = Value(std::forward(max)); + TINT_ASSERT(val_value); + TINT_ASSERT(min_value); + TINT_ASSERT(max_value); + + return Call(val_value->Type(), core::BuiltinFn::kClamp, val_value, min_value, max_value); + } + + /// Creates an op for `op val` + /// @param op the unary operator + /// @param val the value of the operation + /// @returns the operation + template + ir::CoreUnary* Unary(UnaryOp op, VAL&& val) { + auto* value = Value(std::forward(val)); + + core::ir::InstructionResult* result = nullptr; + if (value) { + result = InstructionResult(value->Type()); + } + return Append(ir.CreateInstruction(result, op, value)); + } + + /// Creates a Complement operation + /// @param val the value + /// @returns the operation + template + ir::CoreUnary* Complement(VAL&& val) { + return Unary(UnaryOp::kComplement, std::forward(val)); + } + + /// Creates a Negation operation + /// @param val the value + /// @returns the operation + template + ir::CoreUnary* Negation(VAL&& val) { + return Unary(UnaryOp::kNegation, std::forward(val)); + } + + /// Creates a Not operation + /// @param val the value + /// @returns the operation + template + ir::CoreUnary* Not(VAL&& val) { + return Unary(UnaryOp::kNot, std::forward(val)); + } + + /// Creates a bitcast instruction + /// @param type the result type of the bitcast + /// @param val the value being bitcast + /// @returns the instruction + template + ir::Bitcast* Bitcast(const core::type::Type* type, VAL&& val) { + auto* value = Value(std::forward(val)); + return Append(ir.CreateInstruction(InstructionResult(type), value)); + } + + /// Creates a bitcast instruction + /// @tparam TYPE the result type of the bitcast + /// @param val the value being bitcast + /// @returns the instruction + template + ir::Bitcast* Bitcast(VAL&& val) { + auto* type = ir.Types().Get(); + auto* value = Value(std::forward(val)); + return Bitcast(type, value); + } + + /// Creates a bitcast instruction + /// @param result the result + /// @param val the value being bitcast + /// @returns the instruction + template + ir::Bitcast* BitcastWithResult(ir::InstructionResult* result, VAL&& val) { + return Append(ir.CreateInstruction(result, val)); + } + + /// Creates a discard instruction + /// @returns the instruction + ir::Discard* Discard(); + + /// Creates a user function call instruction with an existing instruction result + /// @param result the instruction result to use + /// @param func the function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::UserCall* CallWithResult(ir::InstructionResult* result, + ir::Function* func, + ARGS&&... args) { + return Append( + ir.CreateInstruction(result, func, Values(std::forward(args)...))); + } + + /// Creates a user function call instruction + /// @param func the function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::UserCall* Call(ir::Function* func, ARGS&&... args) { + return Call(func->ReturnType(), func, std::forward(args)...); + } + + /// Creates a user function call instruction + /// @param type the return type of the call + /// @param func the function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::UserCall* Call(const core::type::Type* type, ir::Function* func, ARGS&&... args) { + return CallWithResult(InstructionResult(type), func, Values(std::forward(args)...)); + } + + /// Creates a user function call instruction + /// @tparam TYPE the return type of the call + /// @param func the function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::UserCall* Call(ir::Function* func, ARGS&&... args) { + auto* type = ir.Types().Get(); + return CallWithResult(InstructionResult(type), func, Values(std::forward(args)...)); + } + + /// Creates a core builtin call instruction with an existing instruction result + /// @param result the instruction result to use + /// @param func the builtin function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::CoreBuiltinCall* CallWithResult(core::ir::InstructionResult* result, + core::BuiltinFn func, + ARGS&&... args) { + return Append(ir.CreateInstruction( + result, func, Values(std::forward(args)...))); + } + + /// Creates a core builtin call instruction + /// @param type the return type of the call + /// @param func the builtin function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::CoreBuiltinCall* Call(const core::type::Type* type, core::BuiltinFn func, ARGS&&... args) { + return CallWithResult(InstructionResult(type), func, Values(std::forward(args)...)); + } + + /// Creates a core builtin call instruction + /// @tparam TYPE the return type of the call + /// @param func the builtin function to call + /// @param args the call arguments + /// @returns the instruction + template + ir::CoreBuiltinCall* Call(core::BuiltinFn func, ARGS&&... args) { + auto* type = ir.Types().Get(); + return CallWithResult(InstructionResult(type), func, Values(std::forward(args)...)); + } + + /// Creates a builtin call instruction with an existing instruction result + /// @param result the instruction result to use + /// @param func the builtin function to call + /// @param explicit_params the explicit params + /// @param args the call arguments + /// @returns the instruction + template + requires(tint::traits::IsTypeOrDerived) + KLASS* CallExplicitWithResult(ir::InstructionResult* result, + FUNC func, + VectorRef explicit_params, + ARGS&&... args) { + auto* inst = ir.CreateInstruction(result, func, Values(std::forward(args)...)); + inst->SetExplicitTemplateParams(explicit_params); + return Append(inst); + } + + /// Creates a builtin call instruction with an existing instruction result + /// @param result the instruction result to use + /// @param func the builtin function to call + /// @param args the call arguments + /// @returns the instruction + template + requires(tint::traits::IsTypeOrDerived) + KLASS* CallWithResult(ir::InstructionResult* result, FUNC func, ARGS&&... args) { + return Append( + ir.CreateInstruction(result, func, Values(std::forward(args)...))); + } + + /// Creates a builtin call instruction + /// @param type the return type of the call + /// @param func the builtin function to call + /// @param explicit_params the explicit parameters + /// @param args the call arguments + /// @returns the instruction + template + requires(tint::traits::IsTypeOrDerived) + KLASS* CallExplicit(const core::type::Type* type, + FUNC func, + VectorRef explicit_params, + ARGS&&... args) { + return CallExplicitWithResult(InstructionResult(type), func, explicit_params, + Values(std::forward(args)...)); + } + + /// Creates a core builtin call instruction with explicit parameters + /// @param type the return type of the call + /// @param func the builtin function to call + /// @param explicit_params the explicit parameters + /// @param args the call arguments + /// @returns the instruction + template + ir::CoreBuiltinCall* CallExplicit(const core::type::Type* type, + core::BuiltinFn func, + VectorRef explicit_params, + ARGS&&... args) { + return CallExplicitWithResult( + InstructionResult(type), func, explicit_params, Values(std::forward(args)...)); + } + + /// Creates a builtin call instruction + /// @param type the return type of the call + /// @param func the builtin function to call + /// @param args the call arguments + /// @returns the instruction + template + requires(tint::traits::IsTypeOrDerived) + KLASS* Call(const core::type::Type* type, FUNC func, ARGS&&... args) { + return CallWithResult(InstructionResult(type), func, + Values(std::forward(args)...)); + } + + /// Creates a member builtin call instruction with an existing instruction result. + /// @param result the instruction result to use + /// @param func the builtin function to call + /// @param obj the object + /// @param args the call arguments + /// @returns the instruction + template + requires(tint::traits::IsTypeOrDerived) + KLASS* MemberCallWithResult(ir::InstructionResult* result, + FUNC func, + OBJ&& obj, + ARGS&&... args) { + return Append(ir.CreateInstruction(result, func, Value(std::forward(obj)), + Values(std::forward(args)...))); + } + + /// Creates a member builtin call instruction. + /// @param type the return type of the call + /// @param func the builtin function to call + /// @param obj the object + /// @param args the call arguments + /// @returns the instruction + template + requires(tint::traits::IsTypeOrDerived) + KLASS* MemberCall(const core::type::Type* type, FUNC func, OBJ&& obj, ARGS&&... args) { + return MemberCallWithResult(InstructionResult(type), func, + Value(std::forward(obj)), + Values(std::forward(args)...)); + } + + /// Creates a value conversion instruction with an existing instruction result. + /// @param result the instruction result to use + /// @param val the value to be converted + /// @returns the instruction + template + ir::Convert* ConvertWithResult(ir::InstructionResult* result, VAL&& val) { + return Append(ir.CreateInstruction(result, Value(std::forward(val)))); + } + + /// Creates a value conversion instruction to the template type T + /// @param val the value to be converted + /// @returns the instruction + template + ir::Convert* Convert(VAL&& val) { + auto* type = ir.Types().Get(); + return Convert(type, std::forward(val)); + } + + /// Creates a value conversion instruction + /// @param to the type converted to + /// @param val the value to be converted + /// @returns the instruction + template + ir::Convert* Convert(const core::type::Type* to, VAL&& val) { + return ConvertWithResult(InstructionResult(to), Value(std::forward(val))); + } + + /// Adds a call to convert if destination type is different then the value's type + /// @param to the type converted to + /// @param val the value to be converted + /// @returns either result of the conversion or original value + ir::Value* InsertConvertIfNeeded(const core::type::Type* to, ir::Value* val) { + return val->Type()->Equals(*to) ? val : Convert(to, val)->Result(); + } + + /// Creates a value constructor instruction with an existing instruction result + /// @param result the instruction result to use + /// @param args the arguments to the constructor + /// @returns the instruction + template + ir::Construct* ConstructWithResult(ir::InstructionResult* result, ARGS&&... args) { + return Append( + ir.CreateInstruction(result, Values(std::forward(args)...))); + } + + /// Creates a value constructor instruction to the template type T + /// @param args the arguments to the constructor + /// @returns the instruction + template + ir::Construct* Construct(ARGS&&... args) { + auto* type = ir.Types().Get(); + return Construct(type, std::forward(args)...); + } + + /// Creates a value constructor instruction + /// @param type the type to constructed + /// @param args the arguments to the constructor + /// @returns the instruction + template + ir::Construct* Construct(const core::type::Type* type, ARGS&&... args) { + return ConstructWithResult(InstructionResult(type), Values(std::forward(args)...)); + } + + /// Creates a load instruction with an existing result + /// @param result the instruction result to use + /// @param from the expression being loaded from + /// @returns the instruction + template + ir::Load* LoadWithResult(ir::InstructionResult* result, VAL&& from) { + auto* value = Value(std::forward(from)); + return Append(ir.CreateInstruction(result, value)); + } + + /// Creates a load instruction + /// @param from the expression being loaded from + /// @returns the instruction + template + ir::Load* Load(VAL&& from) { + auto* value = Value(std::forward(from)); + return LoadWithResult(InstructionResult(value->Type()->UnwrapPtrOrRef()), value); + } + + /// Creates a store instruction + /// @param to the expression being stored too + /// @param from the expression being stored + /// @returns the instruction + template + ir::Store* Store(TO&& to, FROM&& from) { + CheckForNonDeterministicEvaluation(); + auto* to_val = Value(std::forward(to)); + auto* from_val = Value(std::forward(from)); + return Append(ir.CreateInstruction(to_val, from_val)); + } + + /// Creates a store vector element instruction + /// @param to the vector pointer expression being stored too + /// @param index the new vector element index + /// @param value the new vector element expression + /// @returns the instruction + template + ir::StoreVectorElement* StoreVectorElement(TO&& to, INDEX&& index, VALUE&& value) { + CheckForNonDeterministicEvaluation(); + auto* to_val = Value(std::forward(to)); + auto* index_val = Value(std::forward(index)); + auto* value_val = Value(std::forward(value)); + return Append(ir.CreateInstruction(to_val, index_val, value_val)); + } + + /// Creates a load vector element instruction with an existing instruction result + /// @param result the instruction result to use + /// @param from the vector pointer expression being loaded from + /// @param index the new vector element index + /// @returns the instruction + template + ir::LoadVectorElement* LoadVectorElementWithResult(ir::InstructionResult* result, + FROM&& from, + INDEX&& index) { + CheckForNonDeterministicEvaluation(); + auto* from_val = Value(std::forward(from)); + auto* index_val = Value(std::forward(index)); + return Append(ir.CreateInstruction(result, from_val, index_val)); + } + + /// Creates a load vector element instruction + /// @param from the vector pointer expression being loaded from + /// @param index the new vector element index + /// @returns the instruction + template + ir::LoadVectorElement* LoadVectorElement(FROM&& from, INDEX&& index) { + CheckForNonDeterministicEvaluation(); + auto* from_val = Value(std::forward(from)); + auto* index_val = Value(std::forward(index)); + auto* res = InstructionResult(VectorPtrElementType(from_val->Type())); + return LoadVectorElementWithResult(res, from_val, index_val); + } + + /// Creates a new `var` declaration + /// @param type the var type + /// @returns the instruction + ir::Var* Var(const core::type::MemoryView* type); + + /// Creates a new `var` declaration with a name + /// @param name the var name + /// @param type the var type + /// @returns the instruction + ir::Var* Var(std::string_view name, const core::type::MemoryView* type); + + /// Creates a new `var` declaration with a name and initializer value + /// @tparam SPACE the var's address space + /// @tparam ACCESS the var's access mode + /// @param name the var name + /// @param init the var initializer + /// @returns the instruction + template + requires( + !traits::IsTypeOrDerived>, core::type::Type>) + ir::Var* Var(std::string_view name, VALUE&& init) { + auto* val = Value(std::forward(init)); + if (DAWN_UNLIKELY(!val)) { + TINT_ASSERT(val); + return nullptr; + } + auto* var = Var(name, ir.Types().ptr(SPACE, val->Type(), ACCESS)); + var->SetInitializer(val); + ir.SetName(var->Result(), name); + return var; + } + + /// Creates a new `var` declaration + /// @tparam SPACE the var's address space + /// @tparam T the storage pointer's element type + /// @tparam ACCESS the var's access mode + /// @returns the instruction + template + ir::Var* Var() { + return Var(ir.Types().ptr()); + } + + /// Creates a new `var` declaration with a name + /// @tparam SPACE the var's address space + /// @tparam T the storage pointer's element type + /// @tparam ACCESS the var's access mode + /// @param name the var name + /// @returns the instruction + template + ir::Var* Var(std::string_view name) { + return Var(name, ir.Types().ptr()); + } + + /// Creates a new `var` declaration with a name + /// @param name the var name + /// @param space the var's address space + /// @param subtype the storage pointer's element type + /// @param access the var's access mode + /// @returns the instruction + ir::Var* Var(std::string_view name, + core::AddressSpace space, + const core::type::Type* subtype, + core::Access access = core::Access::kUndefined) { + return Var(name, ir.Types().ptr(space, subtype, access)); + } + + /// Creates a new `let` declaration + /// @param name the let name + /// @param value the let value + /// @returns the instruction + template + ir::Let* Let(std::string_view name, VALUE&& value) { + auto* val = Value(std::forward(value)); + if (DAWN_UNLIKELY(!val)) { + TINT_ASSERT(val); + return nullptr; + } + auto* let = Append(ir.CreateInstruction(InstructionResult(val->Type()), val)); + ir.SetName(let->Result(), name); + return let; + } + + /// Creates a new `let` declaration, with an unassigned value + /// @param type the let type + /// @returns the instruction + ir::Let* Let(const core::type::Type* type) { + auto* let = ir.CreateInstruction(InstructionResult(type), nullptr); + Append(let); + return let; + } + + /// Creates a new `let` declaration + /// @param value the value + /// @returns the instruction + template + requires( + !traits::IsTypeOrDerived>, core::type::Type>) + ir::Let* Let(VALUE&& value) { + auto* val = Value(std::forward(value)); + if (DAWN_UNLIKELY(!val)) { + TINT_ASSERT(val); + return nullptr; + } + auto* let = ir.CreateInstruction(InstructionResult(val->Type()), val); + Append(let); + return let; + } + + /// Creates a return instruction + /// @param func the function being returned + /// @returns the instruction + ir::Return* Return(ir::Function* func) { + return Append(ir.CreateInstruction(func)); + } + + /// Creates a return instruction + /// @param func the function being returned + /// @param value the return value + /// @returns the instruction + template + ir::Return* Return(ir::Function* func, ARG&& value) { + if constexpr (std::is_same_v, ir::Value*>) { + if (value == nullptr) { + return Append(ir.CreateInstruction(func)); + } + } + auto* val = Value(std::forward(value)); + return Append(ir.CreateInstruction(func, val)); + } + + /// Creates a loop next iteration instruction + /// @param loop the loop being iterated + /// @param args the arguments for the target MultiInBlock + /// @returns the instruction + template + ir::NextIteration* NextIteration(ir::Loop* loop, ARGS&&... args) { + return Append( + ir.CreateInstruction(loop, Values(std::forward(args)...))); + } + + /// Creates a loop break-if instruction + /// @param condition the break condition + /// @param loop the loop being iterated + /// @returns the instruction + template + ir::BreakIf* BreakIf(ir::Loop* loop, CONDITION&& condition) { + CheckForNonDeterministicEvaluation(); + auto* cond_val = Value(std::forward(condition)); + return Append(ir.CreateInstruction(cond_val, loop)); + } + + /// Creates a loop break-if instruction + /// @param condition the break condition + /// @param loop the loop being iterated + /// @param next_iter_values the arguments passed to the loop body MultiInBlock, if the break + /// condition evaluates to `false`. + /// @param exit_values the values returned by the loop, if the break condition evaluates to + /// `true`. + /// @returns the instruction + template + ir::BreakIf* BreakIf(ir::Loop* loop, + CONDITION&& condition, + NEXT_ITER_VALUES&& next_iter_values, + EXIT_VALUES&& exit_values) { + CheckForNonDeterministicEvaluation(); + auto* cond_val = Value(std::forward(condition)); + return Append(ir.CreateInstruction( + cond_val, loop, Values(std::forward(next_iter_values)), + Values(std::forward(exit_values)))); + } + + /// Creates a continue instruction + /// @param loop the loop being continued + /// @param args the arguments for the target MultiInBlock + /// @returns the instruction + template + ir::Continue* Continue(ir::Loop* loop, ARGS&&... args) { + return Append( + ir.CreateInstruction(loop, Values(std::forward(args)...))); + } + + /// Creates an exit switch instruction + /// @param sw the switch being exited + /// @param args the arguments for the target MultiInBlock + /// @returns the instruction + template + ir::ExitSwitch* ExitSwitch(ir::Switch* sw, ARGS&&... args) { + return Append( + ir.CreateInstruction(sw, Values(std::forward(args)...))); + } + + /// Creates an exit loop instruction + /// @param loop the loop being exited + /// @param args the arguments for the target MultiInBlock + /// @returns the instruction + template + ir::ExitLoop* ExitLoop(ir::Loop* loop, ARGS&&... args) { + return Append( + ir.CreateInstruction(loop, Values(std::forward(args)...))); + } + + /// Creates an exit if instruction + /// @param i the if being exited + /// @param args the arguments for the target MultiInBlock + /// @returns the instruction + template + ir::ExitIf* ExitIf(ir::If* i, ARGS&&... args) { + return Append(ir.CreateInstruction(i, Values(std::forward(args)...))); + } + + /// Creates an exit instruction for the given control instruction + /// @param inst the control instruction being exited + /// @param args the arguments for the target MultiInBlock + /// @returns the exit instruction, or nullptr if the control instruction is not supported. + template + ir::Exit* Exit(ir::ControlInstruction* inst, ARGS&&... args) { + return tint::Switch( + inst, // + [&](ir::If* i) { return ExitIf(i, std::forward(args)...); }, + [&](ir::Loop* i) { return ExitLoop(i, std::forward(args)...); }, + [&](ir::Switch* i) { return ExitSwitch(i, std::forward(args)...); }); + } + + /// Creates a new `BlockParam` + /// @param type the parameter type + /// @returns the value + ir::BlockParam* BlockParam(const core::type::Type* type); + + /// Creates a new `BlockParam` with a name. + /// @param name the parameter name + /// @param type the parameter type + /// @returns the value + ir::BlockParam* BlockParam(std::string_view name, const core::type::Type* type); + + /// Creates a new `BlockParam` with a name. + /// @tparam TYPE the parameter type + /// @param name the parameter name + /// @returns the value + template + ir::BlockParam* BlockParam(std::string_view name) { + auto* type = ir.Types().Get(); + return BlockParam(name, type); + } + + /// Creates a new `BlockParam` + /// @tparam TYPE the parameter type + /// @returns the value + template + ir::BlockParam* BlockParam() { + auto* type = ir.Types().Get(); + return BlockParam(type); + } + + /// Creates a new `FunctionParam` + /// @param type the parameter type + /// @returns the value + ir::FunctionParam* FunctionParam(const core::type::Type* type); + + /// Creates a new `FunctionParam` with a name. + /// @param name the parameter name + /// @param type the parameter type + /// @returns the value + ir::FunctionParam* FunctionParam(std::string_view name, const core::type::Type* type); + + /// Creates a new `FunctionParam` with a name. + /// @tparam TYPE the parameter type + /// @param name the parameter name + /// @returns the value + template + ir::FunctionParam* FunctionParam(std::string_view name) { + auto* type = ir.Types().Get(); + return FunctionParam(name, type); + } + + /// Creates a new `FunctionParam` + /// @tparam TYPE the parameter type + /// @returns the value + template + ir::FunctionParam* FunctionParam() { + auto* type = ir.Types().Get(); + return FunctionParam(type); + } + + /// Creates a new `Access` with an existing instruction result + /// @param result the instruction result to use + /// @param object the object being accessed + /// @param indices the access indices + /// @returns the instruction + template + ir::Access* AccessWithResult(ir::InstructionResult* result, OBJ&& object, ARGS&&... indices) { + CheckForNonDeterministicEvaluation(); + auto* obj_val = Value(std::forward(object)); + return Append(ir.CreateInstruction(result, obj_val, + Values(std::forward(indices)...))); + } + + /// Creates a new `Access` + /// @param type the return type + /// @param object the object being accessed + /// @param indices the access indices + /// @returns the instruction + template + ir::Access* Access(const core::type::Type* type, OBJ&& object, ARGS&&... indices) { + return AccessWithResult(InstructionResult(type), std::forward(object), + Values(std::forward(indices)...)); + } + + /// Creates a new `Access` + /// @tparam TYPE the return type + /// @param object the object being accessed + /// @param indices the access indices + /// @returns the instruction + template + ir::Access* Access(OBJ&& object, ARGS&&... indices) { + auto* type = ir.Types().Get(); + return Access(type, std::forward(object), std::forward(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 + ir::Swizzle* Swizzle(const core::type::Type* type, OBJ&& object, VectorRef indices) { + auto* obj_val = Value(std::forward(object)); + return Append(ir.CreateInstruction(InstructionResult(type), obj_val, + std::move(indices))); + } + + /// Creates a new `Swizzle` + /// @tparam TYPE the return type + /// @param object the object being swizzled + /// @param indices the swizzle indices + /// @returns the instruction + template + ir::Swizzle* Swizzle(OBJ&& object, VectorRef indices) { + auto* type = ir.Types().Get(); + return Swizzle(type, std::forward(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 + ir::Swizzle* Swizzle(const core::type::Type* type, + OBJ&& object, + std::initializer_list indices) { + auto* obj_val = Value(std::forward(object)); + return Append(ir.CreateInstruction(InstructionResult(type), obj_val, + Vector(indices))); + } + + /// Name names the value or instruction with @p name + /// @param name the new name for the value or instruction + /// @param object the value or instruction + /// @return @p object + template + OBJECT* Name(std::string_view name, OBJECT* object) { + ir.SetName(object, name); + return object; + } + + /// Creates a terminate invocation instruction + /// @returns the instruction + ir::TerminateInvocation* TerminateInvocation(); + + /// Creates an unreachable instruction + /// @returns the instruction + ir::Unreachable* Unreachable(); + + /// Creates an unused instruction + /// @returns the instruction + ir::Unused* Unused(); + + /// Creates a new phony assignment declaration + /// @param value the assignment value + /// @returns the instruction + template + ir::Phony* Phony(VALUE&& value) { + auto* val = Value(std::forward(value)); + if (DAWN_UNLIKELY(!val)) { + TINT_ASSERT(val); + return nullptr; + } + return Append(ir.CreateInstruction(val)); + } + + /// Creates a new runtime value + /// @param type the return type + /// @returns the value + ir::InstructionResult* InstructionResult(const core::type::Type* type) { + return ir.CreateValue(type); + } + + /// Creates a new runtime value + /// @tparam TYPE the return type + /// @returns the value + template + ir::InstructionResult* InstructionResult() { + auto* type = ir.Types().Get(); + return InstructionResult(type); + } + + /// Create a ranged loop with a callback to build the loop body. + /// @param start the first loop index + /// @param end one past the last loop index + /// @param step the loop index step amount + /// @param cb the callback to call for the loop body + template + void LoopRange(START&& start, END&& end, STEP&& step, FUNCTION&& cb) { + auto* start_value = Value(std::forward(start)); + auto* end_value = Value(std::forward(end)); + auto* step_value = Value(std::forward(step)); + + auto* loop = Loop(); + auto* idx = BlockParam("idx", start_value->Type()); + loop->Body()->SetParams({idx}); + Append(loop->Initializer(), [&] { + // Start the loop with `idx = start`. + NextIteration(loop, start_value); + }); + Append(loop->Body(), [&] { + // Loop until `idx == end`. + auto* breakif = If(GreaterThanEqual(idx, end_value)); + Append(breakif->True(), [&] { // + ExitLoop(loop); + }); + + cb(idx); + + Continue(loop); + }); + Append(loop->Continuing(), [&] { + // Update the index with `idx += step` and go to the next iteration. + auto* new_idx = Add(idx, step_value); + NextIteration(loop, new_idx); + }); + } + + /// Creates a new `override` declaration + /// @param name the override name + /// @param value the override value + /// @returns the instruction + template + requires( + !traits::IsTypeOrDerived>, core::type::Type>) + ir::Override* Override(std::string_view name, VALUE&& value) { + auto* val = Value(std::forward(value)); + if (DAWN_UNLIKELY(!val)) { + TINT_ASSERT(val); + return nullptr; + } + auto* override = Append(ir.CreateInstruction(InstructionResult(val->Type()))); + override->SetInitializer(val); + ir.SetName(override->Result(), name); + return override; + } + + /// Creates a new `override` declaration + /// @param src the source + /// @param name the override name + /// @param value the override value + /// @returns the instruction + template + requires( + !traits::IsTypeOrDerived>, core::type::Type>) + ir::Override* Override(Source src, std::string_view name, VALUE&& value) { + auto* val = Value(std::forward(value)); + if (DAWN_UNLIKELY(!val)) { + TINT_ASSERT(val); + return nullptr; + } + auto* override = Append(ir.CreateInstruction(InstructionResult(val->Type()))); + override->SetInitializer(val); + ir.SetName(override->Result(), name); + ir.SetSource(override, src); + return override; + } + + /// Creates a new `override` declaration, with an unassigned value + /// @param name the override name + /// @param type the override type + /// @returns the instruction + ir::Override* Override(std::string_view name, const core::type::Type* type) { + return Override(Source{}, name, type); + } + + /// Creates a new `override` declaration, with an unassigned value + /// @param name the override name + /// @param type the override type + /// @returns the instruction + ir::Override* Override(Source src, std::string_view name, const core::type::Type* type) { + auto* override = ir.CreateInstruction(InstructionResult(type)); + ir.SetName(override->Result(), name); + ir.SetSource(override, src); + Append(override); + return override; + } + + /// Creates a new `override` declaration, with an unassigned value + /// @param type the override type + /// @returns the instruction + ir::Override* Override(const core::type::Type* type) { + auto* override = ir.CreateInstruction(InstructionResult(type)); + Append(override); + return override; + } + + /// The IR module. + Module& ir; + + private: + /// @returns the element type of the vector-pointer type + /// Asserts and return i32 if @p type is not a pointer to a vector + const core::type::Type* VectorPtrElementType(const core::type::Type* type); +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BUILDER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/builtin_call.cc b/3rdparty/dawn/src/tint/lang/core/ir/builtin_call.cc new file mode 100644 index 000000000..92e0d172d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/builtin_call.cc @@ -0,0 +1,48 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/builtin_call.h" + +#include + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::BuiltinCall); + +namespace tint::core::ir { + +BuiltinCall::BuiltinCall(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +BuiltinCall::BuiltinCall(Id id, InstructionResult* result, VectorRef arguments) : Base(id) { + flags_.Add(Flag::kSequenced); + AddOperands(BuiltinCall::kArgsOperandOffset, std::move(arguments)); + AddResult(result); +} + +BuiltinCall::~BuiltinCall() = default; + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/builtin_call.h b/3rdparty/dawn/src/tint/lang/core/ir/builtin_call.h new file mode 100644 index 000000000..ddd3d1d2a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/builtin_call.h @@ -0,0 +1,67 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_BUILTIN_CALL_H_ +#define SRC_TINT_LANG_CORE_IR_BUILTIN_CALL_H_ + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// The base class for builtin call instructions in the IR. +class BuiltinCall : public Castable { + public: + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit BuiltinCall(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param args the conversion arguments + BuiltinCall(Id id, InstructionResult* result, VectorRef args = tint::Empty); + + ~BuiltinCall() override; + + /// @returns the identifier for the function + virtual size_t FuncId() const = 0; + + /// @returns the table data to validate this builtin + virtual const core::intrinsic::TableData& TableData() const = 0; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_BUILTIN_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/call.cc b/3rdparty/dawn/src/tint/lang/core/ir/call.cc new file mode 100644 index 000000000..0b6cf8849 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/call.cc @@ -0,0 +1,38 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/call.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Call); + +namespace tint::core::ir { + +Call::Call(Id id) : Base(id) {} + +Call::~Call() = default; + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/call.h b/3rdparty/dawn/src/tint/lang/core/ir/call.h new file mode 100644 index 000000000..a501f5236 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/call.h @@ -0,0 +1,84 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CALL_H_ +#define SRC_TINT_LANG_CORE_IR_CALL_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A Call instruction in the IR. +class Call : public Castable> { + public: + ~Call() override; + + /// @returns the offset of the arguments in Operands() + virtual size_t ArgsOperandOffset() const { return 0; } + + /// Sets the explicit template params for the call + void SetExplicitTemplateParams(VectorRef params) { + explicit_template_params_ = params; + } + /// Retrieves the explicit template params for the call + tint::VectorRef ExplicitTemplateParams() const { + return explicit_template_params_; + } + + /// @returns the call arguments + tint::Slice Args() { return operands_.Slice().Offset(ArgsOperandOffset()); } + + /// @returns the call arguments + tint::Slice Args() const { + return operands_.Slice().Offset(ArgsOperandOffset()); + } + + /// Sets the argument at `idx` of `arg`. `idx` must be within bounds of the current argument + /// set. + void SetArg(size_t idx, ir::Value* arg) { SetOperand(ArgsOperandOffset() + idx, arg); } + + /// Append a new argument to the argument list for this call instruction. + /// @param arg the argument value to append + void AppendArg(ir::Value* arg) { AddOperand(operands_.Length(), arg); } + + /// @returns the side effects for this instruction + Accesses GetSideEffects() const override { return Accesses{Access::kLoad, Access::kStore}; } + + protected: + /// Constructor + explicit Call(Id id); + + Vector explicit_template_params_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/clone_context.cc b/3rdparty/dawn/src/tint/lang/core/ir/clone_context.cc new file mode 100644 index 000000000..ccd8a6fef --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/clone_context.cc @@ -0,0 +1,37 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/clone_context.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/let.h" + +namespace tint::core::ir { + +CloneContext::CloneContext(Module& module) : ir(module) {} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/clone_context.h b/3rdparty/dawn/src/tint/lang/core/ir/clone_context.h new file mode 100644 index 000000000..ea49f6ac3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/clone_context.h @@ -0,0 +1,143 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CLONE_CONTEXT_H_ +#define SRC_TINT_LANG_CORE_IR_CLONE_CONTEXT_H_ + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint::core::ir { +class Block; +class Instruction; +class Module; +class Value; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// Constant in the IR. +class CloneContext { + public: + /// @param module the IR module + explicit CloneContext(Module& module); + + /// The IR module + Module& ir; + + /// Performs a clone of @p what. + /// @param what the item to clone + /// @return the cloned item + template + T* Clone(T* what) { + if (auto replacement = replacements_.Get(what)) { + return (*replacement)->template As(); + } + T* result = what->Clone(*this); + Replace(what, result); + return result; + } + + /// Performs a clone of all the elements in @p what. + /// @param what the elements to clone + /// @return the cloned elements + template + Vector Clone(Slice what) { + return Transform(what, [&](T* const p) { return Clone(p); }); + } + + /// Performs a clone of all the elements in @p what. + /// @param what the elements to clone + /// @return the cloned elements + template + Vector Clone(Slice what) { + return Transform(what, [&](T* p) { return Clone(p); }); + } + + /// Performs a clone of all the elements in @p what. + /// @param what the elements to clone + /// @return the cloned elements + template + Vector Clone(Vector what) { + return Transform(what, [&](T* p) { return Clone(p); }); + } + + /// Obtains the (potentially) remapped pointer to @p what + /// @param what the item + /// @return the cloned item for @p what, or the original pointer if @p what has not been cloned. + template + T* Remap(T* what) { + if (auto replacement = replacements_.Get(what)) { + return (*replacement)->template As(); + } + return what; + } + + /// Obtains the (potentially) remapped pointer of all the elements in @p what. + /// @param what the item + /// @return the remapped elements + template + Vector Remap(Slice what) { + return Transform(what, [&](T* const p) { return Remap(p); }); + } + + /// Obtains the (potentially) remapped pointer of all the elements in @p what. + /// @param what the item + /// @return the remapped elements + template + Vector Remap(Slice what) { + return Transform(what, [&](T* p) { return Remap(p); }); + } + + /// Obtains the (potentially) remapped pointer of all the elements in @p what. + /// @param what the item + /// @return the remapped elements + template + Vector Remap(Vector what) { + return Transform(what, [&](T* p) { return Remap(p); }); + } + + /// Registers the replacement of `what` with `with` + /// @param what the value or instruction to replace + /// @param with a pointer to a replacement value or instruction + template + void Replace(WHAT* what, WITH* with) { + static_assert(traits::IsTypeOrDerived || + traits::IsTypeOrDerived); + static_assert(traits::IsTypeOrDerived); + TINT_ASSERT(with); + replacements_.Add(what, with); + } + + private: + Hashmap replacements_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CLONE_CONTEXT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.cc b/3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.cc new file mode 100644 index 000000000..b71f9a74f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.cc @@ -0,0 +1,318 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/const_param_validator.h" + +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/intrinsic/table.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/core_binary.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/type/array_count.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/internal_limits.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir { + +namespace { + +/// The core IR const param validator. +class ConstParamValidator { + public: + /// Create a core const param validator + /// @param mod the module to be validated + explicit ConstParamValidator(Module& mod); + + /// Destructor + ~ConstParamValidator(); + + /// Runs the const param validator over the module provided during construction + /// @returns success or failure + Result Run(); + + void CheckSubgroupCall(const CoreBuiltinCall* call); + void CheckBuiltinCall(const BuiltinCall* call); + void CheckCoreBinaryCall(const CoreBinary* inst); + void CheckExtractBitsCall(const CoreBuiltinCall* call); + void CheckInsertBitsCall(const CoreBuiltinCall* call); + void CheckLdexpCall(const CoreBuiltinCall* call); + void CheckQuantizeToF16(const CoreBuiltinCall* call); + void CheckClampCall(const CoreBuiltinCall* call); + void CheckPack2x16float(const CoreBuiltinCall* call); + void CheckSmoothstepCall(const CoreBuiltinCall* call); + void CheckBinaryDivModCall(const CoreBinary* call); + void CheckBinaryShiftCall(const CoreBinary* call); + + diag::Diagnostic& AddError(const Instruction& inst); + + private: + Module& mod_; + constant::Eval const_eval_; + diag::List diagnostics_; +}; + +ConstParamValidator::ConstParamValidator(Module& mod) + : mod_(mod), const_eval_(mod.constant_values, diagnostics_) {} + +ConstParamValidator::~ConstParamValidator() = default; + +diag::Diagnostic& ConstParamValidator::AddError(const Instruction& inst) { + auto src = mod_.SourceOf(&inst); + return diagnostics_.AddError(src); +} + +const constant::Value* GetConstArg(const CoreBuiltinCall* call, uint32_t param_index) { + if (call->Args().Length() <= param_index) { + return nullptr; + } + if (call->Args()[param_index] == nullptr) { + return nullptr; + } + if (!call->Args()[param_index]->Is()) { + return nullptr; + } + return call->Args()[param_index]->As()->Value(); +} + +void ConstParamValidator::CheckExtractBitsCall(const CoreBuiltinCall* call) { + // This can be u32/i32 or vector of those types. + auto* param0 = call->Args()[0]; + auto* const_val_offset = GetConstArg(call, 1); + auto* const_val_count = GetConstArg(call, 2); + if (const_val_count && const_val_offset) { + auto* zero = const_eval_.Zero(param0->Type(), {}, Source{}).Get(); + auto fakeArgs = Vector{zero, const_val_offset, const_val_count}; + [[maybe_unused]] auto result = + const_eval_.extractBits(param0->Type(), fakeArgs, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckInsertBitsCall(const CoreBuiltinCall* call) { + // This can be u32/i32 or vector of those types. + auto* param0 = call->Args()[0]; + auto* const_val_offset = GetConstArg(call, 2); + auto* const_val_count = GetConstArg(call, 3); + if (const_val_count && const_val_offset) { + auto* zero = const_eval_.Zero(param0->Type(), {}, Source{}).Get(); + auto fakeArgs = Vector{zero, zero, const_val_offset, const_val_count}; + [[maybe_unused]] auto result = + const_eval_.insertBits(param0->Type(), fakeArgs, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckLdexpCall(const CoreBuiltinCall* call) { + auto* param0 = call->Args()[0]; + if (auto const_val = GetConstArg(call, 1)) { + auto* zero = const_eval_.Zero(param0->Type(), {}, Source{}).Get(); + auto fakeArgs = Vector{zero, const_val}; + [[maybe_unused]] auto result = + const_eval_.ldexp(param0->Type(), fakeArgs, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckQuantizeToF16(const CoreBuiltinCall* call) { + if (auto const_val = GetConstArg(call, 0)) { + [[maybe_unused]] auto result = const_eval_.quantizeToF16( + call->Result()->Type(), Vector{const_val}, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckPack2x16float(const CoreBuiltinCall* call) { + if (auto const_val = GetConstArg(call, 0)) { + [[maybe_unused]] auto result = const_eval_.pack2x16float( + call->Result()->Type(), Vector{const_val}, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckSubgroupCall(const CoreBuiltinCall* call) { + if (auto const_val = GetConstArg(call, 1)) { + auto as_aint = const_val->ValueAs(); + // User friendly param name. + std::string paramName = "sourceLaneIndex"; + switch (call->Func()) { + case core::BuiltinFn::kSubgroupShuffleXor: + paramName = "mask"; + break; + case core::BuiltinFn::kSubgroupShuffleUp: + case core::BuiltinFn::kSubgroupShuffleDown: + paramName = "delta"; + break; + default: + break; + } + + if (as_aint >= tint::internal_limits::kMaxSubgroupSize) { + AddError(*call) << "The " << paramName << " argument of " << call->FriendlyName() + << " must be less than " << tint::internal_limits::kMaxSubgroupSize; + } else if (as_aint < 0) { + AddError(*call) << "The " << paramName << " argument of " << call->FriendlyName() + << " must be greater than or equal to zero"; + } + } +} + +void ConstParamValidator::CheckClampCall(const CoreBuiltinCall* call) { + auto* const_val_low = GetConstArg(call, 1); + auto* const_val_high = GetConstArg(call, 2); + if (const_val_low && const_val_high) { + auto fakeArgs = Vector{const_val_low, const_val_low, const_val_high}; + [[maybe_unused]] auto result = + const_eval_.clamp(call->Result()->Type(), fakeArgs, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckSmoothstepCall(const CoreBuiltinCall* call) { + auto* const_val_low = GetConstArg(call, 0); + auto* const_val_high = GetConstArg(call, 1); + if (const_val_low && const_val_high) { + auto fakeArgs = Vector{const_val_low, const_val_high, const_val_high}; + [[maybe_unused]] auto result = + const_eval_.smoothstep(call->Result()->Type(), fakeArgs, mod_.SourceOf(call)); + } +} + +void ConstParamValidator::CheckBuiltinCall(const BuiltinCall* inst) { + if (auto* call = inst->As()) { + switch (call->Func()) { + case core::BuiltinFn::kSubgroupShuffle: + case core::BuiltinFn::kSubgroupShuffleXor: + case core::BuiltinFn::kSubgroupShuffleUp: + case core::BuiltinFn::kSubgroupShuffleDown: + CheckSubgroupCall(call); + break; + case core::BuiltinFn::kExtractBits: + CheckExtractBitsCall(call); + break; + case core::BuiltinFn::kInsertBits: + CheckInsertBitsCall(call); + break; + case core::BuiltinFn::kLdexp: + CheckLdexpCall(call); + break; + case core::BuiltinFn::kClamp: + CheckClampCall(call); + break; + case core::BuiltinFn::kSmoothstep: + CheckSmoothstepCall(call); + break; + case core::BuiltinFn::kQuantizeToF16: + CheckQuantizeToF16(call); + break; + case core::BuiltinFn::kPack2X16Float: + CheckPack2x16float(call); + break; + default: + break; + } + } +} + +void ConstParamValidator::CheckBinaryDivModCall(const CoreBinary* call) { + // Integer division by zero should be checked for the partial evaluation case (only rhs + // is const). FP division by zero is only invalid when the whole expression is + // constant-evaluated. + if (call->RHS()->Type()->IsIntegerScalarOrVector()) { + auto rhs_constant = call->RHS()->As(); + if (rhs_constant && rhs_constant->Value()->AnyZero()) { + AddError(*call) << "integer division by zero is invalid"; + } + } +} + +void ConstParamValidator::CheckBinaryShiftCall(const CoreBinary* call) { + // If lhs value is a concrete type, and rhs is a const-expression greater than or equal + // to the bit width of lhs, then it is a shader-creation error. + const auto* elem_type = call->LHS()->Type()->DeepestElement(); + const uint32_t bit_width = elem_type->Size() * 8; + if (auto* rhs_val_as_const = call->RHS()->As()) { + auto* rhs_as_value = rhs_val_as_const->Value(); + for (size_t i = 0, n = rhs_as_value->NumElements(); i < n; i++) { + auto* shift_val = n == 1 ? rhs_as_value : rhs_as_value->Index(i); + if (shift_val->ValueAs() >= bit_width) { + AddError(*call) << "shift " + << (call->Op() == core::BinaryOp::kShiftLeft ? "left" : "right") + << " value must be less than the bit width of the lhs, which is " + << bit_width; + break; + } + } + } +} + +void ConstParamValidator::CheckCoreBinaryCall(const CoreBinary* call) { + switch (call->Op()) { + case core::BinaryOp::kDivide: + case core::BinaryOp::kModulo: + CheckBinaryDivModCall(call); + break; + case core::BinaryOp::kShiftLeft: + case core::BinaryOp::kShiftRight: + CheckBinaryShiftCall(call); + break; + default: + break; + } +} + +Result ConstParamValidator::Run() { + auto instructions = this->mod_.Instructions(); + + for (auto inst : instructions) { + tint::Switch( + inst, // + [&](const BuiltinCall* c) { CheckBuiltinCall(c); }, // + [&](const CoreBinary* c) { CheckCoreBinaryCall(c); }, // + [&](Default) {}); + } + + if (diagnostics_.ContainsErrors()) { + return Failure{diagnostics_.Str()}; + } + + return Success; +} + +} // namespace + +Result ValidateConstParam(Module& mod) { + ConstParamValidator v(mod); + return v.Run(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.h b/3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.h new file mode 100644 index 000000000..7fc257f23 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/const_param_validator.h @@ -0,0 +1,47 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONST_PARAM_VALIDATOR_H_ +#define SRC_TINT_LANG_CORE_IR_CONST_PARAM_VALIDATOR_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// Validates the constant params for all instructions in the IR. +/// @param mod the module to validate +/// @returns success or failure +Result ValidateConstParam(Module& mod); + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONST_PARAM_VALIDATOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/constant.cc b/3rdparty/dawn/src/tint/lang/core/ir/constant.cc new file mode 100644 index 000000000..97907e4a8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/constant.cc @@ -0,0 +1,46 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Constant); + +namespace tint::core::ir { + +Constant::Constant(const core::constant::Value* val) : Base(nullptr), value_(val) { + TINT_ASSERT(value_); + SetType(val->Type()); +} + +Constant::~Constant() = default; + +Constant* Constant::Clone(CloneContext&) { + return this; // Constants are immutable so can just return ourselves. +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/constant.h b/3rdparty/dawn/src/tint/lang/core/ir/constant.h new file mode 100644 index 000000000..0a57e3b57 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/constant.h @@ -0,0 +1,56 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONSTANT_H_ +#define SRC_TINT_LANG_CORE_IR_CONSTANT_H_ + +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/ir/value.h" + +namespace tint::core::ir { + +/// Constant in the IR. +class Constant : public Castable { + public: + /// Constructor + /// @param val the value stored in the constant + explicit Constant(const core::constant::Value* val); + ~Constant() override; + + /// @returns the constants value + const core::constant::Value* Value() const { return value_; } + + /// @copydoc Value::Clone() + Constant* Clone(CloneContext& ctx) override; + + private: + const core::constant::Value* const value_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONSTANT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.cc b/3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.cc new file mode 100644 index 000000000..8af6572fe --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.cc @@ -0,0 +1,57 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/constexpr_if.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ConstExprIf); + +namespace tint::core::ir { + +ConstExprIf::ConstExprIf(Id id) : Base(id) {} + +ConstExprIf::ConstExprIf(Id id, Value* cond, ir::Block* t, ir::Block* f) : Base(id, cond, t, f) {} + +ConstExprIf* ConstExprIf::Clone(CloneContext& ctx) { + auto* cond = ctx.Remap(Condition()); + auto* new_true = ctx.ir.blocks.Create(); + auto* new_false = ctx.ir.blocks.Create(); + + auto* new_if = ctx.ir.CreateInstruction(cond, new_true, new_false); + ctx.Replace(this, new_if); + + True()->CloneInto(ctx, new_true); + False()->CloneInto(ctx, new_false); + + new_if->SetResults(ctx.Clone(results_)); + + return new_if; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.h b/3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.h new file mode 100644 index 000000000..df1f51bc4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/constexpr_if.h @@ -0,0 +1,61 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONSTEXPR_IF_H_ +#define SRC_TINT_LANG_CORE_IR_CONSTEXPR_IF_H_ + +#include + +#include "src/tint/lang/core/ir/if.h" + +namespace tint::core::ir { + +/// A `constexpr-if` is an `if` instruction which will always be evaluated during +/// const-eval processing. The `condition` must be a `const` or `override` +/// expression. +class ConstExprIf final : public Castable { + public: + /// Constructor (no results, no operands, no blocks) + /// @param id the instruction id + explicit ConstExprIf(Id id); + + /// Constructor + /// @param cond the if condition + /// @param t the true block + /// @param f the false block + ConstExprIf(Id id, Value* cond, ir::Block* t, ir::Block* f); + + /// @copydoc Instruction::Clone() + ConstExprIf* Clone(CloneContext& ctx) override; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "constexpr_if"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONSTEXPR_IF_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/construct.cc b/3rdparty/dawn/src/tint/lang/core/ir/construct.cc new file mode 100644 index 000000000..e99a90b82 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/construct.cc @@ -0,0 +1,54 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/construct.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Construct); + +namespace tint::core::ir { + +Construct::Construct(Id id) : Base(id) {} + +Construct::Construct(Id id, InstructionResult* result, VectorRef arguments) : Base(id) { + AddOperands(Construct::kArgsOperandOffset, std::move(arguments)); + AddResult(result); +} + +Construct::~Construct() = default; + +Construct* Construct::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(new_result, args); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/construct.h b/3rdparty/dawn/src/tint/lang/core/ir/construct.h new file mode 100644 index 000000000..9ae249f85 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/construct.h @@ -0,0 +1,71 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONSTRUCT_H_ +#define SRC_TINT_LANG_CORE_IR_CONSTRUCT_H_ + +#include + +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A constructor instruction in the IR. +class Construct final : public Castable { + public: + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The minimum number of operands expected for this instruction + static constexpr size_t kMinOperands = 0; + + /// Constructor (no result, no operands) + /// @param id the instruction id + explicit Construct(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param args the constructor arguments + Construct(Id id, InstructionResult* result, VectorRef args = tint::Empty); + + ~Construct() override; + + /// @copydoc Instruction::Clone() + Construct* Clone(CloneContext& ctx) override; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "construct"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONSTRUCT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/continue.cc b/3rdparty/dawn/src/tint/lang/core/ir/continue.cc new file mode 100644 index 000000000..ae3229956 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/continue.cc @@ -0,0 +1,81 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/continue.h" + +#include + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Continue); + +namespace tint::core::ir { + +Continue::Continue(Id id) : Base(id) {} + +Continue::Continue(Id id, ir::Loop* loop, VectorRef args) : Base(id), loop_(loop) { + TINT_ASSERT(loop_); + + AddOperands(Continue::kArgsOperandOffset, std::move(args)); + + if (loop_) { + loop_->Continuing()->AddInboundSiblingBranch(this); + } +} + +Continue::~Continue() = default; + +void Continue::Destroy() { + if (loop_) { + loop_->Continuing()->RemoveInboundSiblingBranch(this); + } + Instruction::Destroy(); +} + +Continue* Continue::Clone(CloneContext& ctx) { + auto* loop = ctx.Remap(Loop()); + auto args = ctx.Remap(Args()); + + return ctx.ir.CreateInstruction(loop, args); +} + +void Continue::SetLoop(ir::Loop* loop) { + if (loop_ && loop_->Body()) { + loop_->Continuing()->RemoveInboundSiblingBranch(this); + } + loop_ = loop; + if (loop) { + loop->Continuing()->AddInboundSiblingBranch(this); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/continue.h b/3rdparty/dawn/src/tint/lang/core/ir/continue.h new file mode 100644 index 000000000..3451316ae --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/continue.h @@ -0,0 +1,84 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONTINUE_H_ +#define SRC_TINT_LANG_CORE_IR_CONTINUE_H_ + +#include + +#include "src/tint/lang/core/ir/terminator.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Loop; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A continue instruction. +class Continue final : public Castable { + public: + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// Constructor (no operands, no loop) + /// @param id the instruction id + explicit Continue(Id id); + + /// Constructor + /// @param id the instruction id + /// @param loop the loop owning the continue block + /// @param args the arguments for the MultiInBlock + Continue(Id id, ir::Loop* loop, VectorRef args = tint::Empty); + ~Continue() override; + + /// @copydoc Instruction::Clone() + Continue* Clone(CloneContext& ctx) override; + + /// @copydoc Instruction::Destroy() + void Destroy() override; + + /// @returns the loop owning the continue block + ir::Loop* Loop() { return loop_; } + + /// @returns the loop owning the continue block + const ir::Loop* Loop() const { return loop_; } + + /// @param loop the new loop owning the continue block + void SetLoop(ir::Loop* loop); + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "continue"; } + + private: + ir::Loop* loop_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONTINUE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/control_instruction.cc b/3rdparty/dawn/src/tint/lang/core/ir/control_instruction.cc new file mode 100644 index 000000000..91b7c56df --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/control_instruction.cc @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/control_instruction.h" + +#include "src/tint/lang/core/ir/block.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ControlInstruction); + +namespace tint::core::ir { + +ControlInstruction::ControlInstruction(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +ControlInstruction::~ControlInstruction() = default; + +void ControlInstruction::AddExit(Exit* exit) { + exits_.Add(exit); +} + +void ControlInstruction::RemoveExit(Exit* exit) { + exits_.Remove(exit); +} + +void ControlInstruction::Destroy() { + Base::Destroy(); + ForeachBlock([](ir::Block* blk) { blk->Destroy(); }); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/control_instruction.h b/3rdparty/dawn/src/tint/lang/core/ir/control_instruction.h new file mode 100644 index 000000000..1d5ed624f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/control_instruction.h @@ -0,0 +1,83 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONTROL_INSTRUCTION_H_ +#define SRC_TINT_LANG_CORE_IR_CONTROL_INSTRUCTION_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" + +// Forward declarations +namespace tint::core::ir { +class Block; +class Exit; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// Base class of instructions that perform control flow to two or more blocks, owned by the +/// ControlInstruction. +class ControlInstruction : public Castable> { + public: + /// Constructor + /// @param id the instruction id + explicit ControlInstruction(Id id); + + /// 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& cb) = 0; + + /// 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& cb) const = 0; + + /// @return All the exits for the flow control instruction + const Hashset& 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); + + /// @copydoc Instruction::Destroy + void Destroy() override; + + protected: + /// The flow control exits + Hashset exits_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONTROL_INSTRUCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/convert.cc b/3rdparty/dawn/src/tint/lang/core/ir/convert.cc new file mode 100644 index 000000000..d80a65734 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/convert.cc @@ -0,0 +1,54 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/convert.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Convert); + +namespace tint::core::ir { + +Convert::Convert(Id id) : Base(id) {} + +Convert::Convert(Id id, InstructionResult* result, Value* value) : Base(id) { + AddOperand(Convert::kValueOperandOffset, value); + AddResult(result); +} + +Convert::~Convert() = default; + +Convert* Convert::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* val = ctx.Remap(Args()[0]); + return ctx.ir.CreateInstruction(new_result, val); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/convert.h b/3rdparty/dawn/src/tint/lang/core/ir/convert.h new file mode 100644 index 000000000..616abc415 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/convert.h @@ -0,0 +1,72 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CONVERT_H_ +#define SRC_TINT_LANG_CORE_IR_CONVERT_H_ + +#include + +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A value conversion instruction in the IR. +class Convert final : public Castable { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands expected for this instruction + static constexpr size_t kNumOperands = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Convert(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param value the value to convert + Convert(Id id, InstructionResult* result, Value* value); + + ~Convert() override; + + /// @copydoc Instruction::Clone() + Convert* Clone(CloneContext& ctx) override; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "convert"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CONVERT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/core_binary.cc b/3rdparty/dawn/src/tint/lang/core/ir/core_binary.cc new file mode 100644 index 000000000..ba55795b3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/core_binary.cc @@ -0,0 +1,56 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/core_binary.h" + +#include "src/tint/lang/core/intrinsic/dialect.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::CoreBinary); + +namespace tint::core::ir { + +CoreBinary::CoreBinary(Id id) : Base(id) {} + +CoreBinary::CoreBinary(Id id, InstructionResult* result, BinaryOp op, Value* lhs, Value* rhs) + : Base(id, result, op, lhs, rhs) {} + +CoreBinary::~CoreBinary() = default; + +CoreBinary* CoreBinary::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* lhs = ctx.Remap(LHS()); + auto* rhs = ctx.Remap(RHS()); + return ctx.ir.CreateInstruction(new_result, Op(), lhs, rhs); +} + +const core::intrinsic::TableData& CoreBinary::TableData() const { + return core::intrinsic::Dialect::kData; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/core_binary.h b/3rdparty/dawn/src/tint/lang/core/ir/core_binary.h new file mode 100644 index 000000000..3cfbbcab6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/core_binary.h @@ -0,0 +1,64 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CORE_BINARY_H_ +#define SRC_TINT_LANG_CORE_IR_CORE_BINARY_H_ + +#include "src/tint/lang/core/ir/binary.h" + +namespace tint::core::ir { + +/// A core-dialect binary-op instruction in the IR. +class CoreBinary final : public Castable { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit CoreBinary(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param op the Binary operator + /// @param lhs the lhs of the instruction + /// @param rhs the rhs of the instruction + CoreBinary(Id id, InstructionResult* result, BinaryOp op, Value* lhs, Value* rhs); + + ~CoreBinary() override; + + /// @copydoc Instruction::Clone() + CoreBinary* Clone(CloneContext& ctx) override; + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CORE_BINARY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.cc b/3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.cc new file mode 100644 index 000000000..3922f5f74 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.cc @@ -0,0 +1,229 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/core_builtin_call.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::CoreBuiltinCall); + +namespace tint::core::ir { + +CoreBuiltinCall::CoreBuiltinCall(Id id) : Base(id) {} + +CoreBuiltinCall::CoreBuiltinCall(Id id, + InstructionResult* result, + core::BuiltinFn func, + VectorRef arguments) + : Base(id, result, arguments), func_(func) { + TINT_ASSERT(func != core::BuiltinFn::kNone); +} + +CoreBuiltinCall::~CoreBuiltinCall() = default; + +CoreBuiltinCall* CoreBuiltinCall::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(new_result, func_, args); +} + +tint::core::ir::Instruction::Accesses CoreBuiltinCall::GetSideEffects() const { + switch (func_) { + case BuiltinFn::kAtomicLoad: + case BuiltinFn::kInputAttachmentLoad: + case BuiltinFn::kSubgroupMatrixLoad: + case BuiltinFn::kTextureSample: + case BuiltinFn::kTextureSampleBias: + case BuiltinFn::kTextureSampleCompare: + case BuiltinFn::kTextureSampleCompareLevel: + case BuiltinFn::kTextureSampleGrad: + case BuiltinFn::kTextureSampleLevel: + case BuiltinFn::kTextureSampleBaseClampToEdge: + case BuiltinFn::kTextureLoad: + case BuiltinFn::kGetResource: + return Accesses{Access::kLoad}; + + case BuiltinFn::kSubgroupMatrixStore: + case BuiltinFn::kTextureStore: + return Accesses{Access::kStore}; + + case BuiltinFn::kAtomicStore: + case BuiltinFn::kAtomicAdd: + case BuiltinFn::kAtomicSub: + case BuiltinFn::kAtomicMax: + case BuiltinFn::kAtomicMin: + case BuiltinFn::kAtomicAnd: + case BuiltinFn::kAtomicOr: + case BuiltinFn::kAtomicXor: + case BuiltinFn::kAtomicExchange: + case BuiltinFn::kAtomicCompareExchangeWeak: + case BuiltinFn::kDpdx: + case BuiltinFn::kDpdxCoarse: + case BuiltinFn::kDpdxFine: + case BuiltinFn::kDpdy: + case BuiltinFn::kDpdyCoarse: + case BuiltinFn::kDpdyFine: + case BuiltinFn::kFwidth: + case BuiltinFn::kFwidthCoarse: + case BuiltinFn::kFwidthFine: + case BuiltinFn::kSubgroupBallot: + case BuiltinFn::kSubgroupElect: + case BuiltinFn::kSubgroupBroadcast: + case BuiltinFn::kSubgroupBroadcastFirst: + case BuiltinFn::kSubgroupShuffle: + case BuiltinFn::kSubgroupShuffleXor: + case BuiltinFn::kSubgroupShuffleUp: + case BuiltinFn::kSubgroupShuffleDown: + case BuiltinFn::kSubgroupAdd: + case BuiltinFn::kSubgroupInclusiveAdd: + case BuiltinFn::kSubgroupExclusiveAdd: + case BuiltinFn::kSubgroupMul: + case BuiltinFn::kSubgroupInclusiveMul: + case BuiltinFn::kSubgroupExclusiveMul: + case BuiltinFn::kSubgroupAnd: + case BuiltinFn::kSubgroupOr: + case BuiltinFn::kSubgroupXor: + case BuiltinFn::kSubgroupMin: + case BuiltinFn::kSubgroupMax: + case BuiltinFn::kSubgroupAll: + case BuiltinFn::kSubgroupAny: + case BuiltinFn::kQuadBroadcast: + case BuiltinFn::kQuadSwapX: + case BuiltinFn::kQuadSwapY: + case BuiltinFn::kQuadSwapDiagonal: + case BuiltinFn::kStorageBarrier: + case BuiltinFn::kWorkgroupBarrier: + case BuiltinFn::kTextureBarrier: + case BuiltinFn::kPrint: + return Accesses{Access::kLoad, Access::kStore}; + + case BuiltinFn::kAbs: + case BuiltinFn::kAcos: + case BuiltinFn::kAcosh: + case BuiltinFn::kAll: + case BuiltinFn::kAny: + case BuiltinFn::kArrayLength: + case BuiltinFn::kAsin: + case BuiltinFn::kAsinh: + case BuiltinFn::kAtan: + case BuiltinFn::kAtan2: + case BuiltinFn::kAtanh: + case BuiltinFn::kCeil: + case BuiltinFn::kClamp: + case BuiltinFn::kCos: + case BuiltinFn::kCosh: + case BuiltinFn::kCountLeadingZeros: + case BuiltinFn::kCountOneBits: + case BuiltinFn::kCountTrailingZeros: + case BuiltinFn::kCross: + case BuiltinFn::kDegrees: + case BuiltinFn::kDeterminant: + case BuiltinFn::kDistance: + case BuiltinFn::kDot: + case BuiltinFn::kDot4I8Packed: + case BuiltinFn::kDot4U8Packed: + case BuiltinFn::kExp: + case BuiltinFn::kExp2: + case BuiltinFn::kExtractBits: + case BuiltinFn::kFaceForward: + case BuiltinFn::kFirstLeadingBit: + case BuiltinFn::kFirstTrailingBit: + case BuiltinFn::kFloor: + case BuiltinFn::kFma: + case BuiltinFn::kFract: + case BuiltinFn::kFrexp: + case BuiltinFn::kInsertBits: + case BuiltinFn::kInverseSqrt: + case BuiltinFn::kLdexp: + case BuiltinFn::kLength: + case BuiltinFn::kLog: + case BuiltinFn::kLog2: + case BuiltinFn::kMax: + case BuiltinFn::kMin: + case BuiltinFn::kMix: + case BuiltinFn::kModf: + case BuiltinFn::kNormalize: + case BuiltinFn::kPack2X16Float: + case BuiltinFn::kPack2X16Snorm: + case BuiltinFn::kPack2X16Unorm: + case BuiltinFn::kPack4X8Snorm: + case BuiltinFn::kPack4X8Unorm: + case BuiltinFn::kPack4XI8: + case BuiltinFn::kPack4XU8: + case BuiltinFn::kPack4XI8Clamp: + case BuiltinFn::kPack4XU8Clamp: + case BuiltinFn::kPow: + case BuiltinFn::kQuantizeToF16: + case BuiltinFn::kRadians: + case BuiltinFn::kReflect: + case BuiltinFn::kRefract: + case BuiltinFn::kReverseBits: + case BuiltinFn::kRound: + case BuiltinFn::kSaturate: + case BuiltinFn::kSelect: + case BuiltinFn::kSign: + case BuiltinFn::kSin: + case BuiltinFn::kSinh: + case BuiltinFn::kSmoothstep: + case BuiltinFn::kSqrt: + case BuiltinFn::kStep: + case BuiltinFn::kTan: + case BuiltinFn::kTanh: + case BuiltinFn::kTextureDimensions: + case BuiltinFn::kTextureGather: + case BuiltinFn::kTextureGatherCompare: + case BuiltinFn::kTextureNumLayers: + case BuiltinFn::kTextureNumLevels: + case BuiltinFn::kTextureNumSamples: + case BuiltinFn::kTranspose: + case BuiltinFn::kTrunc: + case BuiltinFn::kUnpack2X16Float: + case BuiltinFn::kUnpack2X16Snorm: + case BuiltinFn::kUnpack2X16Unorm: + case BuiltinFn::kUnpack4X8Snorm: + case BuiltinFn::kUnpack4X8Unorm: + case BuiltinFn::kUnpack4XI8: + case BuiltinFn::kUnpack4XU8: + case BuiltinFn::kSubgroupMatrixMultiply: + case BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + case BuiltinFn::kSubgroupMatrixScalarAdd: + case BuiltinFn::kSubgroupMatrixScalarSubtract: + case BuiltinFn::kSubgroupMatrixScalarMultiply: + case BuiltinFn::kHasResource: + case BuiltinFn::kBufferView: + case BuiltinFn::kBufferLength: + case BuiltinFn::kNone: + break; + } + return Accesses{}; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.h b/3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.h new file mode 100644 index 000000000..830f6947d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/core_builtin_call.h @@ -0,0 +1,89 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CORE_BUILTIN_CALL_H_ +#define SRC_TINT_LANG_CORE_IR_CORE_BUILTIN_CALL_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/intrinsic/dialect.h" +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/ir/builtin_call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A core builtin call instruction in the IR. +class CoreBuiltinCall final : public Castable { + public: + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit CoreBuiltinCall(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param func the builtin function + /// @param args the conversion arguments + CoreBuiltinCall(Id id, + InstructionResult* result, + core::BuiltinFn func, + VectorRef args = tint::Empty); + + ~CoreBuiltinCall() override; + + /// @copydoc Instruction::Clone() + CoreBuiltinCall* Clone(CloneContext& ctx) override; + + /// @returns the builtin function + core::BuiltinFn Func() const { return func_; } + + /// @param func the new builtin function + void SetFunc(core::BuiltinFn func) { func_ = func; } + + /// @returns the identifier for the function + size_t FuncId() const override { return static_cast(func_); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return core::str(func_); } + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override { + return core::intrinsic::Dialect::kData; + } + + /// @returns an access information for the function + Accesses GetSideEffects() const override; + + private: + core::BuiltinFn func_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CORE_BUILTIN_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/core_unary.cc b/3rdparty/dawn/src/tint/lang/core/ir/core_unary.cc new file mode 100644 index 000000000..ac2ba5670 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/core_unary.cc @@ -0,0 +1,55 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/core_unary.h" + +#include "src/tint/lang/core/intrinsic/dialect.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::CoreUnary); + +namespace tint::core::ir { + +CoreUnary::CoreUnary(Id id) : Base(id) {} + +CoreUnary::CoreUnary(Id id, InstructionResult* result, UnaryOp op, Value* val) + : Base(id, result, op, val) {} + +CoreUnary::~CoreUnary() = default; + +CoreUnary* CoreUnary::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* val = ctx.Remap(Val()); + return ctx.ir.CreateInstruction(new_result, Op(), val); +} + +const core::intrinsic::TableData& CoreUnary::TableData() const { + return core::intrinsic::Dialect::kData; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/core_unary.h b/3rdparty/dawn/src/tint/lang/core/ir/core_unary.h new file mode 100644 index 000000000..a0eb9f818 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/core_unary.h @@ -0,0 +1,63 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_CORE_UNARY_H_ +#define SRC_TINT_LANG_CORE_IR_CORE_UNARY_H_ + +#include "src/tint/lang/core/ir/unary.h" + +namespace tint::core::ir { + +/// A core-dialect unary instruction in the IR. +class CoreUnary final : public Castable { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit CoreUnary(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param op the unary operator + /// @param val the input value for the instruction + CoreUnary(Id id, InstructionResult* result, UnaryOp op, Value* val); + + ~CoreUnary() override; + + /// @copydoc Instruction::Clone() + CoreUnary* Clone(CloneContext& ctx) override; + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_CORE_UNARY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/disassembler.cc b/3rdparty/dawn/src/tint/lang/core/ir/disassembler.cc new file mode 100644 index 000000000..73d525fbd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/disassembler.cc @@ -0,0 +1,1186 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/disassembler.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/constant/composite.h" +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/constant/splat.h" +#include "src/tint/lang/core/constant/string.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/block_param.h" +#include "src/tint/lang/core/ir/break_if.h" +#include "src/tint/lang/core/ir/builtin_call.h" +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/continue.h" +#include "src/tint/lang/core/ir/discard.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/member_builtin_call.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/store_vector_element.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/terminate_invocation.h" +#include "src/tint/lang/core/ir/type/array_count.h" +#include "src/tint/lang/core/ir/unary.h" +#include "src/tint/lang/core/ir/unreachable.h" +#include "src/tint/lang/core/ir/unused.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::core::ir { +namespace { + +static constexpr auto StylePlain = style::Plain; +static constexpr auto StyleAttribute = style::Attribute + style::NoQuote; +static constexpr auto StyleCode = style::Code + style::NoQuote; +static constexpr auto StyleComment = style::Comment + style::NoQuote; +static constexpr auto StyleEnum = style::Enum + style::NoQuote; +static constexpr auto StyleError = style::Error + style::NoQuote; +static constexpr auto StyleFunction = style::Function + style::NoQuote; +static constexpr auto StyleInstruction = style::Instruction + style::NoQuote; +static constexpr auto StyleKeyword = style::Keyword + style::NoQuote; +static constexpr auto StyleLabel = style::Label + style::NoQuote; +static constexpr auto StyleLiteral = style::Literal + style::NoQuote; +static constexpr auto StyleType = style::Type + style::NoQuote; +static constexpr auto StyleVariable = style::Variable + style::NoQuote; + +class ScopedIndent { + public: + explicit ScopedIndent(uint32_t& indent) : indent_(indent) { indent_ += 2; } + + ~ScopedIndent() { indent_ -= 2; } + + private: + uint32_t& indent_; +}; + +} // namespace + +Disassembler::Disassembler(Disassembler&&) = default; + +Disassembler::Disassembler(const Module& mod) : mod_(mod) { + Disassemble(); + file_ = std::make_shared("", Plain()); + + auto set_source_file = [&](auto& map) { + for (auto& it : map) { + it.value.file = file_.get(); + } + }; + set_source_file(block_to_src_); + set_source_file(block_param_to_src_); + set_source_file(instruction_to_src_); + set_source_file(operand_to_src_); + set_source_file(result_to_src_); + set_source_file(function_to_src_); + set_source_file(function_param_to_src_); +} + +Disassembler::~Disassembler() = default; + +void Disassembler::Disassemble() { + TINT_DEFER(out_ << StylePlain); + out_.Clear(); + out_ << StyleCode; + + for (auto* ty : mod_.Types()) { + if (auto* str = ty->As()) { + EmitStructDecl(str); + } + } + + if (!mod_.root_block->IsEmpty()) { + EmitBlock(mod_.root_block, "root"); + EmitLine(); + } + + for (auto& func : mod_.functions) { + EmitFunction(func); + } +} + +StyledText& Disassembler::Indent() { + for (uint32_t i = 0; i < indent_size_; i++) { + out_ << " "; + } + return out_; +} + +void Disassembler::EmitLine() { + out_ << "\n"; + current_output_line_ += 1; + current_output_start_pos_ = static_cast(out_.Length()); +} + +Source::Location Disassembler::MakeCurrentLocation() { + return Source::Location{ + current_output_line_, + static_cast(out_.Length()) - current_output_start_pos_ + 1, + }; +} + +void Disassembler::EmitBlock(const Block* blk, std::string_view comment /* = "" */) { + Indent(); + + SourceMarker sm(this); + out_ << NameOf(blk); + if (auto* merge = blk->As()) { + if (!merge->Params().IsEmpty()) { + out_ << " ("; + for (auto* p : merge->Params()) { + if (p != merge->Params().Front()) { + out_ << ", "; + } + { + SourceMarker psm(this); + EmitValue(p); + psm.Store(p); + } + out_ << ":" << NameOf(p->Type()); + } + out_ << ")"; + } + } + sm.Store(blk); + + out_ << ": {"; + if (!comment.empty()) { + out_ << " " << StyleComment("# ", comment); + } + + EmitLine(); + { + ScopedIndent si(indent_size_); + for (auto* inst : *blk) { + Indent(); + EmitInstruction(inst); + } + } + Indent() << "}"; + + EmitLine(); +} + +void Disassembler::EmitBindingPoint(BindingPoint p) { + out_ << StyleAttribute("@binding_point") << "(" << StyleLiteral(p.group) << ", " + << StyleLiteral(p.binding) << ")"; +} + +void Disassembler::EmitInputAttachmentIndex(uint32_t i) { + out_ << StyleAttribute("@input_attachment_index") << "(" << StyleLiteral(i) << ")"; +} + +void Disassembler::EmitInterpolation(Interpolation interp) { + out_ << StyleAttribute("@interpolate") << "("; + out_ << StyleEnum(interp.type); + if (interp.sampling != core::InterpolationSampling::kUndefined) { + out_ << ", "; + out_ << StyleEnum(interp.sampling); + } + out_ << ")"; +} + +void Disassembler::EmitParamAttributes(const FunctionParam* p) { + if (!p->Invariant() && !p->Location().has_value() && !p->Color().has_value() && + !p->BindingPoint().has_value() && !p->Builtin().has_value()) { + return; + } + + out_ << " ["; + + bool need_comma = false; + auto comma = [&] { + if (need_comma) { + out_ << ", "; + } + }; + + if (p->Invariant()) { + comma(); + out_ << StyleAttribute("@invariant"); + need_comma = true; + } + if (p->Location().has_value()) { + comma(); + out_ << StyleAttribute("@location") << "(" << p->Location().value() << ")"; + need_comma = true; + } + if (p->Color().has_value()) { + comma(); + out_ << StyleAttribute("@color") << "(" << p->Color().value() << ")"; + need_comma = true; + } + if (p->Interpolation().has_value()) { + comma(); + EmitInterpolation(p->Interpolation().value()); + need_comma = true; + } + if (p->BindingPoint().has_value()) { + comma(); + EmitBindingPoint(p->BindingPoint().value()); + need_comma = true; + } + if (p->Builtin().has_value()) { + comma(); + out_ << StyleAttribute("@", p->Builtin().value()); + need_comma = true; + } + out_ << "]"; +} + +void Disassembler::EmitReturnAttributes(const Function* func) { + if (!func->ReturnInvariant() && !func->ReturnLocation().has_value() && + !func->ReturnBuiltin().has_value()) { + return; + } + + out_ << " ["; + + bool need_comma = false; + auto comma = [&] { + if (need_comma) { + out_ << ", "; + } + }; + if (func->ReturnInvariant()) { + comma(); + out_ << StyleAttribute("@invariant"); + need_comma = true; + } + if (func->ReturnLocation().has_value()) { + comma(); + out_ << StyleAttribute("@location") << "(" << func->ReturnLocation().value() << ")"; + need_comma = true; + } + if (func->ReturnInterpolation().has_value()) { + comma(); + EmitInterpolation(func->ReturnInterpolation().value()); + need_comma = true; + } + if (func->ReturnBuiltin().has_value()) { + comma(); + out_ << StyleAttribute("@", func->ReturnBuiltin().value()); + need_comma = true; + } + out_ << "]"; +} + +void Disassembler::EmitFunction(const Function* func) { + in_function_ = true; + + auto fn_id = NameOf(func); + { + SourceMarker sm(this); + Indent() << fn_id; + sm.Store(func); + } + out_ << " ="; + + if (func->IsEntryPoint()) { + out_ << " " << StyleAttribute("@", func->Stage()); + } + if (func->WorkgroupSize()) { + auto arr = func->WorkgroupSize().value(); + out_ << " " << StyleAttribute("@workgroup_size") << "("; + EmitValue(arr[0]); + out_ << ", "; + EmitValue(arr[1]); + out_ << ", "; + EmitValue(arr[2]); + out_ << ")"; + } + if (func->SubgroupSize()) { + auto subgroup_size = func->SubgroupSize().value(); + out_ << " " << StyleAttribute("@subgroup_size") << "("; + EmitValue(subgroup_size); + out_ << ")"; + } + + out_ << " " << StyleKeyword("func") << "("; + + for (auto* p : func->Params()) { + if (p != func->Params().Front()) { + out_ << ", "; + } + SourceMarker sm(this); + out_ << NameOf(p) << ":" << NameOf(p->Type()); + sm.Store(p); + + EmitParamAttributes(p); + } + out_ << "):" << NameOf(func->ReturnType()); + + EmitReturnAttributes(func); + + out_ << " {"; + + { // Add a comment if the function IDs or parameter IDs doesn't match their name + Vector names; + if (auto name = mod_.NameOf(func); name.IsValid()) { + if ("%" + name.Name() != fn_id.Plain()) { + names.Push(fn_id.Plain() + ": '" + name.Name() + "'"); + } + } + for (auto* p : func->Params()) { + if (auto name = mod_.NameOf(p); name.IsValid()) { + auto id = NameOf(p); + if ("%" + name.Name() != id.Plain()) { + names.Push(id.Plain() + ": '" + name.Name() + "'"); + } + } + } + if (!names.IsEmpty()) { + out_ << " " << StyleComment("# ", tint::Join(names, ", ")); + } + } + + EmitLine(); + + { + ScopedIndent si(indent_size_); + EmitBlock(func->Block()); + } + Indent() << "}"; + EmitLine(); +} + +void Disassembler::EmitValueWithType(const Instruction* val) { + SourceMarker sm(this); + // Always emit the first value, so that 'undef' is printed if there is no value + EmitValueWithType(val->Result(0)); + sm.StoreResult(IndexedValue{val, 0}); + + if (auto results = val->Results(); !results.IsEmpty()) { + for (size_t i = 1; i < results.Length(); ++i) { + out_ << ", "; + EmitValueWithType(results[i]); + sm.StoreResult(IndexedValue{val, i}); + } + } +} + +void Disassembler::EmitValueWithType(const Value* val) { + EmitValue(val); + if (val) { + out_ << ":" << NameOf(val->Type()); + } +} + +StyledText Disassembler::ValueToStyledText(const Value* val) { + StyledText text{}; + if (!val) { + text << StyleLiteral("undef"); + return text; + } + + tint::Switch( + val, + [&](const ir::Constant* constant) { + std::function emit = + [&](const core::constant::Value* c) { + tint::Switch( + c, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(scalar->ValueAs().value, "i"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(i32(scalar->ValueAs().value), "i8"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(scalar->ValueAs().value, "u"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(scalar->ValueAs().value, "u64"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(u32(scalar->ValueAs().value), "u8"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(scalar->ValueAs().value, "f"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral(scalar->ValueAs().value, "h"); + }, + [&](const core::constant::Scalar* scalar) { + text << StyleLiteral((scalar->ValueAs() ? "true" : "false")); + }, + [&](const core::constant::Splat* splat) { + text << NameOf(splat->Type()) << "("; + emit(splat->Index(0)); + text << ")"; + }, + [&](const core::constant::Composite* composite) { + text << NameOf(composite->Type()) << "("; + bool need_comma = false; + for (const auto* elem : composite->elements) { + if (need_comma) { + text << ", "; + } + emit(elem); + need_comma = true; + } + text << ")"; + }, + [&](const core::constant::String* str) { + text << "\"" << str->Value() << "\""; + }, + TINT_ICE_ON_NO_MATCH); + }; + emit(constant->Value()); + }, + [&](const tint::core::ir::Unused*) { text << StyleLiteral("unused"); }, + [&](Default) { text << NameOf(val); }); + return text; +} + +void Disassembler::EmitValue(const Value* val) { + out_ << ValueToStyledText(val); +} + +void Disassembler::EmitInstructionName(const Instruction* inst) { + SourceMarker sm(this); + out_ << StyleInstruction(inst->FriendlyName()); + sm.Store(inst); +} + +void Disassembler::EmitInstruction(const Instruction* inst) { + TINT_DEFER(EmitLine()); + + if (!inst->Alive()) { + SourceMarker sm(this); + out_ << StyleError("TypeInfo().name, " ", inst, ">"); + sm.Store(inst); + return; + } + tint::Switch( + inst, // + [&](const Switch* s) { EmitSwitch(s); }, // + [&](const If* i) { EmitIf(i); }, // + [&](const Loop* l) { EmitLoop(l); }, // + [&](const Binary* b) { EmitBinary(b); }, // + [&](const Unary* u) { EmitUnary(u); }, // + [&](const Discard* d) { EmitInstructionName(d); }, + [&](const Store* s) { + EmitInstructionName(s); + EmitOperandList(s); + }, + [&](const StoreVectorElement* s) { + EmitInstructionName(s); + EmitOperandList(s); + }, + [&](const UserCall* uc) { + EmitValueWithType(uc); + out_ << " = "; + EmitInstructionName(uc); + EmitOperandList(uc); + }, + [&](const BuiltinCall* c) { + EmitValueWithType(c); + out_ << " = "; + EmitInstructionName(c); + + auto ep = c->ExplicitTemplateParams(); + if (!ep.IsEmpty()) { + out_ << "<"; + for (size_t i = 0; i < ep.Length(); ++i) { + if (i > 0) { + out_ << ", "; + } + out_ << ep[i]->FriendlyName(); + } + out_ << ">"; + } + + EmitOperandList(c, BuiltinCall::kArgsOperandOffset); + }, + [&](const MemberBuiltinCall* c) { + EmitValueWithType(c); + out_ << " = "; + EmitOperand(c, MemberBuiltinCall::kObjectOperandOffset); + out_ << "."; + EmitInstructionName(c); + EmitOperandList(c, UserCall::kArgsOperandOffset); + }, + [&](const Override* o) { + EmitValueWithType(o); + out_ << " = "; + EmitInstructionName(o); + EmitOperandList(o); + if (o->OverrideId().has_value()) { + out_ << " @id(" << o->OverrideId().value().value << ")"; + } + }, + [&](const Var* v) { + EmitValueWithType(v); + out_ << " = "; + EmitInstructionName(v); + EmitOperandList(v); + + if (v->BindingPoint().has_value()) { + out_ << " "; + EmitBindingPoint(v->BindingPoint().value()); + } + + if (v->InputAttachmentIndex().has_value()) { + out_ << " "; + EmitInputAttachmentIndex(v->InputAttachmentIndex().value()); + } + + if (v->Attributes().invariant) { + out_ << " " << StyleAttribute("@invariant"); + } + if (v->Attributes().location.has_value()) { + out_ << " " << StyleAttribute("@location") << "(" + << v->Attributes().location.value() << ")"; + } + if (v->Attributes().blend_src.has_value()) { + out_ << " " << StyleAttribute("@blend_src") << "(" + << v->Attributes().blend_src.value() << ")"; + } + if (v->Attributes().interpolation.has_value()) { + auto& interp = v->Attributes().interpolation.value(); + out_ << " " << StyleAttribute("@interpolate") << "(" << interp.type; + if (interp.sampling != core::InterpolationSampling::kUndefined) { + out_ << ", " << interp.sampling; + } + out_ << ")"; + } + if (v->Attributes().builtin.has_value()) { + out_ << " " << StyleAttribute("@builtin") << "(" << v->Attributes().builtin.value() + << ")"; + } + }, + [&](const Swizzle* s) { + EmitValueWithType(s); + out_ << " = "; + EmitInstructionName(s); + out_ << " "; + EmitValue(s->Object()); + + out_ << ","; + if (!s->Indices().IsEmpty()) { + out_ << " "; + } + for (auto idx : s->Indices()) { + switch (idx) { + case 0: + out_ << "x"; + break; + case 1: + out_ << "y"; + break; + case 2: + out_ << "z"; + break; + case 3: + out_ << "w"; + break; + } + } + }, + [&](const Terminator* b) { EmitTerminator(b); }, + [&](Default) { + EmitValueWithType(inst); + out_ << " = "; + EmitInstructionName(inst); + EmitOperandList(inst); + }); + + { // Add a comment if the result IDs don't match their names + Vector names; + for (auto* result : inst->Results()) { + if (result) { + if (auto name = mod_.NameOf(result); name.IsValid()) { + auto id = NameOf(result).Plain(); + if ("%" + name.Name() != id) { + names.Push(id + ": '" + name.Name() + "'"); + } + } + } + } + if (!names.IsEmpty()) { + out_ << " # " << tint::Join(names, ", "); + } + } +} + +void Disassembler::EmitOperand(const Instruction* inst, size_t index) { + SourceMarker marker(this); + EmitValue(inst->Operand(index)); + marker.Store(IndexedValue{inst, static_cast(index)}); +} + +void Disassembler::EmitOperandList(const Instruction* inst, size_t start_index /* = 0 */) { + for (size_t i = start_index, n = inst->Operands().Length(); i < n; i++) { + if (i != start_index) { + out_ << ", "; + } else { + out_ << " "; + } + EmitOperand(inst, i); + } +} + +void Disassembler::EmitOperandList(const Instruction* inst, size_t start_index, size_t count) { + size_t n = std::min(start_index + count, inst->Operands().Length()); + for (size_t i = start_index; i < n; i++) { + if (i != start_index) { + out_ << ", "; + } else { + out_ << " "; + } + EmitOperand(inst, i); + } +} + +void Disassembler::EmitIf(const If* if_) { + SourceMarker sm(this); + if (auto results = if_->Results(); !results.IsEmpty()) { + for (size_t i = 0; i < results.Length(); ++i) { + if (i > 0) { + out_ << ", "; + } + SourceMarker rs(this); + EmitValueWithType(results[i]); + rs.StoreResult(IndexedValue{if_, i}); + } + out_ << " = "; + } + + out_ << StyleInstruction(if_->FriendlyName()) << " "; + + EmitOperand(if_, If::kConditionOperandOffset); + + bool has_false = if_->False() != nullptr && !if_->False()->IsEmpty(); + + out_ << " [" << StyleKeyword("t") << ": " << NameOf(if_->True()); + if (has_false) { + out_ << ", " << StyleKeyword("f") << ": " << NameOf(if_->False()); + } + out_ << "]"; + sm.Store(if_); + + out_ << " { " << StyleComment("# ", NameOf(if_)); + EmitLine(); + + // True block is assumed to have instructions + { + ScopedIndent si(indent_size_); + EmitBlock(if_->True(), "true"); + } + + if (has_false) { + ScopedIndent si(indent_size_); + EmitBlock(if_->False(), "false"); + } else if (auto results = if_->Results(); !results.IsEmpty()) { + ScopedIndent si(indent_size_); + Indent(); + out_ << StyleComment("# implicit false block: exit_if undef"); + for (size_t v = 1; v < if_->Results().Length(); v++) { + out_ << StyleComment(", undef"); + } + EmitLine(); + } + + Indent(); + out_ << "}"; +} + +void Disassembler::EmitLoop(const Loop* l) { + SourceMarker sm(this); + if (auto results = l->Results(); !results.IsEmpty()) { + for (size_t i = 0; i < results.Length(); ++i) { + if (i > 0) { + out_ << ", "; + } + SourceMarker rs(this); + EmitValueWithType(results[i]); + rs.StoreResult(IndexedValue{l, i}); + } + out_ << " = "; + } + out_ << StyleInstruction("loop") << " ["; + + if (l->Initializer() != nullptr && !l->Initializer()->IsEmpty()) { + out_ << StyleKeyword("i") << ": " << NameOf(l->Initializer()); + out_ << ", "; + } + + out_ << StyleKeyword("b") << ": " << NameOf(l->Body()); + + if (l->Continuing() != nullptr && !l->Continuing()->IsEmpty()) { + out_ << ", "; + out_ << StyleKeyword("c") << ": " << NameOf(l->Continuing()); + } + + out_ << "]"; + sm.Store(l); + + out_ << " { " << StyleComment("# ", NameOf(l)); + EmitLine(); + + if (l->Initializer() != nullptr && !l->Initializer()->IsEmpty()) { + ScopedIndent si(indent_size_); + EmitBlock(l->Initializer(), "initializer"); + } + + if (l->Body() != nullptr) { + ScopedIndent si(indent_size_); + EmitBlock(l->Body(), "body"); + } + + if (l->Continuing() != nullptr && !l->Continuing()->IsEmpty()) { + ScopedIndent si(indent_size_); + EmitBlock(l->Continuing(), "continuing"); + } + + Indent(); + out_ << "}"; +} + +void Disassembler::EmitSwitch(const Switch* s) { + SourceMarker sm(this); + if (auto results = s->Results(); !results.IsEmpty()) { + for (size_t i = 0; i < results.Length(); ++i) { + if (i > 0) { + out_ << ", "; + } + SourceMarker rs(this); + EmitValueWithType(results[i]); + rs.StoreResult(IndexedValue{s, i}); + } + out_ << " = "; + } + out_ << StyleInstruction("switch") << " "; + EmitValue(s->Condition()); + out_ << " ["; + for (auto& c : s->Cases()) { + if (&c != &s->Cases().Front()) { + out_ << ", "; + } + out_ << "c: ("; + Vector selectors; + bool contains_default = false; + for (auto& selector : c.selectors) { + if (selector.IsDefault()) { + contains_default = true; + continue; + } + selectors.Push(ValueToStyledText(selector.val)); + } + selectors.Sort([](StyledText& lhs, StyledText& rhs) { return lhs.Plain() < rhs.Plain(); }); + + if (contains_default) { + StyledText d{}; + d << StyleKeyword("default"); + selectors.Push(d); + } + + for (auto& selector : selectors) { + if (&selector != &selectors.Front()) { + out_ << " "; + } + out_ << selector; + } + out_ << ", " << NameOf(c.block) << ")"; + } + out_ << "]"; + sm.Store(s); + + out_ << " { " << StyleComment("# ", NameOf(s)); + EmitLine(); + + for (auto& c : s->Cases()) { + ScopedIndent si(indent_size_); + EmitBlock(c.block, "case"); + } + + Indent(); + out_ << "}"; +} + +void Disassembler::EmitTerminator(const Terminator* term) { + SourceMarker sm(this); + auto args_offset = tint::Switch>( + term, + [&](const ir::Return*) { + out_ << StyleInstruction("ret"); + return ir::Return::kArgsOperandOffset; + }, + [&](const ir::Continue*) { + out_ << StyleInstruction("continue"); + return ir::Continue::kArgsOperandOffset; + }, + [&](const ir::ExitIf*) { + out_ << StyleInstruction("exit_if"); + return ir::ExitIf::kArgsOperandOffset; + }, + [&](const ir::ExitSwitch*) { + out_ << StyleInstruction("exit_switch"); + return ir::ExitSwitch::kArgsOperandOffset; + }, + [&](const ir::ExitLoop*) { + out_ << StyleInstruction("exit_loop"); + return ir::ExitLoop::kArgsOperandOffset; + }, + [&](const ir::NextIteration*) { + out_ << StyleInstruction("next_iteration"); + return ir::NextIteration::kArgsOperandOffset; + }, + [&](const ir::Unreachable*) { + out_ << StyleInstruction("unreachable"); + return std::nullopt; + }, + [&](const ir::BreakIf* bi) { + out_ << StyleInstruction("break_if"); + out_ << " "; + EmitValue(bi->Condition()); + auto next_iter_values = bi->NextIterValues(); + auto exit_values = bi->ExitValues(); + if (!next_iter_values.empty()) { + out_ << " " << StyleLabel("next_iteration") << ": ["; + EmitOperandList(bi, ir::BreakIf::kArgsOperandOffset, next_iter_values.size()); + out_ << " ]"; + } + if (!exit_values.empty()) { + out_ << " " << StyleLabel("exit_loop") << ": ["; + EmitOperandList(bi, ir::BreakIf::kArgsOperandOffset + next_iter_values.size()); + out_ << " ]"; + } + return std::nullopt; + }, + [&](const ir::TerminateInvocation*) { + out_ << StyleInstruction("terminate_invocation"); + return std::nullopt; + }, + [&](Default) { + out_ << StyleError("unknown terminator ", term->TypeInfo().name); + return std::nullopt; + }); + + if (args_offset) { + EmitOperandList(term, *args_offset); + } + + sm.Store(term); + + tint::Switch( + term, // + [&](const ir::BreakIf* bi) { + out_ << " " + << StyleComment("# -> [t: exit_loop ", NameOf(bi->Loop()), + ", f: ", NameOf(bi->Loop() ? bi->Loop()->Body() : nullptr), "]"); + }, + [&](const ir::Continue* c) { + out_ << " " + << StyleComment("# -> ", NameOf(c->Loop() ? c->Loop()->Continuing() : nullptr)); + }, // + [&](const ir::ExitIf* e) { out_ << " " << StyleComment("# ", NameOf(e->If())); }, // + [&](const ir::ExitSwitch* e) { + out_ << " " << StyleComment("# ", NameOf(e->Switch())); + }, // + [&](const ir::ExitLoop* e) { out_ << " " << StyleComment("# ", NameOf(e->Loop())); }, // + [&](const ir::NextIteration* ni) { + out_ << " " + << StyleComment("# -> ", NameOf(ni->Loop() ? ni->Loop()->Body() : nullptr)); + }); +} + +void Disassembler::EmitBinary(const Binary* b) { + SourceMarker sm(this); + EmitValueWithType(b); + out_ << " = " << NameOf(b->Op()); + EmitOperandList(b); + + sm.Store(b); +} + +void Disassembler::EmitUnary(const Unary* u) { + SourceMarker sm(this); + EmitValueWithType(u); + out_ << " = " << NameOf(u->Op()); + EmitOperandList(u); + + sm.Store(u); +} + +void Disassembler::EmitStructDecl(const core::type::Struct* str) { + out_ << StyleType(str->Name().Name()) << " = " << StyleKeyword("struct") << " " + << StyleAttribute("@align") << "(" << StyleLiteral(str->Align()) << ")"; + for (auto flag : str->StructFlags()) { + switch (flag) { + case core::type::kBlock: + out_ << ", " << StyleAttribute("@block"); + break; + case core::type::kExplicitLayout: + out_ << ", " << StyleAttribute("@core.explicit_layout"); + break; + } + } + out_ << " {"; + EmitLine(); + for (auto* member : str->Members()) { + out_ << " " << StyleVariable(member->Name().Name()) << ":" << NameOf(member->Type()); + out_ << " " << StyleAttribute("@offset") << "(" << StyleLiteral(member->Offset()) << ")"; + if (member->Size() != member->Type()->Size()) { + out_ << " " << StyleAttribute("@size") << "(" << StyleLiteral(member->Size()) << ")"; + } + if (member->Attributes().invariant) { + out_ << ", " << StyleAttribute("@invariant"); + } + if (member->Attributes().location.has_value()) { + out_ << ", " << StyleAttribute("@location") << "(" + << StyleLiteral(member->Attributes().location.value()) << ")"; + } + if (member->Attributes().blend_src.has_value()) { + out_ << ", " << StyleAttribute("@blend_src") << "(" + << StyleLiteral(member->Attributes().blend_src.value()) << ")"; + } + if (member->Attributes().color.has_value()) { + out_ << ", " << StyleAttribute("@color") << "(" + << StyleLiteral(member->Attributes().color.value()) << ")"; + } + if (member->Attributes().interpolation.has_value()) { + auto& interp = member->Attributes().interpolation.value(); + out_ << ", " << StyleAttribute("@interpolate") << "(" << StyleEnum(interp.type); + if (interp.sampling != core::InterpolationSampling::kUndefined) { + out_ << ", " << StyleEnum(interp.sampling); + } + out_ << ")"; + } + if (member->Attributes().builtin.has_value()) { + out_ << ", " << StyleAttribute("@builtin") << "(" + << StyleLiteral(member->Attributes().builtin.value()) << ")"; + } + if (member->Attributes().binding_point.has_value()) { + out_ << ", "; + EmitBindingPoint(member->Attributes().binding_point.value()); + } + if (member->RowMajor()) { + out_ << ", " << StyleAttribute("@row_major"); + } + if (member->HasMatrixStride()) { + out_ << ", " << StyleAttribute("@matrix_stride") << "(" + << StyleLiteral(member->MatrixStride()) << ")"; + } + EmitLine(); + } + out_ << "}"; + EmitLine(); + EmitLine(); +} + +StyledText Disassembler::NameOf(const core::type::Type* ty) { + if (!ty) { + return StyledText{} << StyleError("undef"); + } + + auto ary_emit = [&](StyledText& out, const core::type::Array* ary, + const core::ir::type::ValueArrayCount* cnt) -> void { + out << "array<" << ary->ElemType()->FriendlyName() << ", " << NameOf(cnt->value) << ">"; + }; + + if (auto* ptr = ty->As()) { + if (auto* ary = ty->UnwrapPtr()->As()) { + if (auto* cnt = ary->Count()->As()) { + auto out = StyledText{} << "ptr<"; + if (ptr->AddressSpace() != core::AddressSpace::kUndefined) { + out << ptr->AddressSpace() << ", "; + } + ary_emit(out, ary, cnt); + out << ", " << ptr->Access() << ">"; + + return out; + } + } + } else if (auto* ary = ty->UnwrapPtr()->As()) { + if (auto* cnt = ary->Count()->As()) { + auto out = StyledText{}; + ary_emit(out, ary, cnt); + return out; + } + } + + return StyledText{} << StyleType(ty->FriendlyName()); +} + +StyledText Disassembler::NameOf(const Block* node) { + if (!node) { + return StyledText{} << StyleError("undef"); + } + + auto id = block_ids_.GetOrAdd(node, [&] { return block_ids_.Count(); }); + return StyledText{} << StyleLabel("$B", id); +} + +StyledText Disassembler::NameOf(const Value* value) { + if (!value) { + return StyledText{} << StyleError("undef"); + } + + auto id = value_ids_.GetOrAdd(value, [&] { + if (auto sym = mod_.NameOf(value)) { + if (ids_.Add(sym.Name())) { + return sym.Name(); + } + auto prefix = sym.Name() + "_"; + for (size_t i = 1;; i++) { + auto name = prefix + std::to_string(i); + if (ids_.Add(name)) { + return name; + } + } + } + return std::to_string(value_ids_.Count()); + }); + + auto style = tint::Switch( + value, // + [&](const Function*) { return StyleFunction; }, // + [&](const InstructionResult*) { return StyleVariable; }); + return StyledText{} << style("%", id); +} + +StyledText Disassembler::NameOf(const If* inst) { + if (!inst) { + return StyledText{} << StyleError("undef"); + } + + auto name = if_names_.GetOrAdd( + inst, [&] { return inst->FriendlyName() + "_" + std::to_string(if_names_.Count()); }); + return StyledText{} << StyleInstruction(name); +} + +StyledText Disassembler::NameOf(const Loop* inst) { + if (!inst) { + return StyledText{} << StyleError("undef"); + } + + auto name = + loop_names_.GetOrAdd(inst, [&] { return "loop_" + std::to_string(loop_names_.Count()); }); + return StyledText{} << StyleInstruction(name); +} + +StyledText Disassembler::NameOf(const Switch* inst) { + if (!inst) { + return StyledText{} << StyleError("undef"); + } + + auto name = switch_names_.GetOrAdd( + inst, [&] { return "switch_" + std::to_string(switch_names_.Count()); }); + return StyledText{} << StyleInstruction(name); +} + +StyledText Disassembler::NameOf(BinaryOp op) { + switch (op) { + case BinaryOp::kAdd: + return StyledText{} << StyleInstruction("add"); + case BinaryOp::kSubtract: + return StyledText{} << StyleInstruction("sub"); + case BinaryOp::kMultiply: + return StyledText{} << StyleInstruction("mul"); + case BinaryOp::kDivide: + return StyledText{} << StyleInstruction("div"); + case BinaryOp::kModulo: + return StyledText{} << StyleInstruction("mod"); + case BinaryOp::kAnd: + return StyledText{} << StyleInstruction("and"); + case BinaryOp::kOr: + return StyledText{} << StyleInstruction("or"); + case BinaryOp::kXor: + return StyledText{} << StyleInstruction("xor"); + case BinaryOp::kEqual: + return StyledText{} << StyleInstruction("eq"); + case BinaryOp::kNotEqual: + return StyledText{} << StyleInstruction("neq"); + case BinaryOp::kLessThan: + return StyledText{} << StyleInstruction("lt"); + case BinaryOp::kGreaterThan: + return StyledText{} << StyleInstruction("gt"); + case BinaryOp::kLessThanEqual: + return StyledText{} << StyleInstruction("lte"); + case BinaryOp::kGreaterThanEqual: + return StyledText{} << StyleInstruction("gte"); + case BinaryOp::kShiftLeft: + return StyledText{} << StyleInstruction("shl"); + case BinaryOp::kShiftRight: + return StyledText{} << StyleInstruction("shr"); + case BinaryOp::kLogicalAnd: + return StyledText{} << StyleInstruction("logical-and"); + case BinaryOp::kLogicalOr: + return StyledText{} << StyleInstruction("logical-or"); + } + TINT_UNREACHABLE() << op; +} + +StyledText Disassembler::NameOf(UnaryOp op) { + switch (op) { + case UnaryOp::kComplement: + return StyledText{} << StyleInstruction("complement"); + case UnaryOp::kNegation: + return StyledText{} << StyleInstruction("negation"); + case UnaryOp::kAddressOf: + return StyledText{} << StyleInstruction("ref-to-ptr"); + case UnaryOp::kIndirection: + return StyledText{} << StyleInstruction("ptr-to-ref"); + case UnaryOp::kNot: + return StyledText{} << StyleInstruction("not"); + } + TINT_UNREACHABLE() << op; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/disassembler.h b/3rdparty/dawn/src/tint/lang/core/ir/disassembler.h new file mode 100644 index 000000000..cec6f41ce --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/disassembler.h @@ -0,0 +1,286 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_ +#define SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_ + +#include +#include +#include + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/block_param.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/unary.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/text/styled_text.h" + +// Forward declarations. +namespace tint::core::type { +class Struct; +} + +namespace tint::core::ir { + +/// Disassembler is responsible for creating the disassembly of an IR module. +class Disassembler { + public: + /// A reference to an instruction's operand or result. + struct IndexedValue { + /// The instruction that is using the value; + const Instruction* instruction = nullptr; + /// The index of the operand that is the value being used. + size_t index = 0u; + + /// @returns the hash code of the IndexedValue + tint::HashCode HashCode() const { return Hash(instruction, index); } + + /// An equality helper for IndexedValue. + /// @param other the IndexedValue to compare against + /// @returns true if the two IndexedValues are equal + bool operator==(const IndexedValue& other) const { + return instruction == other.instruction && index == other.index; + } + }; + + /// Constructor. + /// Performs the disassembly of the module @p mod, constructing a Source::File with the name @p + /// file_name. + /// @param mod the module to disassemble + explicit Disassembler(const Module& mod); + + /// Move constructor + Disassembler(Disassembler&&); + + /// Destructor + ~Disassembler(); + + /// @returns the string representation of the module + const StyledText& Text() const { return out_; } + + /// @returns the string representation of the module as plain-text + std::string Plain() const { return out_.Plain(); } + + /// @returns the disassembly file + const std::shared_ptr& File() const { return file_; } + + /// @returns the disassembled name for the Type @p ty + StyledText NameOf(const core::type::Type* ty); + + /// @returns the disassembled name for the Block @p blk + StyledText NameOf(const Block* blk); + + /// @returns the disassembled name for the Value @p node + StyledText NameOf(const Value* node); + + /// @returns the disassembled name for the If @p inst + StyledText NameOf(const If* inst); + + /// @returns the disassembled name for the Loop @p inst + StyledText NameOf(const Loop* inst); + + /// @returns the disassembled name for the Switch @p inst + StyledText NameOf(const Switch* inst); + + /// @returns the disassembled name for the BinaryOp @p op + StyledText NameOf(BinaryOp op); + + /// @returns the disassembled name for the UnaryOp @p op + StyledText NameOf(UnaryOp op); + + /// @param inst the instruction to retrieve + /// @returns the source for the instruction + Source InstructionSource(const Instruction* inst) const { + return instruction_to_src_.GetOr(inst, Source{}); + } + + /// @param operand the operand to retrieve + /// @returns the source for the operand + Source OperandSource(IndexedValue operand) const { + return operand_to_src_.GetOr(operand, Source{}); + } + + /// @param result the result to retrieve + /// @returns the source for the result + Source ResultSource(IndexedValue result) const { + return result_to_src_.GetOr(result, Source{}); + } + + /// @param blk the block to retrieve + /// @returns the source for the block + Source BlockSource(const Block* blk) const { return block_to_src_.GetOr(blk, Source{}); } + + /// @param param the block parameter to retrieve + /// @returns the source for the parameter + Source BlockParamSource(const BlockParam* param) { + return block_param_to_src_.GetOr(param, Source{}); + } + + /// @param func the function to retrieve + /// @returns the source for the function + Source FunctionSource(const Function* func) { return function_to_src_.GetOr(func, Source{}); } + + /// @param param the function parameter to retrieve + /// @returns the source for the parameter + Source FunctionParamSource(const FunctionParam* param) { + return function_param_to_src_.GetOr(param, Source{}); + } + + private: + class SourceMarker { + public: + explicit SourceMarker(Disassembler* d) : dis_(d), begin_(dis_->MakeCurrentLocation()) {} + ~SourceMarker() = default; + + void Store(const Instruction* inst) { dis_->SetSource(inst, MakeSource()); } + + void Store(const Block* blk) { dis_->SetSource(blk, MakeSource()); } + + void Store(const BlockParam* param) { dis_->SetSource(param, MakeSource()); } + + void Store(const Function* func) { dis_->SetSource(func, MakeSource()); } + + void Store(const FunctionParam* param) { dis_->SetSource(param, MakeSource()); } + + void Store(IndexedValue operand) { dis_->SetSource(operand, MakeSource()); } + + void StoreResult(IndexedValue result) { dis_->SetResultSource(result, MakeSource()); } + + Source MakeSource() const { + return Source(Source::Range(begin_, dis_->MakeCurrentLocation())); + } + + private: + Disassembler* dis_ = nullptr; + Source::Location begin_; + }; + + /// Performs the disassembling of the module. + void Disassemble(); + + /// Stores the given @p src location for @p inst instruction + /// @param inst the instruction to store + /// @param src the source location + void SetSource(const Instruction* inst, Source src) { instruction_to_src_.Add(inst, src); } + + /// Stores the given @p src location for @p blk block + /// @param blk the block to store + /// @param src the source location + void SetSource(const Block* blk, Source src) { block_to_src_.Add(blk, src); } + + /// Stores the given @p src location for @p param block parameter + /// @param param the block parameter to store + /// @param src the source location + void SetSource(const BlockParam* param, Source src) { block_param_to_src_.Add(param, src); } + + /// Stores the given @p src location for @p func function + /// @param func the function to store + /// @param src the source location + void SetSource(const Function* func, Source src) { function_to_src_.Add(func, src); } + + /// Stores the given @p src location for @p param function parameter + /// @param param the function parameter to store + /// @param src the source location + void SetSource(const FunctionParam* param, Source src) { + function_param_to_src_.Add(param, src); + } + + /// Stores the given @p src location for @p op operand + /// @param op the operand to store + /// @param src the source location + void SetSource(IndexedValue op, Source src) { operand_to_src_.Add(op, src); } + + /// Stores the given @p src location for @p result + /// @param result the result to store + /// @param src the source location + void SetResultSource(IndexedValue result, Source src) { result_to_src_.Add(result, src); } + + /// @returns the source location for the current emission location + Source::Location MakeCurrentLocation(); + + StyledText& Indent(); + + void EmitBlock(const Block* blk, std::string_view comment = ""); + void EmitFunction(const Function* func); + void EmitParamAttributes(const FunctionParam* p); + void EmitReturnAttributes(const Function* func); + void EmitBindingPoint(BindingPoint p); + void EmitInputAttachmentIndex(uint32_t i); + void EmitInterpolation(Interpolation interp); + void EmitInstruction(const Instruction* inst); + void EmitValueWithType(const Instruction* val); + void EmitValueWithType(const Value* val); + StyledText ValueToStyledText(const Value* val); + void EmitValue(const Value* val); + void EmitBinary(const Binary* b); + void EmitUnary(const Unary* b); + void EmitTerminator(const Terminator* b); + void EmitSwitch(const Switch* s); + void EmitLoop(const Loop* l); + void EmitIf(const If* i); + void EmitStructDecl(const core::type::Struct* str); + void EmitLine(); + void EmitOperand(const Instruction* inst, size_t index); + void EmitOperandList(const Instruction* inst, size_t start_index = 0); + void EmitOperandList(const Instruction* inst, size_t start_index, size_t count); + void EmitInstructionName(const Instruction* inst); + + const Module& mod_; + StyledText out_; + std::shared_ptr file_; + uint32_t indent_size_ = 0; + bool in_function_ = false; + + uint32_t current_output_line_ = 1; + uint32_t current_output_start_pos_ = 0; + + Hashmap block_to_src_; + Hashmap block_param_to_src_; + Hashmap instruction_to_src_; + Hashmap operand_to_src_; + Hashmap result_to_src_; + Hashmap function_to_src_; + Hashmap function_param_to_src_; + + // Names / IDs + Hashmap block_ids_; + Hashmap value_ids_; + Hashmap if_names_; + Hashmap loop_names_; + Hashmap switch_names_; + Hashset ids_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/discard.cc b/3rdparty/dawn/src/tint/lang/core/ir/discard.cc new file mode 100644 index 000000000..5cab0fe54 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/discard.cc @@ -0,0 +1,47 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/discard.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Discard); + +namespace tint::core::ir { + +Discard::Discard(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +Discard::~Discard() = default; + +Discard* Discard::Clone(CloneContext& ctx) { + return ctx.ir.CreateInstruction(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/discard.h b/3rdparty/dawn/src/tint/lang/core/ir/discard.h new file mode 100644 index 000000000..e348f8503 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/discard.h @@ -0,0 +1,62 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_DISCARD_H_ +#define SRC_TINT_LANG_CORE_IR_DISCARD_H_ + +#include + +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A discard instruction in the IR. +class Discard final : public Castable { + public: + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 0; + + /// The fixed number of operands expected for this instruction + static constexpr size_t kNumOperands = 0; + + /// Constructor + /// @param id the instruction id + explicit Discard(Id id); + + ~Discard() override; + + /// @copydoc Instruction::Clone() + Discard* Clone(CloneContext& ctx) override; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "discard"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_DISCARD_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/evaluator.cc b/3rdparty/dawn/src/tint/lang/core/ir/evaluator.cc new file mode 100644 index 000000000..609dcd60e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/evaluator.cc @@ -0,0 +1,382 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/evaluator.h" +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/function_param.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir { +namespace eval { + +diag::Result Eval(core::ir::Builder& b, core::ir::Instruction* inst) { + return Eval(b, inst->Result()); +} + +diag::Result Eval(core::ir::Builder& b, core::ir::Value* val) { + ir::Evaluator e(b); + return e.Evaluate(val); +} + +} // namespace eval + +Evaluator::Evaluator(ir::Builder& builder) + : b_(builder), const_eval_(b_.ir.constant_values, diagnostics_) {} + +Evaluator::~Evaluator() = default; + +diag::Result Evaluator::Evaluate(core::ir::Value* src) { + auto res = EvalValue(src); + if (res != Success) { + return diag::Failure(diagnostics_); + } + if (!res.Get()) { + return nullptr; + } + + return b_.Constant(res.Get()); +} + +diag::Diagnostic& Evaluator::AddError(Source src) { + diag::Diagnostic diag; + diag.source = src; + return diagnostics_.Add(diag); +} + +Source Evaluator::SourceOf(core::ir::Instruction* val) { + return b_.ir.SourceOf(val); +} + +Evaluator::EvalResult Evaluator::EvalValue(core::ir::Value* val) { + return tint::Switch( + val, // + [&](core::ir::Constant* c) { return c->Value(); }, + [&](core::ir::FunctionParam*) { return nullptr; }, + [&](core::ir::InstructionResult* r) { + return tint::Switch( + r->Instruction(), // + [&](core::ir::Bitcast* bc) { return EvalBitcast(bc); }, + [&](core::ir::Access* a) { return EvalAccess(a); }, + [&](core::ir::ConstExprIf* c) { return EvalConstExprIf(c); }, + [&](core::ir::Construct* c) { return EvalConstruct(c); }, + [&](core::ir::Convert* c) { return EvalConvert(c); }, + [&](core::ir::CoreBinary* cb) { return EvalBinary(cb); }, + [&](core::ir::CoreBuiltinCall* c) { return EvalCoreBuiltinCall(c); }, + [&](core::ir::CoreUnary* u) { return EvalUnary(u); }, + [&](core::ir::Override* o) { return EvalOverride(o); }, // + [&](core::ir::Swizzle* s) { return EvalSwizzle(s); }, // + [&](Default) { + // Treat any unknown instruction as a termination point for trying to eval. + return nullptr; + }); + }, + TINT_ICE_ON_NO_MATCH); +} + +Evaluator::EvalResult Evaluator::EvalBitcast(core::ir::Bitcast* bc) { + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(bc->Val())); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + + TINT_CHECK_RESULT_UNWRAP(r, + const_eval_.bitcast(bc->Result()->Type(), Vector{val}, SourceOf(bc))); + return r; +} + +Evaluator::EvalResult Evaluator::EvalAccess(core::ir::Access* a) { + TINT_CHECK_RESULT_UNWRAP(obj, EvalValue(a->Object())); + + auto* access_obj_type = a->Object()->Type()->UnwrapPtrOrRef(); + for (auto* idx : a->Indices()) { + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(idx)); + + // Check if the value could be evaluated + constexpr uint32_t kDefaultConstIndex = 0; + uint32_t index_const = kDefaultConstIndex; + if (val) { + TINT_ASSERT(val->Is()); + + TINT_CHECK_RESULT_UNWRAP(res, + const_eval_.Index(obj, access_obj_type, val, SourceOf(a))); + index_const = val->ValueAs(); + obj = res; + } else { + // No constant array evaluation possible for non-const (dynamic) indices. Only + // validation of bounds is possible at this stage. + obj = nullptr; + } + + // Index element to type to support type nested access. + access_obj_type = access_obj_type->Element(index_const); + TINT_ASSERT(access_obj_type); + } + return obj; +} + +Evaluator::EvalResult Evaluator::EvalConstruct(core::ir::Construct* c) { + auto table = core::intrinsic::Table(b_.ir.Types(), b_.ir.symbols); + + auto result_ty = c->Result()->Type(); + + Vector arg_types; + arg_types.Reserve(c->Args().Length()); + Vector arg_values; + arg_values.Reserve(c->Args().Length()); + + for (auto* arg : c->Args()) { + arg_types.Push(arg->Type()); + + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(arg)); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + arg_values.Push(val); + } + + auto mat_vec = [&](const core::type::Type* type, + core::intrinsic::CtorConv intrinsic) -> constant::Eval::Result { + auto op = + table.Lookup(intrinsic, Vector{type}, arg_types, core::EvaluationStage::kOverride); + if (op != Success) { + AddError(SourceOf(c)) << "unable to find intrinsic for construct: " << op.Failure(); + return Failure(); + } + if (!op->const_eval_fn) { + AddError(SourceOf(c)) << "unhandled type constructor"; + return Failure(); + } + TINT_CHECK_RESULT_UNWRAP( + r, (const_eval_.*op->const_eval_fn)(result_ty, arg_values, SourceOf(c))); + return r; + }; + + // Dispatch to the appropriate const eval function. + auto r = tint::Switch( + result_ty, // + [&](const core::type::Array*) { + return const_eval_.ArrayOrStructCtor(result_ty, arg_values); + }, + [&](const core::type::Struct*) { + return const_eval_.ArrayOrStructCtor(result_ty, arg_values); + }, + [&](const core::type::Vector* vec) { + return mat_vec(vec->Type(), core::intrinsic::VectorCtorConv(vec->Width())); + }, + [&](const core::type::Matrix* mat) { + return mat_vec(mat->Type(), + core::intrinsic::MatrixCtorConv(mat->Columns(), mat->Rows())); + }, + [&](Default) { + if (!result_ty->Is()) { + AddError(SourceOf(c)) << "unhandled type constructor"; + return core::constant::Eval::Result(nullptr); + } + // For scalars, this must be an identity constructor. + if (arg_values[0]->Type() != result_ty) { + AddError(SourceOf(c)) << "invalid type constructor"; + return core::constant::Eval::Result(nullptr); + } + return const_eval_.Identity(result_ty, arg_values, SourceOf(c)); + }); + + if (r != Success) { + return Failure(); + } + return r.Get(); +} + +Evaluator::EvalResult Evaluator::EvalConvert(core::ir::Convert* c) { + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(c->Args()[0])); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + TINT_CHECK_RESULT_UNWRAP(r, const_eval_.Convert(c->Result()->Type(), val, SourceOf(c))); + return r; +} + +Evaluator::EvalResult Evaluator::EvalOverride(core::ir::Override* o) { + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(o->Initializer())); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + return val; +} + +Evaluator::EvalResult Evaluator::EvalConstExprIf(core::ir::ConstExprIf* c) { + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(c->Condition())); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + bool branch_val = val->ValueAs(); + auto* inline_block = branch_val ? c->True() : c->False(); + + // Note: ConstExprIf must be limited to side effect boolean values for this evaluation to be + // correct. This is currently the case as ConstExprIf was created for the singular purpose of + // correctly semantically representing short circuiting operations (and/or). + TINT_CHECK_RESULT_UNWRAP(ret, EvalValue(inline_block->Terminator()->Args()[0])); + // Check if the value could be evaluated + if (!ret) { + return nullptr; + } + + return ret; +} + +Evaluator::EvalResult Evaluator::EvalSwizzle(core::ir::Swizzle* s) { + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(s->Object())); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + + TINT_CHECK_RESULT_UNWRAP(r, const_eval_.Swizzle(s->Result()->Type(), val, s->Indices())); + return r; +} + +Evaluator::EvalResult Evaluator::EvalUnary(core::ir::CoreUnary* u) { + intrinsic::Context context{u->TableData(), b_.ir.Types(), b_.ir.symbols}; + + auto overload = core::intrinsic::LookupUnary(context, u->Op(), u->Val()->Type(), + core::EvaluationStage::kOverride); + if (overload != Success) { + AddError(SourceOf(u)) << overload.Failure().Plain(); + return Failure(); + } + + auto const_eval_fn = overload->const_eval_fn; + if (!const_eval_fn) { + AddError(SourceOf(u)) << "invalid unary expression"; + return Failure(); + } + + auto val = EvalValue(u->Val()); + if (val != Success) { + return Failure(); + } + // Check if the value could be evaluated + if (!val.Get()) { + return nullptr; + } + + auto r = (const_eval_.*const_eval_fn)(u->Result()->Type(), Vector{val.Get()}, SourceOf(u)); + if (r != Success) { + return Failure(); + } + return r.Get(); +} + +Evaluator::EvalResult Evaluator::EvalBinary(core::ir::CoreBinary* cb) { + intrinsic::Context context{cb->TableData(), b_.ir.Types(), b_.ir.symbols}; + + auto overload = + core::intrinsic::LookupBinary(context, cb->Op(), cb->LHS()->Type(), cb->RHS()->Type(), + core::EvaluationStage::kOverride, /* is_compound */ false); + if (overload != Success) { + AddError(SourceOf(cb)) << overload.Failure().Plain(); + return Failure(); + } + + auto const_eval_fn = overload->const_eval_fn; + if (!const_eval_fn) { + AddError(SourceOf(cb)) << "invalid binary expression"; + return Failure(); + } + + TINT_CHECK_RESULT_UNWRAP(lhs, EvalValue(cb->LHS())); + // Check LHS could be evaluated + if (!lhs) { + return nullptr; + } + + // These short circuiting operators should not be present in the IR at any time. These need + // special handling and are transformed into ConstExprIfs on program construction. + TINT_ASSERT(cb->Op() != tint::core::BinaryOp::kLogicalAnd && + cb->Op() != tint::core::BinaryOp::kLogicalOr); + + TINT_CHECK_RESULT_UNWRAP(rhs, EvalValue(cb->RHS())); + // Check RHS could be evaluated + if (!rhs) { + return nullptr; + } + + TINT_CHECK_RESULT_UNWRAP( + r, (const_eval_.*const_eval_fn)(cb->Result()->Type(), Vector{lhs, rhs}, SourceOf(cb))); + return r; +} + +Evaluator::EvalResult Evaluator::EvalCoreBuiltinCall(core::ir::CoreBuiltinCall* c) { + intrinsic::Context context{c->TableData(), b_.ir.Types(), b_.ir.symbols}; + + Vector arg_types; + arg_types.Reserve(c->Args().Length()); + Vector args; + args.Reserve(c->Args().Length()); + for (auto* arg : c->Args()) { + arg_types.Push(arg->Type()); + + TINT_CHECK_RESULT_UNWRAP(val, EvalValue(arg)); + // Check if the value could be evaluated + if (!val) { + return nullptr; + } + args.Push(val); + } + + auto overload = core::intrinsic::LookupFn(context, c->FriendlyName().c_str(), c->FuncId(), + Empty, arg_types, core::EvaluationStage::kOverride); + if (overload != Success) { + AddError(SourceOf(c)) << overload.Failure(); + return Failure(); + } + + // If there is no `@const` override, we don't fail the eval, we return a nullptr. This is + // because we can call eval for things like `dpdx` which is not overridable but that's not an + // eval failure, we just don't eval. + auto const_eval_fn = overload->const_eval_fn; + if (!const_eval_fn) { + return nullptr; + } + + auto r = (const_eval_.*const_eval_fn)(c->Result()->Type(), args, SourceOf(c)); + if (r != Success) { + return Failure(); + } + return r.Get(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/evaluator.h b/3rdparty/dawn/src/tint/lang/core/ir/evaluator.h new file mode 100644 index 000000000..e8fe27a32 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/evaluator.h @@ -0,0 +1,99 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_EVALUATOR_H_ +#define SRC_TINT_LANG_CORE_IR_EVALUATOR_H_ + +#include "src/tint/lang/core/constant/eval.h" +#include "src/tint/lang/core/intrinsic/table.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_binary.h" +#include "src/tint/lang/core/ir/core_unary.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/value.h" + +namespace tint::core::ir { + +/// An evaluator to take a given `ir::Value` and return the result of evaluating the expression. +class Evaluator { + public: + /// Constructor + /// @param builder the ir builder + explicit Evaluator(ir::Builder& builder); + /// Destructor + ~Evaluator(); + + /// Evaluate the given `src` expression. + /// @param src the source expression + /// @returns the generated constant or a failure result. + diag::Result Evaluate(core::ir::Value* src); + + private: + using EvalResult = Result; + + diag::Diagnostic& AddError(Source src); + Source SourceOf(core::ir::Instruction* val); + + EvalResult EvalBitcast(core::ir::Bitcast* bc); + EvalResult EvalValue(core::ir::Value* val); + EvalResult EvalAccess(core::ir::Access* a); + EvalResult EvalConvert(core::ir::Convert* c); + EvalResult EvalConstruct(core::ir::Construct* c); + EvalResult EvalSwizzle(core::ir::Swizzle* s); + EvalResult EvalOverride(core::ir::Override* o); + EvalResult EvalUnary(core::ir::CoreUnary* u); + EvalResult EvalBinary(core::ir::CoreBinary* cb); + EvalResult EvalCoreBuiltinCall(core::ir::CoreBuiltinCall* c); + EvalResult EvalConstExprIf(core::ir::ConstExprIf* c); + + ir::Builder& b_; + diag::List diagnostics_; + core::constant::Eval const_eval_; +}; + +namespace eval { + +/// Evaluate the given `inst` with the provided `b`. +/// @param b the builder +/// @param inst the instruction +/// @returns the evaluated constant for `inst` or a `Failure` otherwise. +diag::Result Eval(core::ir::Builder& b, core::ir::Instruction* inst); + +/// Evaluate the given `val` with the provided `b`. +/// @param b the builder +/// @param val the value +/// @returns the evaluated constant for `val` or a `Failure` otherwise. +diag::Result Eval(core::ir::Builder& b, core::ir::Value* val); + +} // namespace eval + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_EVALUATOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit.cc b/3rdparty/dawn/src/tint/lang/core/ir/exit.cc new file mode 100644 index 000000000..c8ace8701 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit.cc @@ -0,0 +1,58 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/exit.h" + +#include "src/tint/lang/core/ir/control_instruction.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Exit); + +namespace tint::core::ir { + +Exit::Exit(Instruction::Id id) : Base(id) {} + +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::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit.h b/3rdparty/dawn/src/tint/lang/core/ir/exit.h new file mode 100644 index 000000000..607b538af --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_EXIT_H_ +#define SRC_TINT_LANG_CORE_IR_EXIT_H_ + +#include "src/tint/lang/core/ir/terminator.h" + +// Forward declarations +namespace tint::core::ir { +class ControlInstruction; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// The base class for all exit terminators. +class Exit : public Castable { + public: + /// Constructor + /// @param id the instruction id + explicit Exit(Instruction::Id id); + + ~Exit() override; + + /// @copydoc Value::Destroy + void Destroy() override; + + /// @return the control instruction that this exit is associated with + ir::ControlInstruction* ControlInstruction() { return ctrl_inst_; } + + /// @return the control instruction that this exit is associated with + const ir::ControlInstruction* ControlInstruction() const { return ctrl_inst_; } + + protected: + /// 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::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_EXIT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit_if.cc b/3rdparty/dawn/src/tint/lang/core/ir/exit_if.cc new file mode 100644 index 000000000..b10249f05 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit_if.cc @@ -0,0 +1,68 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/exit_if.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ExitIf); + +namespace tint::core::ir { + +ExitIf::ExitIf(Id id) : Base(id) {} + +ExitIf::ExitIf(Id id, ir::If* i, VectorRef args) : Base(id) { + SetIf(i); + AddOperands(ExitIf::kArgsOperandOffset, std::move(args)); +} + +ExitIf::~ExitIf() = default; + +ExitIf* ExitIf::Clone(CloneContext& ctx) { + auto* if_ = ctx.Remap(If()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(if_, args); +} + +void ExitIf::SetIf(ir::If* i) { + SetControlInstruction(i); +} + +ir::If* ExitIf::If() { + return static_cast(ControlInstruction()); +} + +const ir::If* ExitIf::If() const { + return static_cast(ControlInstruction()); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit_if.h b/3rdparty/dawn/src/tint/lang/core/ir/exit_if.h new file mode 100644 index 000000000..1b21176ec --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit_if.h @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_EXIT_IF_H_ +#define SRC_TINT_LANG_CORE_IR_EXIT_IF_H_ + +#include + +#include "src/tint/lang/core/ir/exit.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class If; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A exit if instruction. +class ExitIf final : public Castable { + public: + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// Constructor (no operands, no if) + /// @param id the instruction id + explicit ExitIf(Id id); + + /// Constructor + /// @param id the instruction id + /// @param i the if being exited + /// @param args the target MultiInBlock arguments + ExitIf(Id id, ir::If* i, VectorRef args = tint::Empty); + + ~ExitIf() override; + + /// @copydoc Instruction::Clone() + ExitIf* Clone(CloneContext& ctx) override; + + /// Re-associates the exit with the given if instruction + /// @param i the new If to exit from + void SetIf(ir::If* i); + + /// @returns the if being exited + ir::If* If(); + + /// @returns the if being exited + const ir::If* If() const; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "exit_if"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_EXIT_IF_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit_loop.cc b/3rdparty/dawn/src/tint/lang/core/ir/exit_loop.cc new file mode 100644 index 000000000..50b62cd66 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit_loop.cc @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/exit_loop.h" + +#include + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ExitLoop); + +namespace tint::core::ir { + +ExitLoop::ExitLoop(Id id) : Base(id) {} + +ExitLoop::ExitLoop(Id id, ir::Loop* loop, VectorRef args /* = tint::Empty */) : Base(id) { + SetLoop(loop); + AddOperands(ExitLoop::kArgsOperandOffset, std::move(args)); +} + +ExitLoop::~ExitLoop() = default; + +ExitLoop* ExitLoop::Clone(CloneContext& ctx) { + auto* loop = ctx.Remap(Loop()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(loop, args); +} + +void ExitLoop::SetLoop(ir::Loop* l) { + SetControlInstruction(l); +} + +ir::Loop* ExitLoop::Loop() { + return static_cast(ControlInstruction()); +} + +const ir::Loop* ExitLoop::Loop() const { + return static_cast(ControlInstruction()); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit_loop.h b/3rdparty/dawn/src/tint/lang/core/ir/exit_loop.h new file mode 100644 index 000000000..eb0bf1cca --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit_loop.h @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_EXIT_LOOP_H_ +#define SRC_TINT_LANG_CORE_IR_EXIT_LOOP_H_ + +#include + +#include "src/tint/lang/core/ir/exit.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Loop; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A exit loop instruction. +class ExitLoop final : public Castable { + public: + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// Constructor (no operands, no loop) + /// @param id the instruction id + explicit ExitLoop(Id id); + + /// Constructor + /// @param id the instruction id + /// @param loop the loop being exited + /// @param args the target MultiInBlock arguments + ExitLoop(Id id, ir::Loop* loop, VectorRef args = tint::Empty); + + ~ExitLoop() override; + + /// @copydoc Instruction::Clone() + ExitLoop* Clone(CloneContext& ctx) override; + + /// Re-associates the exit with the given loop instruction + /// @param l the new loop to exit from + void SetLoop(ir::Loop* l); + + /// @returns the loop being exited + ir::Loop* Loop(); + + /// @returns the loop being exited + const ir::Loop* Loop() const; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "exit_loop"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_EXIT_LOOP_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit_switch.cc b/3rdparty/dawn/src/tint/lang/core/ir/exit_switch.cc new file mode 100644 index 000000000..acbceb9f7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit_switch.cc @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/exit_switch.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/switch.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ExitSwitch); + +namespace tint::core::ir { + +ExitSwitch::ExitSwitch(Id id) : Base(id) {} + +ExitSwitch::ExitSwitch(Id id, ir::Switch* sw, VectorRef args /* = tint::Empty */) + : Base(id) { + SetSwitch(sw); + AddOperands(ExitSwitch::kArgsOperandOffset, std::move(args)); +} + +ExitSwitch::~ExitSwitch() = default; + +ExitSwitch* ExitSwitch::Clone(CloneContext& ctx) { + auto* switch_ = ctx.Remap(Switch()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(switch_, args); +} + +void ExitSwitch::SetSwitch(ir::Switch* s) { + SetControlInstruction(s); +} + +ir::Switch* ExitSwitch::Switch() { + return static_cast(ControlInstruction()); +} + +const ir::Switch* ExitSwitch::Switch() const { + return static_cast(ControlInstruction()); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/exit_switch.h b/3rdparty/dawn/src/tint/lang/core/ir/exit_switch.h new file mode 100644 index 000000000..93d5ce2c4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/exit_switch.h @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_EXIT_SWITCH_H_ +#define SRC_TINT_LANG_CORE_IR_EXIT_SWITCH_H_ + +#include + +#include "src/tint/lang/core/ir/exit.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Switch; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A exit switch instruction. +class ExitSwitch final : public Castable { + public: + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// Constructor (no operands, no switch) + /// @param id the instruction id + explicit ExitSwitch(Id id); + + /// Constructor + /// @param id the instruction id + /// @param sw the switch being exited + /// @param args the target MultiInBlock arguments + ExitSwitch(Id id, ir::Switch* sw, VectorRef args = tint::Empty); + + ~ExitSwitch() override; + + /// @copydoc Instruction::Clone() + ExitSwitch* Clone(CloneContext& ctx) override; + + /// Re-associates the exit with the given switch instruction + /// @param s the new switch to exit from + void SetSwitch(ir::Switch* s); + + /// @returns the switch being exited + ir::Switch* Switch(); + + /// @returns the switch being exited + const ir::Switch* Switch() const; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "exit_switch"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_EXIT_SWITCH_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/function.cc b/3rdparty/dawn/src/tint/lang/core/ir/function.cc new file mode 100644 index 000000000..7479ec1db --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/function.cc @@ -0,0 +1,120 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/function.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/containers/predicates.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Function); + +namespace tint::core::ir { + +Function::Function() : Base(nullptr) {} + +Function::Function(const core::type::Type* type, + const core::type::Type* rt, + PipelineStage stage, + std::optional> wg_size) + : Base(type), pipeline_stage_(stage), workgroup_size_(wg_size) { + TINT_ASSERT(rt != nullptr); + + return_.type = rt; +} + +Function::~Function() = default; + +Function* Function::Clone(CloneContext& ctx) { + auto* new_func = + ctx.ir.CreateValue(Type(), return_.type, pipeline_stage_, workgroup_size_); + new_func->block_ = ctx.ir.blocks.Create(); + new_func->SetParams(ctx.Clone<1>(params_.Slice())); + new_func->return_.attributes = return_.attributes; + + ctx.Replace(this, new_func); + block_->CloneInto(ctx, new_func->block_); + + if (auto name = ctx.ir.NameOf(this)) { + ctx.ir.SetName(new_func, name); + } + return new_func; +} + +void Function::SetParams(VectorRef params) { + for (auto* param : params_) { + param->SetFunction(nullptr); + } + params_ = std::move(params); + TINT_ASSERT(!params_.Any(IsNull)); + uint32_t index = 0; + for (auto* param : params_) { + param->SetFunction(this); + param->SetIndex(index++); + } +} + +void Function::SetParams(std::initializer_list params) { + for (auto* param : params_) { + param->SetFunction(nullptr); + } + params_ = params; + TINT_ASSERT(!params_.Any(IsNull)); + uint32_t index = 0; + for (auto* param : params_) { + param->SetFunction(this); + param->SetIndex(index++); + } +} + +void Function::AppendParam(FunctionParam* param) { + params_.Push(param); + param->SetFunction(this); + param->SetIndex(static_cast(params_.Length() - 1u)); +} + +void Function::Destroy() { + Base::Destroy(); + block_->Destroy(); +} + +std::string_view ToString(Function::PipelineStage value) { + switch (value) { + case Function::PipelineStage::kVertex: + return "vertex"; + case Function::PipelineStage::kFragment: + return "fragment"; + case Function::PipelineStage::kCompute: + return "compute"; + default: + break; + } + return ""; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/function.h b/3rdparty/dawn/src/tint/lang/core/ir/function.h new file mode 100644 index 000000000..eec67a993 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/function.h @@ -0,0 +1,276 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_FUNCTION_H_ +#define SRC_TINT_LANG_CORE_IR_FUNCTION_H_ + +#include +#include +#include + +#include "src/tint/lang/core/io_attributes.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/function_param.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/ice/ice.h" + +// Forward declarations +namespace tint::core::ir { +class Block; +class FunctionTerminator; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// An IR representation of a function +class Function : public Castable { + public: + /// The pipeline stage for an entry point + enum class PipelineStage { + /// Not a pipeline entry point + kUndefined, + /// Vertex + kCompute, + /// Fragment + kFragment, + /// Vertex + kVertex, + }; + + /// Constructor + Function(); + + /// Constructor + /// @param type the type of the function itself + /// @param rt the function return type + /// @param stage the function stage + /// @param wg_size the workgroup_size + Function(const core::type::Type* type, + const core::type::Type* rt, + PipelineStage stage = PipelineStage::kUndefined, + std::optional> wg_size = {}); + ~Function() override; + + /// @copydoc Instruction::Clone() + Function* Clone(CloneContext& ctx) override; + + /// Sets the function stage + /// @param stage the stage to set + void SetStage(PipelineStage stage) { pipeline_stage_ = stage; } + + /// @returns the function pipeline stage + PipelineStage Stage() const { return pipeline_stage_; } + + /// @returns true if the function is an entry point + bool IsEntryPoint() const { return pipeline_stage_ != PipelineStage::kUndefined; } + + /// @returns true if the function is a compute stage entry point + bool IsCompute() const { return pipeline_stage_ == PipelineStage::kCompute; } + + /// @returns true if the function is a fragment stage entry point + bool IsFragment() const { return pipeline_stage_ == PipelineStage::kFragment; } + + /// @returns true if the function is a vertex stage entry point + bool IsVertex() const { return pipeline_stage_ == PipelineStage::kVertex; } + + /// Sets the workgroup size + /// @param x the x size + /// @param y the y size + /// @param z the z size + void SetWorkgroupSize(Value* x, Value* y, Value* z) { workgroup_size_ = {x, y, z}; } + + /// Sets the workgroup size + /// @param size the new size + void SetWorkgroupSize(std::array size) { workgroup_size_ = size; } + + /// Clears the workgroup size. + void ClearWorkgroupSize() { workgroup_size_ = {}; } + + /// @returns the workgroup size information + std::optional> WorkgroupSize() const { return workgroup_size_; } + + /// @returns the workgroup size information as `uint32_t` values. Note, this requires the values + /// to all be constants. + std::optional> WorkgroupSizeAsConst() const { + if (!workgroup_size_.has_value()) { + return std::nullopt; + } + + auto& ary = workgroup_size_.value(); + auto* x = ary[0]->As(); + auto* y = ary[1]->As(); + auto* z = ary[2]->As(); + TINT_ASSERT(x && y && z); + + return {{ + x->Value()->ValueAs(), + y->Value()->ValueAs(), + z->Value()->ValueAs(), + }}; + } + + /// Sets the subgroup size + /// @param size the new subgroup size + void SetSubgroupSize(Value* size) { subgroup_size_ = size; } + + /// @returns the subgroup size information + std::optional SubgroupSize() const { return subgroup_size_; } + + /// @returns the subgroup size information as `uint32_t` values. Note, this requires the value + /// to be constant. + std::optional SubgroupSizeAsConst() const { + if (!subgroup_size_.has_value()) { + return std::nullopt; + } + + auto* value = subgroup_size_.value()->As(); + TINT_ASSERT(value); + + return value->Value()->ValueAs(); + } + + /// Clears the subgroup size. + void ClearSubgroupSize() { subgroup_size_ = {}; } + + /// @param type the return type for the function + void SetReturnType(const core::type::Type* type) { return_.type = type; } + + /// @returns the return type for the function + const core::type::Type* ReturnType() const { return return_.type; } + + /// Sets the return IO attributes. + /// @param attrs the attributes + void SetReturnAttributes(const IOAttributes& attrs) { return_.attributes = attrs; } + /// @returns the return IO attributes + const IOAttributes& ReturnAttributes() const { return return_.attributes; } + + /// Sets the return builtin attribute + /// @param builtin the builtin to set + void SetReturnBuiltin(BuiltinValue builtin) { + TINT_ASSERT(!return_.attributes.builtin.has_value()); + return_.attributes.builtin = builtin; + } + /// @returns the return builtin attribute + std::optional ReturnBuiltin() const { return return_.attributes.builtin; } + + /// Sets the return depth mode attribute + /// @param depth_mode the depth mode to set + void SetReturnDepthMode(BuiltinDepthMode depth_mode) { + TINT_ASSERT(!return_.attributes.depth_mode.has_value()); + return_.attributes.depth_mode = depth_mode; + } + + /// Sets the return location. + /// @param loc the optional location to set + void SetReturnLocation(std::optional loc) { return_.attributes.location = loc; } + + /// @returns the return location + std::optional ReturnLocation() const { return return_.attributes.location; } + + /// Sets the return interpolation. + /// @param interp the optional interpolation + void SetReturnInterpolation(std::optional interp) { + return_.attributes.interpolation = interp; + } + + /// @returns the return interpolation + std::optional ReturnInterpolation() const { + return return_.attributes.interpolation; + } + + /// Sets the return as invariant + /// @param val the invariant value to set + void SetReturnInvariant(bool val) { return_.attributes.invariant = val; } + + /// @returns the return invariant value + bool ReturnInvariant() const { return return_.attributes.invariant; } + + /// Sets the function parameters + /// @param params the function parameters + void SetParams(VectorRef params); + + /// Sets the function parameters + /// @param params the function parameters + void SetParams(std::initializer_list params); + + /// Appends a new function parameter. + /// @param param the function parameter to append + void AppendParam(FunctionParam* param); + + /// @returns the function parameters + const VectorRef Params() { return params_; } + + /// @returns the function parameters + VectorRef Params() const { return params_; } + + /// Sets the root block for the function + /// @param target the root block + void SetBlock(Block* target) { + TINT_ASSERT(target != nullptr); + block_ = target; + } + + /// @returns the function root block + ir::Block* Block() { return block_; } + + /// @returns the function root block + const ir::Block* Block() const { return block_; } + + /// Destroys the function and all of its instructions. + void Destroy() override; + + private: + PipelineStage pipeline_stage_ = PipelineStage::kUndefined; + std::optional> workgroup_size_; + std::optional subgroup_size_; + + struct { + const core::type::Type* type = nullptr; + IOAttributes attributes = {}; + } return_; + + Vector params_; + ir::Block* block_ = nullptr; +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(Function::PipelineStage value); + +/// @param out the stream to write to +/// @param value the Function::PipelineStage +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Function::PipelineStage value) { + return out << ToString(value); +} + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_FUNCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/function_param.cc b/3rdparty/dawn/src/tint/lang/core/ir/function_param.cc new file mode 100644 index 000000000..bb2f00a5f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/function_param.cc @@ -0,0 +1,54 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/function_param.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::FunctionParam); + +namespace tint::core::ir { + +FunctionParam::FunctionParam(const core::type::Type* ty) : Base(ty) {} + +FunctionParam::~FunctionParam() = default; + +FunctionParam* FunctionParam::Clone(CloneContext& ctx) { + auto* out = ctx.ir.CreateValue(Type()); + out->attributes_ = attributes_; + + auto name = ctx.ir.NameOf(this); + if (name.IsValid()) { + ctx.ir.SetName(out, name); + } + return out; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/function_param.h b/3rdparty/dawn/src/tint/lang/core/ir/function_param.h new file mode 100644 index 000000000..d39a59d11 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/function_param.h @@ -0,0 +1,149 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_FUNCTION_PARAM_H_ +#define SRC_TINT_LANG_CORE_IR_FUNCTION_PARAM_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/io_attributes.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Function; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A function parameter in the IR. +class FunctionParam : public Castable { + public: + /// Constructor + /// @param type the type of the var + explicit FunctionParam(const core::type::Type* type); + ~FunctionParam() override; + + /// Sets the function that this parameter belongs to. + /// @param func the function + void SetFunction(ir::Function* func) { func_ = func; } + + /// @returns the function that this parameter belongs to, or nullptr + ir::Function* Function() { return func_; } + + /// @returns the function that this parameter belongs to, or nullptr + const ir::Function* Function() const { return func_; } + + /// Sets the index of the parameter in the function's parameter list + /// @param index the index + void SetIndex(uint32_t index) { index_ = index; } + + /// @returns the index of the parameter in the function's parameter list + uint32_t Index() const { return index_; } + + /// @copydoc Value::Clone() + FunctionParam* Clone(CloneContext& ctx) override; + + /// Sets the IO attributes. + /// @param attrs the attributes + void SetAttributes(const IOAttributes& attrs) { attributes_ = attrs; } + + /// Resets the function attributes + void ResetAttributes() { attributes_ = {}; } + + /// @returns the IO attributes + const IOAttributes& Attributes() const { return attributes_; } + + /// Sets the builtin information. Note, it is currently an error if the builtin is already set. + /// @param val the builtin to set + void SetBuiltin(core::BuiltinValue val) { + TINT_ASSERT(!attributes_.builtin.has_value()); + attributes_.builtin = val; + } + /// @returns the builtin set for the parameter + std::optional Builtin() const { return attributes_.builtin; } + + /// Sets the parameter as invariant + /// @param val the value to set for invariant + void SetInvariant(bool val) { attributes_.invariant = val; } + + /// @returns true if parameter is invariant + bool Invariant() const { return attributes_.invariant; } + + /// Sets the location. + /// @param loc the optional location value + void SetLocation(std::optional loc) { attributes_.location = loc; } + + /// @returns the optional location attribute value + std::optional Location() const { return attributes_.location; } + + /// Sets the color. + /// @param col the optional color value + void SetColor(std::optional col) { attributes_.color = col; } + + /// @returns the optional color attribute value + std::optional Color() const { return attributes_.color; } + + /// Sets the interpolation. + /// @param interpolation the optional location interpolation settings + void SetInterpolation(std::optional interpolation) { + attributes_.interpolation = interpolation; + } + + /// @returns the optional interpolation attribute value + std::optional Interpolation() const { return attributes_.interpolation; } + + /// Sets the binding point + /// @param group the group + /// @param binding the binding + void SetBindingPoint(uint32_t group, uint32_t binding) { + attributes_.binding_point = {group, binding}; + } + + /// Sets the binding point + /// @param binding_point the binding point + void SetBindingPoint(std::optional binding_point) { + attributes_.binding_point = binding_point; + } + + /// @returns the binding points if `Attributes` contains `kBindingPoint` + std::optional BindingPoint() const { return attributes_.binding_point; } + + private: + ir::Function* func_ = nullptr; + uint32_t index_ = 0xffffffff; + IOAttributes attributes_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_FUNCTION_PARAM_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/if.cc b/3rdparty/dawn/src/tint/lang/core/ir/if.cc new file mode 100644 index 000000000..f4c413015 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/if.cc @@ -0,0 +1,111 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/if.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::If); + +namespace tint::core::ir { + +If::If(Id id) : Base(id) {} + +If::If(Id id, Value* cond, ir::Block* t, ir::Block* f) : Base(id), true_(t), false_(f) { + TINT_ASSERT(true_); + TINT_ASSERT(false_); + + AddOperand(If::kConditionOperandOffset, cond); + + if (true_) { + true_->SetParent(this); + } + if (false_) { + false_->SetParent(this); + } +} + +If::~If() = default; + +void If::ForeachBlock(const std::function& cb) { + if (true_) { + cb(true_); + } + if (false_) { + cb(false_); + } +} + +void If::ForeachBlock(const std::function& cb) const { + if (true_) { + cb(true_); + } + if (false_) { + cb(false_); + } +} + +If* If::Clone(CloneContext& ctx) { + auto* cond = ctx.Remap(Condition()); + auto* new_true = ctx.ir.blocks.Create(); + auto* new_false = ctx.ir.blocks.Create(); + + auto* new_if = ctx.ir.CreateInstruction(cond, new_true, new_false); + ctx.Replace(this, new_if); + + true_->CloneInto(ctx, new_true); + false_->CloneInto(ctx, new_false); + + new_if->SetResults(ctx.Clone(results_)); + + return new_if; +} + +void If::SetTrue(ir::Block* block) { + if (true_ && true_->Parent() == this) { + true_->SetParent(nullptr); + } + true_ = block; + if (block) { + block->SetParent(this); + } +} + +void If::SetFalse(ir::Block* block) { + if (false_ && false_->Parent() == this) { + false_->SetParent(nullptr); + } + false_ = block; + if (block) { + block->SetParent(this); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/if.h b/3rdparty/dawn/src/tint/lang/core/ir/if.h new file mode 100644 index 000000000..70a6992d6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/if.h @@ -0,0 +1,120 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_IF_H_ +#define SRC_TINT_LANG_CORE_IR_IF_H_ + +#include + +#include "src/tint/lang/core/ir/control_instruction.h" + +// Forward declarations +namespace tint::core::ir { +class MultiInBlock; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// If instruction. +/// +/// ``` +/// in +/// ┃ +/// ┏━━━━━━━━━━┻━━━━━━━━━━┓ +/// ▼ ▼ +/// ┌────────────┐ ┌────────────┐ +/// │ True │ │ False │ +/// | (optional) | | (optional) | +/// └────────────┘ └────────────┘ +/// ExitIf ┃ ┃ ExitIf +/// ┗━━━━━━━━━━┳━━━━━━━━━━┛ +/// ▼ +/// out +/// ``` +class If : public Castable { + public: + /// The number of supported operands + static constexpr size_t kNumOperands = 1; + /// The index of the condition operand + static constexpr size_t kConditionOperandOffset = 0; + + /// Constructor (no results, no operands, no blocks) + /// @param id the instruction id + explicit If(Id id); + + /// Constructor + /// @param cond the if condition + /// @param t the true block + /// @param f the false block + If(Id id, Value* cond, ir::Block* t, ir::Block* f); + + ~If() override; + + /// @copydoc Instruction::Clone() + If* Clone(CloneContext& ctx) override; + + /// @copydoc ControlInstruction::ForeachBlock + void ForeachBlock(const std::function& cb) override; + + /// @copydoc ControlInstruction::ForeachBlock + void ForeachBlock(const std::function& cb) const override; + + /// @returns the if condition + Value* Condition() { return Operand(kConditionOperandOffset); } + + /// @returns the if condition + const Value* Condition() const { return Operand(kConditionOperandOffset); } + + /// @returns the true block + ir::Block* True() { return true_; } + + /// @returns the true block + const ir::Block* True() const { return true_; } + + /// @param block the new true block + void SetTrue(ir::Block* block); + + /// @returns the false block + ir::Block* False() { return false_; } + + /// @returns the false block + const ir::Block* False() const { return false_; } + + /// @param block the new false block + void SetFalse(ir::Block* block); + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "if"; } + + private: + ir::Block* true_ = nullptr; + ir::Block* false_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_IF_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/instruction.cc b/3rdparty/dawn/src/tint/lang/core/ir/instruction.cc new file mode 100644 index 000000000..1468fa566 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/instruction.cc @@ -0,0 +1,83 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/instruction.h" + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Instruction); + +namespace tint::core::ir { + +Instruction::Instruction(Id id) : id_(id) {} + +Instruction::~Instruction() = default; + +void Instruction::Destroy() { + TINT_ASSERT(Alive()); + if (Block()) { + Remove(); + } + for (auto* result : Results()) { + result->SetInstruction(nullptr); + result->Destroy(); + } + flags_.Add(Flag::kDead); +} + +void Instruction::InsertBefore(Instruction* before) { + TINT_ASSERT(before); + TINT_ASSERT(before->Block() != nullptr); + before->Block()->InsertBefore(before, this); +} + +void Instruction::InsertAfter(Instruction* after) { + TINT_ASSERT(after); + TINT_ASSERT(after->Block() != nullptr); + after->Block()->InsertAfter(after, this); +} + +void Instruction::ReplaceWith(Instruction* replacement) { + TINT_ASSERT(replacement); + TINT_ASSERT(Block() != nullptr); + Block()->Replace(this, replacement); +} + +void Instruction::Remove() { + TINT_ASSERT(Block() != nullptr); + Block()->Remove(this); +} + +InstructionResult* Instruction::DetachResult() { + TINT_ASSERT(Results().Length() == 1u); + auto* result = Results()[0]; + SetResults({}); + return result; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/instruction.h b/3rdparty/dawn/src/tint/lang/core/ir/instruction.h new file mode 100644 index 000000000..09f796980 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/instruction.h @@ -0,0 +1,225 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_INSTRUCTION_H_ +#define SRC_TINT_LANG_CORE_IR_INSTRUCTION_H_ + +#include + +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/utils/containers/enum_set.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Block; +class CloneContext; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// An instruction in the IR. +class Instruction : public Castable { + public: + using Id = uint32_t; + + /// Kinds of memory access the call will do. + enum class Access { + kLoad, + kStore, + }; + /// Accesses is a set of of Access + using Accesses = EnumSet; + + /// Destructor + ~Instruction() override; + + /// An equality helper for Instructions. + /// @param other the instruction to compare against + /// @returns true if the two instructions have matching IDs + bool operator==(const Instruction& other) const { return id_ == other.id_; } + + /// A comparison helper for Instruction. + /// @param other the instruction to compare against + /// @returns true if `this` is less then `other`. + bool operator<(const Instruction& other) const { return id_ < other.id_; } + + /// 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 VectorRef Operands() = 0; + + /// @returns the operands of the instruction + virtual VectorRef Operands() const = 0; + + /// Replaces the operands of the instruction + /// @param operands the new operands of the instruction + virtual void SetOperands(VectorRef operands) = 0; + + /// Replaces the results of the instruction with a single result + /// @param result the new result of the instruction + virtual void SetResult(ir::InstructionResult* result) = 0; + + /// Replaces the results of the instruction + /// @param results the new results of the instruction + virtual void SetResults(VectorRef results) = 0; + + /// @returns the result values for this instruction + virtual VectorRef Results() = 0; + + /// @returns the result values for this instruction + virtual VectorRef Results() const = 0; + + /// Removes the instruction from the block, and destroys all the result values. + /// The result values must not be in use. + virtual void Destroy(); + + /// @returns the friendly name for the instruction + virtual std::string FriendlyName() const = 0; + + /// @param ctx the CloneContext used to clone this instruction + /// @returns a clone of this instruction + virtual Instruction* Clone(CloneContext& ctx) = 0; + + /// @returns the side effects for this instruction + virtual Accesses GetSideEffects() const { return Accesses{}; } + + /// @returns true if the Instruction has not been destroyed with Destroy() + bool Alive() const { return !flags_.Contains(Flag::kDead); } + + /// @returns true if the Instruction is sequenced. Sequenced instructions cannot be implicitly + /// reordered with other sequenced instructions. + bool Sequenced() const { return flags_.Contains(Flag::kSequenced); } + + /// Sets the block that owns this instruction + /// @param block the new owner block + void SetBlock(ir::Block* block) { block_ = block; } + + /// @returns the block that owns this instruction + ir::Block* Block() { return block_; } + + /// @returns the block that owns this instruction + const ir::Block* Block() const { return block_; } + + /// Adds the new instruction before the given instruction in the owning block + /// @param before the instruction to insert before + void InsertBefore(Instruction* before); + /// Adds the new instruction after the given instruction in the owning block + /// @param after the instruction to insert after + void InsertAfter(Instruction* after); + /// Replaces this instruction with @p replacement in the owning block owning this instruction + /// @param replacement the instruction to replace with + void ReplaceWith(Instruction* replacement); + /// Removes this instruction from the owning block + void Remove(); + + /// Detach an instruction result from this instruction. + /// @returns the instruction result that was detached + InstructionResult* DetachResult(); + + /// @param idx the index of the operand + /// @returns the operand with index @p idx, or `nullptr` if there are no operands or the index + /// is out of bounds. + Value* Operand(size_t idx) { + auto res = Operands(); + return idx < res.Length() ? res[idx] : nullptr; + } + + /// @param idx the index of the operand + /// @returns the operand with index @p idx, or `nullptr` if there are no operands or the index + /// is out of bounds. + const Value* Operand(size_t idx) const { + auto res = Operands(); + return idx < res.Length() ? res[idx] : nullptr; + } + + /// @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. + InstructionResult* Result(size_t idx) { + auto res = Results(); + return idx < res.Length() ? res[idx] : nullptr; + } + + /// @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. + const InstructionResult* Result(size_t idx) const { + auto res = Results(); + return idx < res.Length() ? res[idx] : nullptr; + } + + /// @returns the instruction result + /// @note must only be called on instructions with exactly one result + InstructionResult* Result() { + auto res = Results(); + TINT_ASSERT(res.Length() == 1u); + return res[0]; + } + + /// @returns the instruction result + /// @note must only be called on instructions with exactly one result + const InstructionResult* Result() const { + auto res = Results(); + TINT_ASSERT(res.Length() == 1u); + return res[0]; + } + + /// Pointer to the next instruction in the list + Instruction* next = nullptr; + /// Pointer to the previous instruction in the list + Instruction* prev = nullptr; + + protected: + /// Flags applied to an Instruction + enum class Flag { + /// The instruction has been destroyed + kDead, + /// The instruction must not be reordered with another sequenced instruction + kSequenced, + }; + + /// Constructor + explicit Instruction(Id id); + + /// The instruction id + Id id_; + + /// The block that owns this instruction + ir::Block* block_ = nullptr; + + /// Bitset of instruction flags + tint::EnumSet flags_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_INSTRUCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/instruction_result.cc b/3rdparty/dawn/src/tint/lang/core/ir/instruction_result.cc new file mode 100644 index 000000000..9eb99f774 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/instruction_result.cc @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/instruction_result.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::InstructionResult); + +namespace tint::core::ir { + +InstructionResult::InstructionResult(const core::type::Type* type) : Base(type) { + TINT_ASSERT(type != nullptr); +} + +InstructionResult::~InstructionResult() = default; + +void InstructionResult::Destroy() { + TINT_ASSERT(instruction_ == nullptr); + Base::Destroy(); +} + +InstructionResult* InstructionResult::Clone(CloneContext& ctx) { + // Do not clone the `Instruction`. It will be set when this result is placed in the new parent + // instruction. + return ctx.ir.CreateValue(Type()); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/instruction_result.h b/3rdparty/dawn/src/tint/lang/core/ir/instruction_result.h new file mode 100644 index 000000000..58fd8d2af --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/instruction_result.h @@ -0,0 +1,70 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_INSTRUCTION_RESULT_H_ +#define SRC_TINT_LANG_CORE_IR_INSTRUCTION_RESULT_H_ + +#include "src/tint/lang/core/ir/value.h" + +namespace tint::core::ir { + +/// An instruction result in the IR. +class InstructionResult : public Castable { + public: + /// Constructor + InstructionResult() : Base(nullptr) {} + + /// Constructor + /// @param type the type of the value + explicit InstructionResult(const core::type::Type* type); + + /// Destructor + ~InstructionResult() override; + + /// @copydoc Value::Destroy + void Destroy() override; + + /// @copydoc Value::Clone() + InstructionResult* Clone(CloneContext& ctx) override; + + /// Sets the instruction for this value + /// @param inst the instruction to set + void SetInstruction(Instruction* inst) { instruction_ = inst; } + + /// @returns the instruction, if any + ir::Instruction* Instruction() { return instruction_; } + + /// @returns the instruction, if any + const ir::Instruction* Instruction() const { return instruction_; } + + private: + ir::Instruction* instruction_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_INSTRUCTION_RESULT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/let.cc b/3rdparty/dawn/src/tint/lang/core/ir/let.cc new file mode 100644 index 000000000..443ab87c9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/let.cc @@ -0,0 +1,60 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/let.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/store.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Let); + +namespace tint::core::ir { + +Let::Let(Id id) : Base(id) {} + +Let::Let(Id id, InstructionResult* result, ir::Value* value) : Base(id) { + AddOperand(Let::kValueOperandOffset, value); + AddResult(result); +} + +Let::~Let() = default; + +Let* Let::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* val = ctx.Remap(Value()); + auto* new_let = ctx.ir.CreateInstruction(new_result, val); + + auto name = ctx.ir.NameOf(this); + if (name.IsValid()) { + ctx.ir.SetName(new_let, name.Name()); + } + + return new_let; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/let.h b/3rdparty/dawn/src/tint/lang/core/ir/let.h new file mode 100644 index 000000000..76ae7c6f9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/let.h @@ -0,0 +1,79 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_LET_H_ +#define SRC_TINT_LANG_CORE_IR_LET_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" + +namespace tint::core::ir { + +/// A no-op instruction in the IR, used to position and name a value +class Let final : public Castable> { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// The fixed number of results returned by let instructions + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands accepted by let instructions + static constexpr size_t kNumOperands = 1; + + /// Constructor (no result, no operands) + /// @param id the instruction id + explicit Let(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param value the let's value + Let(Id id, InstructionResult* result, Value* value); + + ~Let() override; + + /// @copydoc Instruction::Clone() + Let* Clone(CloneContext& ctx) override; + + /// @param value the new let value + void SetValue(ir::Value* value) { SetOperand(kValueOperandOffset, value); } + + /// @returns the value + ir::Value* Value() { return Operand(kValueOperandOffset); } + + /// @returns the value + const ir::Value* Value() const { return Operand(kValueOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "let"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_LET_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/load.cc b/3rdparty/dawn/src/tint/lang/core/ir/load.cc new file mode 100644 index 000000000..7f9455b3c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/load.cc @@ -0,0 +1,66 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/load.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Load); + +namespace tint::core::ir { + +Load::Load(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +Load::Load(Id id, InstructionResult* result, Value* from) : Base(id) { + flags_.Add(Flag::kSequenced); + + AddOperand(Load::kFromOperandOffset, from); + AddResult(result); +} + +Load::~Load() = default; + +Load* Load::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* from = ctx.Remap(From()); + return ctx.ir.CreateInstruction(new_result, from); +} + +core::ir::Instruction::Accesses Load::GetSideEffects() const { + // Always inline things in the `handle` address space + if (From()->Type()->As()->AddressSpace() == core::AddressSpace::kHandle) { + return Instruction::Accesses{}; + } + return Instruction::Accesses{Instruction::Access::kLoad}; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/load.h b/3rdparty/dawn/src/tint/lang/core/ir/load.h new file mode 100644 index 000000000..9181a4c51 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/load.h @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_LOAD_H_ +#define SRC_TINT_LANG_CORE_IR_LOAD_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A load instruction in the IR. +class Load final : public Castable> { + public: + /// The offset in Operands() for the from value + static constexpr size_t kFromOperandOffset = 0; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands used by this instruction + static constexpr size_t kNumOperands = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Load(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param from the value being loaded from + Load(Id id, InstructionResult* result, Value* from); + + ~Load() override; + + /// @copydoc Instruction::Clone() + Load* Clone(CloneContext& ctx) override; + + /// @returns the value being loaded from + Value* From() { return Operand(kFromOperandOffset); } + + /// @returns the value being loaded from + const Value* From() const { return Operand(kFromOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "load"; } + + /// @returns the side effects for this instruction + Accesses GetSideEffects() const override; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_LOAD_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.cc b/3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.cc new file mode 100644 index 000000000..a29f995a3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.cc @@ -0,0 +1,62 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/load_vector_element.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::LoadVectorElement); + +namespace tint::core::ir { + +LoadVectorElement::LoadVectorElement(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +LoadVectorElement::LoadVectorElement(Id id, + InstructionResult* result, + ir::Value* from, + ir::Value* index) + : Base(id) { + flags_.Add(Flag::kSequenced); + + AddOperand(LoadVectorElement::kFromOperandOffset, from); + AddOperand(LoadVectorElement::kIndexOperandOffset, index); + AddResult(result); +} + +LoadVectorElement::~LoadVectorElement() = default; + +LoadVectorElement* LoadVectorElement::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* from = ctx.Remap(From()); + auto* index = ctx.Remap(Index()); + return ctx.ir.CreateInstruction(new_result, from, index); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.h b/3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.h new file mode 100644 index 000000000..d1f3adb8c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/load_vector_element.h @@ -0,0 +1,90 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_LOAD_VECTOR_ELEMENT_H_ +#define SRC_TINT_LANG_CORE_IR_LOAD_VECTOR_ELEMENT_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A load instruction for a single vector element in the IR. +class LoadVectorElement final : public Castable> { + public: + /// The offset in Operands() for the `from` value + static constexpr size_t kFromOperandOffset = 0; + + /// The offset in Operands() for the `index` value + static constexpr size_t kIndexOperandOffset = 1; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands used by this instruction + static constexpr size_t kNumOperands = 2; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit LoadVectorElement(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param from the vector pointer + /// @param index the new vector element index + LoadVectorElement(Id id, InstructionResult* result, ir::Value* from, ir::Value* index); + + ~LoadVectorElement() override; + + /// @copydoc Instruction::Clone() + LoadVectorElement* Clone(CloneContext& ctx) override; + + /// @returns the vector pointer value + ir::Value* From() { return Operand(kFromOperandOffset); } + + /// @returns the vector pointer value + const ir::Value* From() const { return Operand(kFromOperandOffset); } + + /// @returns the new vector element index + ir::Value* Index() { return Operand(kIndexOperandOffset); } + + /// @returns the new vector element index + const ir::Value* Index() const { return Operand(kIndexOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "load_vector_element"; } + + /// @returns the side effects for this instruction + Accesses GetSideEffects() const override { return Accesses{Access::kLoad}; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_LOAD_VECTOR_ELEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/loop.cc b/3rdparty/dawn/src/tint/lang/core/ir/loop.cc new file mode 100644 index 000000000..20cb75aac --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/loop.cc @@ -0,0 +1,139 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/loop.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Loop); + +namespace tint::core::ir { + +Loop::Loop(Id id) : Base(id) {} + +Loop::Loop(Id id, ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c) + : Base(id), initializer_(i), body_(b), continuing_(c) { + TINT_ASSERT(initializer_); + TINT_ASSERT(body_); + TINT_ASSERT(continuing_); + + if (initializer_) { + initializer_->SetParent(this); + } + if (body_) { + body_->SetParent(this); + } + if (continuing_) { + continuing_->SetParent(this); + } +} + +Loop::~Loop() = default; + +Loop* Loop::Clone(CloneContext& ctx) { + auto* new_init = ctx.ir.blocks.Create(); + auto* new_body = ctx.ir.blocks.Create(); + auto* new_continuing = ctx.ir.blocks.Create(); + + auto* new_loop = ctx.ir.CreateInstruction(new_init, new_body, new_continuing); + ctx.Replace(this, new_loop); + + initializer_->CloneInto(ctx, new_init); + body_->CloneInto(ctx, new_body); + continuing_->CloneInto(ctx, new_continuing); + + new_loop->SetResults(ctx.Clone(results_)); + + return new_loop; +} + +void Loop::ForeachBlock(const std::function& cb) { + if (initializer_) { + cb(initializer_); + } + if (body_) { + cb(body_); + } + if (continuing_) { + cb(continuing_); + } +} + +void Loop::ForeachBlock(const std::function& cb) const { + if (initializer_) { + cb(initializer_); + } + if (body_) { + cb(body_); + } + if (continuing_) { + cb(continuing_); + } +} + +bool Loop::HasInitializer() const { + return initializer_->Terminator() != nullptr; +} + +void Loop::SetInitializer(ir::Block* block) { + if (initializer_ && initializer_->Parent() == this) { + initializer_->SetParent(nullptr); + } + initializer_ = block; + if (block) { + block->SetParent(this); + } +} + +void Loop::SetBody(ir::MultiInBlock* block) { + if (body_ && body_->Parent() == this) { + body_->SetParent(nullptr); + } + body_ = block; + if (block) { + block->SetParent(this); + } +} + +bool Loop::HasContinuing() const { + return continuing_->Terminator() != nullptr; +} + +void Loop::SetContinuing(ir::MultiInBlock* block) { + if (continuing_ && continuing_->Parent() == this) { + continuing_->SetParent(nullptr); + } + continuing_ = block; + if (block) { + block->SetParent(this); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/loop.h b/3rdparty/dawn/src/tint/lang/core/ir/loop.h new file mode 100644 index 000000000..f8374b98f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/loop.h @@ -0,0 +1,141 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_LOOP_H_ +#define SRC_TINT_LANG_CORE_IR_LOOP_H_ + +#include + +#include "src/tint/lang/core/ir/control_instruction.h" + +// Forward declarations +namespace tint::core::ir { +class MultiInBlock; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// Loop instruction. +/// +/// ``` +/// in +/// ┃ +/// ┣━━━━━━━━━━━┓ +/// ▼ ┃ +/// ┌─────────────────┐ ┃ +/// │ Initializer │ ┃ +/// │ (optional) │ ┃ +/// └─────────────────┘ ┃ +/// NextIteration ┃ ┃ +/// ┃◀━━━━━━━━━━┫ +/// ▼ ┃ +/// ┌─────────────────┐ ┃ +/// ┏━━│ Body │ ┃ +/// ┃ └─────────────────┘ ┃ +/// ┃ Continue ┃ ┃ NextIteration +/// ┃ ▼ ┃ +/// ┃ ┌─────────────────┐ ┃ BreakIf(false) +/// ExitLoop ┃ │ Continuing │━━┛ +/// ┃ │ (optional) │ +/// ┃ └─────────────────┘ +/// ┃ ┃ +/// ┃ ┃ BreakIf(true) +/// ┗━━━━━━━━━━▶┃ +/// ▼ +/// out +/// +/// ``` +class Loop final : public Castable { + public: + /// Constructor (no results, no operands, no blocks) + /// @param id the instruction id + explicit Loop(Id id); + + /// Constructor + /// @param id the instruction id + /// @param i the initializer block + /// @param b the body block + /// @param c the continuing block + Loop(Id id, ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c); + ~Loop() override; + + /// @copydoc Instruction::Clone() + Loop* Clone(CloneContext& ctx) override; + + /// @copydoc ControlInstruction::ForeachBlock + void ForeachBlock(const std::function& cb) override; + + /// @copydoc ControlInstruction::ForeachBlock + void ForeachBlock(const std::function& cb) const override; + + /// @returns the switch initializer block + ir::Block* Initializer() { return initializer_; } + + /// @returns the switch initializer block + const ir::Block* Initializer() const { return initializer_; } + + /// @returns true if the loop uses an initializer block. If true, then the Loop first branches + /// to the initializer block, otherwise it first branches to the body block. + bool HasInitializer() const; + + /// @param block the new switch initializer block + void SetInitializer(ir::Block* block); + + /// @returns the switch start block + ir::MultiInBlock* Body() { return body_; } + + /// @returns the switch start block + const ir::MultiInBlock* Body() const { return body_; } + + /// @param block the new switch body block + void SetBody(ir::MultiInBlock* block); + + /// @returns the switch continuing block + ir::MultiInBlock* Continuing() { return continuing_; } + + /// @returns the switch continuing block + const ir::MultiInBlock* Continuing() const { return continuing_; } + + /// @returns true if the loop uses an continuing block. If true, then the Loop first branches + /// to the continuing block, otherwise it first branches to the body block. + bool HasContinuing() const; + + /// @param block the new switch continuing block + void SetContinuing(ir::MultiInBlock* block); + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "loop"; } + + private: + ir::Block* initializer_ = nullptr; + ir::MultiInBlock* body_ = nullptr; + ir::MultiInBlock* continuing_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_LOOP_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.cc b/3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.cc new file mode 100644 index 000000000..a34047123 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.cc @@ -0,0 +1,58 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/member_builtin_call.h" + +#include + +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/rtti/castable.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::MemberBuiltinCall); + +namespace tint::core::ir { + +MemberBuiltinCall::MemberBuiltinCall(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +MemberBuiltinCall::MemberBuiltinCall(Id id, + InstructionResult* result, + Value* object, + VectorRef arguments) + : Base(id) { + flags_.Add(Flag::kSequenced); + AddOperand(MemberBuiltinCall::kObjectOperandOffset, object); + AddOperands(MemberBuiltinCall::kArgsOperandOffset, std::move(arguments)); + AddResult(result); +} + +MemberBuiltinCall::~MemberBuiltinCall() = default; + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.h b/3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.h new file mode 100644 index 000000000..5d2cbc389 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/member_builtin_call.h @@ -0,0 +1,83 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_MEMBER_BUILTIN_CALL_H_ +#define SRC_TINT_LANG_CORE_IR_MEMBER_BUILTIN_CALL_H_ + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// The base class for member builtin call instructions in the IR. +class MemberBuiltinCall : public Castable { + public: + /// The offset in Operands() for the object. + static constexpr size_t kObjectOperandOffset = 0; + + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 1; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit MemberBuiltinCall(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param object the object + /// @param args the call arguments + MemberBuiltinCall(Id id, + InstructionResult* result, + Value* object, + VectorRef args = tint::Empty); + + ~MemberBuiltinCall() override; + + /// @returns the offset of the arguments in Operands() + size_t ArgsOperandOffset() const override { return kArgsOperandOffset; } + + /// @returns the object used for the call + Value* Object() { return Operand(kObjectOperandOffset); } + + /// @returns the object used for the call + const Value* Object() const { return Operand(kObjectOperandOffset); } + + /// @returns the identifier for the function + virtual size_t FuncId() const = 0; + + /// @returns the table data to validate this builtin + virtual const core::intrinsic::TableData& TableData() const = 0; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_MEMBER_BUILTIN_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/module.cc b/3rdparty/dawn/src/tint/lang/core/ir/module.cc new file mode 100644 index 000000000..721164c4a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/module.cc @@ -0,0 +1,186 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/module.h" + +#include +#include + +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::core::ir { + +namespace { + +/// Helper to non-recursively sort a module's function in dependency order. +struct FunctionSorter { + /// The dependency-ordered list of functions. + UniqueVector ordered_functions{}; + + /// The functions that have been visited and checked for dependencies. + Hashset visited{}; + /// A stack of functions that need to processed and eventually added to the ordered list. + Vector function_stack{}; + + /// Visit a function and check for dependencies, and eventually add it to the ordered list. + /// @param func the function to visit + void Visit(Function* func) { + function_stack.Push(func); + while (!function_stack.IsEmpty()) { + // Visit the next function on the stack, if it hasn't already been visited. + auto* current_function = function_stack.Back(); + if (visited.Add(current_function)) { + // Check for dependencies inside the function, adding them to the queue if they have + // not already been visited. + Visit(current_function->Block()); + } else { + // We previously visited the function, so just discard it. + function_stack.Pop(); + } + + // If the function at the top of the stack has been visited, we know that it has no + // unvisited dependencies. We can now add it to the ordered list, and walk back down the + // stack until we find the next unvisited function. + while (!function_stack.IsEmpty() && visited.Contains(function_stack.Back())) { + ordered_functions.Add(function_stack.Pop()); + } + } + } + + /// Visit a function body block and look for dependencies. + /// @param block the function body to visit + void Visit(Block* block) { + Vector block_stack; + block_stack.Push(block); + while (!block_stack.IsEmpty()) { + auto* current_block = block_stack.Pop(); + for (auto* inst : *current_block) { + if (auto* control = inst->template As()) { + // Enqueue child blocks. + control->ForeachBlock([&](Block* b) { block_stack.Push(b); }); + } else if (auto* call = inst->template As()) { + // Enqueue the function that is being called. + if (!visited.Contains(call->Target())) { + function_stack.Push(call->Target()); + } + } + } + } + } + + /// Sort the functions of a module. + /// @param mod the IR module + /// @returns the sorted function list + static Vector SortFunctions(Module& mod) { + FunctionSorter sorter; + for (auto& func : mod.functions) { + sorter.Visit(func); + } + + auto funcs = sorter.ordered_functions.Release(); + return std::move(funcs); + } +}; + +} // namespace + +Module::Module() : root_block(blocks.Create()) {} + +Module::Module(Module&&) = default; + +Module::~Module() = default; + +Module& Module::operator=(Module&&) = default; + +Symbol Module::NameOf(const Instruction* inst) const { + if (inst->Results().Length() != 1) { + return Symbol{}; + } + return NameOf(inst->Result()); +} + +Symbol Module::NameOf(const Value* value) const { + return value_to_name_.GetOr(value, Symbol{}); +} + +void Module::SetName(Instruction* inst, std::string_view name) { + TINT_ASSERT(inst->Results().Length() == 1); + SetName(inst->Result(), name); +} + +void Module::SetName(Instruction* inst, Symbol name) { + TINT_ASSERT(inst->Results().Length() == 1); + SetName(inst->Result(), name); +} + +void Module::SetName(Value* value, std::string_view name) { + TINT_ASSERT(!name.empty()); + value_to_name_.Replace(value, symbols.Register(name)); +} + +void Module::SetName(Value* value, Symbol name) { + TINT_ASSERT(name.IsValid()); + value_to_name_.Replace(value, name); +} + +void Module::ClearName(Value* value) { + value_to_name_.Remove(value); +} + +void Module::SetSource(Instruction* inst, Source src) { + TINT_ASSERT(inst->Results().Length() == 1); + SetSource(inst->Result(), src); +} + +void Module::SetSource(Value* value, Source src) { + value_to_source_.Replace(value, src); +} + +Source Module::SourceOf(const Instruction* inst) const { + if (inst->Results().Length() != 1) { + return Source{}; + } + return SourceOf(inst->Result()); +} + +Source Module::SourceOf(const Value* value) const { + return value_to_source_.GetOr(value, Source{}); +} + +Vector Module::DependencyOrderedFunctions() { + return FunctionSorter::SortFunctions(*this); +} + +void Module::Destroy(Function* func) { + functions.EraseIf([&](const core::ir::Function* o) { return o == func; }); + func->Destroy(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/module.h b/3rdparty/dawn/src/tint/lang/core/ir/module.h new file mode 100644 index 000000000..ce9949291 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/module.h @@ -0,0 +1,225 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_MODULE_H_ +#define SRC_TINT_LANG_CORE_IR_MODULE_H_ + +#include + +#include "src/tint/lang/core/constant/manager.h" +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/containers/filtered_iterator.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/diagnostic/source.h" +#include "src/tint/utils/memory/block_allocator.h" +#include "src/tint/utils/symbol/symbol_table.h" + +namespace tint::core::ir { + +// Wrappers around the base TINT_ICE() macros that use the ice_callback attached to the module. +#define TINT_IR_ICE(module) TINT_ICE(module.ice_callback) +#define TINT_IR_UNREACHABLE(module) TINT_UNREACHABLE(module.ice_callback) +#define TINT_IR_UNIMPLEMENTED(module) TINT_UNIMPLEMENTED(module.ice_callback) +#define TINT_IR_ASSERT(module, condition) TINT_ASSERT((condition), module.ice_callback) + +/// Main module class for the IR. +class Module { + /// Map of value to name + Hashmap value_to_name_; + + // The source information for a value + Hashmap value_to_source_; + + /// A predicate function that returns true if the instruction or value is alive. + struct IsAlive { + bool operator()(const Instruction* instruction) const { return instruction->Alive(); } + bool operator()(const Value* value) const { return value->Alive(); } + }; + + public: + /// Constructor + Module(); + /// Move constructor + /// @param o the module to move from + Module(Module&& o); + /// Destructor + ~Module(); + + /// Move assign + /// @param o the module to assign from + /// @returns a reference to this module + Module& operator=(Module&& o); + + /// Creates a new `TYPE` instruction owned by the module + /// When the Module is destructed the object will be destructed and freed. + /// @param args the arguments to pass to the constructor + /// @returns the pointer to the instruction + template + TYPE* CreateInstruction(ARGS&&... args) { + return allocators_.instructions.Create(NextInstructionId(), + std::forward(args)...); + } + + /// Creates a new `TYPE` value owned by the module + /// When the Module is destructed the object will be destructed and freed. + /// @param args the arguments to pass to the constructor + /// @returns the pointer to the value + template + TYPE* CreateValue(ARGS&&... args) { + return allocators_.values.Create(std::forward(args)...); + } + + /// @param inst the instruction + /// @return the name of the given instruction, or an invalid symbol if the instruction is not + /// named or does not have a single return value. + Symbol NameOf(const Instruction* inst) const; + + /// @param value the value + /// @return the name of the given value, or an invalid symbol if the value is not named. + Symbol NameOf(const Value* value) const; + + /// @param inst the instruction to set the name of + /// @param name the desired name of the value. May be suffixed on collision. + /// @note requires the instruction be a single result instruction. + void SetName(Instruction* inst, std::string_view name); + + /// @param inst the instruction to set the name of + /// @param name the desired name of the value. + /// @note requires the instruction be a single result instruction. + void SetName(Instruction* inst, Symbol name); + + /// @param value the value to name. + /// @param name the desired name of the value. May be suffixed on collision. + void SetName(Value* value, std::string_view name); + + /// @param value the value to name + /// @param name the desired name of the value + void SetName(Value* value, Symbol name); + + /// Removes the name from @p value + /// @param value the value to remove the name from + void ClearName(Value* value); + + /// @param inst the instruction to set the source of + /// @param src the source + /// @note requires the instruction be a single result instruction. + void SetSource(Instruction* inst, Source src); + + /// @param value the value to set the source + /// @param src the source + void SetSource(Value* value, Source src); + + /// @param inst the instruction + /// @return the source of the given instruction, or an empty source if the instruction does not + /// have a source or does not have a single return value. + Source SourceOf(const Instruction* inst) const; + + /// @param value the value + /// @return the source of the given value, or an empty source if the value does not have a + /// source. + Source SourceOf(const Value* value) const; + + /// @return the type manager for the module + core::type::Manager& Types() { return constant_values.types; } + + /// @return the type manager for the module + const core::type::Manager& Types() const { return constant_values.types; } + + /// @returns a iterable of all the alive instructions + FilteredIterable::View> Instructions() { + return {allocators_.instructions.Objects()}; + } + + /// @returns a iterable of all the alive instructions + FilteredIterable::ConstView> Instructions() const { + return {allocators_.instructions.Objects()}; + } + + /// @returns a iterable of all the alive values + FilteredIterable::View> Values() { + return {allocators_.values.Objects()}; + } + + /// @returns a iterable of all the alive values + FilteredIterable::ConstView> Values() const { + return {allocators_.values.Objects()}; + } + + /// @returns the functions in the module, in dependency order + Vector DependencyOrderedFunctions(); + /// @returns the functions in the module, in dependency order + Vector DependencyOrderedFunctions() const; + + /// Removes `func` from the module and destroys it. + /// @param func the function to destroy + void Destroy(Function* func); + + /// The block allocator + BlockAllocator blocks; + + /// The constant value manager + core::constant::Manager constant_values; + + /// List of functions in the module. + Vector functions; + + /// The block containing module level declarations, if any exist. + Block* root_block = nullptr; + + /// The symbol table for the module + SymbolTable symbols{}; + + /// The map of core::constant::Value to their ir::Constant. + Hashmap constants; + + /// An optional callback to receive an ICE generated while processing this module. + InternalCompilerErrorCallback ice_callback; + + private: + /// @returns the next instruction id for this module + Instruction::Id NextInstructionId() { return next_instruction_id_++; } + + /// The various BlockAllocators for the module + struct { + /// The instruction allocator + BlockAllocator instructions; + + /// The value allocator + BlockAllocator values; + } allocators_; + + Instruction::Id next_instruction_id_ = 0; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_MODULE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.cc b/3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.cc new file mode 100644 index 000000000..88d018810 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.cc @@ -0,0 +1,93 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/multi_in_block.h" + +#include "src/tint/lang/core/ir/block_param.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/containers/predicates.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::MultiInBlock); + +namespace tint::core::ir { + +MultiInBlock::MultiInBlock() : Base() {} + +MultiInBlock::~MultiInBlock() = default; + +MultiInBlock* MultiInBlock::Clone(CloneContext&) { + TINT_UNREACHABLE() << "blocks must be cloned with CloneInto"; +} + +void MultiInBlock::CloneInto(CloneContext& ctx, Block* out) { + TINT_ASSERT(out->Is()); + + auto new_params = ctx.Clone(params_); + out->As()->SetParams(new_params); + Block::CloneInto(ctx, out); +} + +void MultiInBlock::SetParams(VectorRef params) { + for (auto* param : params_) { + param->SetBlock(nullptr); + } + params_ = std::move(params); + TINT_ASSERT(!params_.Any(IsNull)); + for (auto* param : params_) { + param->SetBlock(this); + } +} + +void MultiInBlock::SetParams(std::initializer_list params) { + for (auto* param : params_) { + param->SetBlock(nullptr); + } + params_ = std::move(params); + TINT_ASSERT(!params_.Any(IsNull)); + for (auto* param : params_) { + param->SetBlock(this); + } +} + +void MultiInBlock::AddParam(BlockParam* param) { + params_.Push(param); + param->SetBlock(this); +} + +void MultiInBlock::AddInboundSiblingBranch(ir::Terminator* node) { + TINT_ASSERT(node != nullptr); + inbound_sibling_branches_.Push(node); +} + +void MultiInBlock::RemoveInboundSiblingBranch(ir::Terminator* node) { + TINT_ASSERT(node != nullptr); + inbound_sibling_branches_.EraseIf([node](ir::Terminator* i) { return i == node; }); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.h b/3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.h new file mode 100644 index 000000000..ecc0e5be0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/multi_in_block.h @@ -0,0 +1,89 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_MULTI_IN_BLOCK_H_ +#define SRC_TINT_LANG_CORE_IR_MULTI_IN_BLOCK_H_ + +#include + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/block_param.h" + +namespace tint::core::ir { + +/// A block that can be the target of multiple branches. +/// 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 Castable { + public: + /// Constructor + MultiInBlock(); + ~MultiInBlock() override; + + /// @copydoc Block::Clone() + MultiInBlock* Clone(CloneContext& ctx) override; + + /// @copydoc Block::CloneInto() + void CloneInto(CloneContext& ctx, Block* out) override; + + /// Sets the params to the block + /// @param params the params for the block + void SetParams(VectorRef params); + + /// Sets the params to the block + /// @param params the params for the block + void SetParams(std::initializer_list params); + + /// Adds the param to the block + /// @param param the param for the block + void AddParam(BlockParam* param); + + /// @returns the params to the block + VectorRef Params() { return params_; } + + /// @returns the params to the block + VectorRef Params() const { return params_; } + + /// @returns branches made to this block by sibling blocks + const VectorRef InboundSiblingBranches() { return inbound_sibling_branches_; } + + /// Adds the given branch to the list of branches made to this block by sibling blocks + /// @param branch the branch to add + void AddInboundSiblingBranch(ir::Terminator* branch); + + /// Removes the given branch to the list of branches made to this block by sibling blocks + /// @param branch the branch to remove + void RemoveInboundSiblingBranch(ir::Terminator* branch); + + private: + Vector params_; + Vector inbound_sibling_branches_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_MULTI_IN_BLOCK_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/next_iteration.cc b/3rdparty/dawn/src/tint/lang/core/ir/next_iteration.cc new file mode 100644 index 000000000..425f505d2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/next_iteration.cc @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/next_iteration.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::NextIteration); + +namespace tint::core::ir { + +NextIteration::NextIteration(Id id) : Base(id) {} + +NextIteration::NextIteration(Id id, ir::Loop* loop, VectorRef args /* = tint::Empty */) + : Base(id), loop_(loop) { + TINT_ASSERT(loop_); + + AddOperands(NextIteration::kArgsOperandOffset, std::move(args)); + + if (loop_) { + loop_->Body()->AddInboundSiblingBranch(this); + } +} + +NextIteration::~NextIteration() = default; + +void NextIteration::Destroy() { + if (loop_) { + loop_->Body()->RemoveInboundSiblingBranch(this); + } + Instruction::Destroy(); +} + +NextIteration* NextIteration::Clone(CloneContext& ctx) { + auto* new_loop = ctx.Clone(loop_); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(new_loop, args); +} + +void NextIteration::SetLoop(ir::Loop* loop) { + if (loop_ && loop_->Body()) { + loop_->Body()->RemoveInboundSiblingBranch(this); + } + loop_ = loop; + if (loop) { + loop->Body()->AddInboundSiblingBranch(this); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/next_iteration.h b/3rdparty/dawn/src/tint/lang/core/ir/next_iteration.h new file mode 100644 index 000000000..5b9161c8b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/next_iteration.h @@ -0,0 +1,85 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_NEXT_ITERATION_H_ +#define SRC_TINT_LANG_CORE_IR_NEXT_ITERATION_H_ + +#include + +#include "src/tint/lang/core/ir/terminator.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Loop; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A next iteration instruction. +class NextIteration final : public Castable { + public: + /// The base offset in Operands() for the args + static constexpr size_t kArgsOperandOffset = 0; + + /// Constructor (no operands, no loop) + /// @param id the instruction id + explicit NextIteration(Id id); + + /// Constructor + /// @param id the instruction id + /// @param loop the loop being iterated + /// @param args the arguments for the MultiInBlock + NextIteration(Id id, ir::Loop* loop, VectorRef args = tint::Empty); + + ~NextIteration() override; + + /// @copydoc Instruction::Destroy() + void Destroy() override; + + /// @copydoc Instruction::Clone() + NextIteration* Clone(CloneContext& ctx) override; + + /// @returns the loop being iterated + ir::Loop* Loop() { return loop_; } + + /// @returns the loop being iterated + const ir::Loop* Loop() const { return loop_; } + + /// @param loop the new loop being iterated + void SetLoop(ir::Loop* loop); + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "next_iteration"; } + + private: + ir::Loop* loop_ = nullptr; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_NEXT_ITERATION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.cc b/3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.cc new file mode 100644 index 000000000..6791c2a04 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.cc @@ -0,0 +1,46 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/operand_instruction.h" + +using Op10 = tint::core::ir::OperandInstruction<1, 0>; +using Op11 = tint::core::ir::OperandInstruction<1, 1>; +using Op20 = tint::core::ir::OperandInstruction<2, 0>; +using Op30 = tint::core::ir::OperandInstruction<3, 0>; +using Op21 = tint::core::ir::OperandInstruction<2, 1>; +using Op31 = tint::core::ir::OperandInstruction<3, 1>; +using Op41 = tint::core::ir::OperandInstruction<4, 1>; + +TINT_INSTANTIATE_TYPEINFO(Op10); +TINT_INSTANTIATE_TYPEINFO(Op11); +TINT_INSTANTIATE_TYPEINFO(Op20); +TINT_INSTANTIATE_TYPEINFO(Op30); +TINT_INSTANTIATE_TYPEINFO(Op21); +TINT_INSTANTIATE_TYPEINFO(Op31); +TINT_INSTANTIATE_TYPEINFO(Op41); + +namespace tint::core::ir {} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.h b/3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.h new file mode 100644 index 000000000..c413a0215 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/operand_instruction.h @@ -0,0 +1,236 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_OPERAND_INSTRUCTION_H_ +#define SRC_TINT_LANG_CORE_IR_OPERAND_INSTRUCTION_H_ + +#include + +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::core::ir { + +/// An instruction in the IR that expects one or more operands. +/// @tparam N the number of operands before spilling to the heap +/// @tparam R the number of result values before spilling to the heap +template +class OperandInstruction : public Castable, Instruction> { + public: + /// Constructor + /// @param id the instruction id + explicit OperandInstruction(Instruction::Id id) : OperandInstruction::Base(id) {} + + /// Destructor + ~OperandInstruction() override = default; + + /// @copydoc tint::core::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(size_t index, ir::Value* value) override { + TINT_ASSERT(index < operands_.Length()); + if (operands_[index]) { + operands_[index]->RemoveUsage({this, index}); + } + operands_[index] = value; + if (value) { + value->AddUsage({this, index}); + } + } + + /// Replaces the operands of the instruction + /// @param operands the new operands of the instruction + void SetOperands(VectorRef operands) override { + ClearOperands(); + operands_ = std::move(operands); + for (size_t i = 0; i < operands_.Length(); i++) { + if (operands_[i]) { + operands_[i]->AddUsage({this, static_cast(i)}); + } + } + } + + /// Appends a new operand + /// @param operand the new operand + /// @returns the operand index + uint32_t PushOperand(ir::Value* operand) { + uint32_t idx = static_cast(operands_.Length()); + operands_.Push(operand); + if (operand) { + operand->AddUsage({this, idx}); + } + return idx; + } + + /// Pops the last operand off the operand list + /// @returns the removed element + Value* PopOperand() { return operands_.Pop(); } + + /// Removes all operands from the instruction + void ClearOperands() { + for (uint32_t i = 0; i < operands_.Length(); i++) { + if (!operands_[i]) { + continue; + } + operands_[i]->RemoveUsage({this, i}); + } + operands_.Clear(); + } + + /// Replaces the results of the instruction with a single result. + /// @param result the new result of the instruction + void SetResult(ir::InstructionResult* result) override { + ClearResults(); + results_.Push(result); + if (result) { + result->SetInstruction(this); + } + } + + /// Replaces the results of the instruction + /// @param results the new results of the instruction + void SetResults(VectorRef results) override { + ClearResults(); + results_ = std::move(results); + for (auto* result : results_) { + if (result) { + result->SetInstruction(this); + } + } + } + + /// Sets the results of the instruction + /// @param values the new result values + template >>>> + void SetResults(ARGS&&... values) { + SetResults(Vector{std::forward(values)...}); + } + + /// Appends a result value to the instruction + /// @param value the value to append + void AddResult(InstructionResult* value) { + if (value) { + value->SetInstruction(this); + } + results_.Push(value); + } + + /// Removes all results from the instruction. + void ClearResults() { + for (auto* result : results_) { + if (result && result->Instruction() == this) { + result->SetInstruction(nullptr); + } + } + results_.Clear(); + } + + /// @returns the operands of the instruction + VectorRef Operands() override { return operands_; } + + /// @returns the operands of the instruction + VectorRef Operands() const override { return operands_; } + + /// @returns the result values for this instruction + VectorRef Results() override { return results_; } + + /// @returns the result values for this instruction + VectorRef Results() const override { return results_; } + + /// @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. + InstructionResult* Result(size_t idx) { + return idx < results_.Length() ? results_[idx] : nullptr; + } + + /// @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. + const InstructionResult* Result(size_t idx) const { + return idx < results_.Length() ? results_[idx] : nullptr; + } + + /// @returns the instruction result + /// @note must only be called on instructions with exactly one result + InstructionResult* Result() { + TINT_ASSERT(results_.Length() == 1u); + return results_[0]; + } + + /// @returns the instruction result + /// @note must only be called on instructions with exactly one result + const InstructionResult* Result() const { + TINT_ASSERT(results_.Length() == 1u); + return results_[0]; + } + + 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(size_t idx, ir::Value* value) { + TINT_ASSERT(idx == operands_.Length()); + + if (value) { + value->AddUsage({this, static_cast(operands_.Length())}); + } + operands_.Push(value); + } + + /// 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(size_t start_idx, VectorRef values) { + size_t idx = start_idx; + for (auto* val : values) { + AddOperand(idx, val); + idx += 1; + } + } + + /// The operands to this instruction. + Vector operands_; + /// The results of this instruction. + Vector results_; + + /// The default number of operands + static constexpr size_t kDefaultNumOperands = N; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_OPERAND_INSTRUCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/override.cc b/3rdparty/dawn/src/tint/lang/core/ir/override.cc new file mode 100644 index 000000000..719203e55 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/override.cc @@ -0,0 +1,76 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/override.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Override); + +namespace tint::core::ir { + +Override::Override(Id id) : Base(id) {} + +Override::Override(Id id, InstructionResult* result) : Base(id) { + // Default to no initializer. + AddOperand(Override::kInitializerOperandOffset, nullptr); + AddResult(result); +} + +Override::~Override() = default; + +void Override::SetInitializer(Value* initializer) { + SetOperand(Override::kInitializerOperandOffset, initializer); +} + +Override* Override::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + TINT_ASSERT(new_result); + + auto* new_override = ctx.ir.CreateInstruction(new_result); + + new_override->id_ = id_; + + if (auto* init = Initializer()) { + new_override->SetInitializer(ctx.Clone(init)); + } + if (override_id_.has_value()) { + new_override->SetOverrideId(override_id_.value()); + } + + auto name = ctx.ir.NameOf(this); + if (name.IsValid()) { + ctx.ir.SetName(new_override, name.Name()); + } + return new_override; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/override.h b/3rdparty/dawn/src/tint/lang/core/ir/override.h new file mode 100644 index 000000000..269afc44f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/override.h @@ -0,0 +1,85 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_OVERRIDE_H_ +#define SRC_TINT_LANG_CORE_IR_OVERRIDE_H_ + +#include + +#include "src/tint/api/common/override_id.h" +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A var instruction in the IR. +class Override final : public Castable> { + public: + /// The offset in Operands() for the initializer + static constexpr size_t kInitializerOperandOffset = 0; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Override(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + Override(Id id, InstructionResult* result); + + ~Override() override; + + /// @copydoc Instruction::Clone() + Override* Clone(CloneContext& ctx) override; + + /// Sets the var initializer + /// @param initializer the initializer + void SetInitializer(Value* initializer); + /// @returns the initializer + Value* Initializer() { return Operand(kInitializerOperandOffset); } + /// @returns the initializer + const Value* Initializer() const { return Operand(kInitializerOperandOffset); } + + /// Sets the override Id attribute + /// @param id the override id + void SetOverrideId(OverrideId id) { override_id_ = id; } + /// @returns the override ID + std::optional OverrideId() const { return override_id_; } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "override"; } + + private: + std::optional override_id_{}; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_OVERRIDE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/phony.cc b/3rdparty/dawn/src/tint/lang/core/ir/phony.cc new file mode 100644 index 000000000..a6a6e5faf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/phony.cc @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/phony.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Phony); + +namespace tint::core::ir { + +Phony::Phony(Id id, ir::Value* value) : Base(id) { + AddOperand(Phony::kValueOperandOffset, value); +} + +Phony::~Phony() = default; + +Phony* Phony::Clone(CloneContext& ctx) { + auto* val = ctx.Remap(Operand(kValueOperandOffset)); + return ctx.ir.CreateInstruction(val); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/phony.h b/3rdparty/dawn/src/tint/lang/core/ir/phony.h new file mode 100644 index 000000000..6c1a1276b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/phony.h @@ -0,0 +1,67 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_PHONY_H_ +#define SRC_TINT_LANG_CORE_IR_PHONY_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" + +namespace tint::core::ir { + +/// Phony assignment in the IR. +class Phony : public Castable> { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// The fixed number of operands accepted by phony instructions + static constexpr size_t kNumOperands = 1; + + /// The fixed number of results returned by phony instructions + static constexpr size_t kNumResults = 0; + + /// Constructor + /// @param id the instruction id + /// @param value the assigned value + explicit Phony(Id id, Value* value); + ~Phony() override; + + /// @copydoc Instruction::Clone() + Phony* Clone(CloneContext& ctx) override; + + /// @returns the value + const ir::Value* Value() const { return Operand(kValueOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "phony"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_PHONY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/referenced_functions.h b/3rdparty/dawn/src/tint/lang/core/ir/referenced_functions.h new file mode 100644 index 000000000..3af65546f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/referenced_functions.h @@ -0,0 +1,144 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_REFERENCED_FUNCTIONS_H_ +#define SRC_TINT_LANG_CORE_IR_REFERENCED_FUNCTIONS_H_ + +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/rtti/switch.h" + +/// Utility that helps guarantee the same const-ness is applied to both types. +template +using TranscribeConst = std::conditional_t{}, std::add_const_t, Dst>; + +namespace tint::core::ir { + +/// ReferencedFunctions is a helper to determine the set of functions that are transitively +/// referenced by functions in a module. References are determined lazily and cached for future +/// requests. +/// +/// Note: +/// The template param M is used to ensure that inputs and outputs of this class have the same +/// const-ness. If 'Module' is supplied then the internal operations and output will not be +/// const, which is needed for transforms. Whereas if the param is 'const Module' the internals +/// and outputs will be const, which is needed for the IR validator. +/// Note: +/// Changes to the module can invalidate the cached data. This is intended to be created by +/// operations that need this information, and discarded when they complete. Tracking this +/// information inside the IR module would add overhead any time an instruction is added or +/// removed from the module. Since only a few operations need this information, it is expected +/// to be more efficient to generate it on demand. +template +class ReferencedFunctions { + // Replace this with concepts when C++20 is available. + static_assert(std::is_same, Module>()); + + public: + /// Short form aliases for types that have the same constant-ness as M. + using BlockT = TranscribeConst; + using FunctionT = TranscribeConst; + + /// A set of a functions referenced by a function. + using FunctionSet = Hashset; + + /// Constructor. + /// @param ir the module + explicit ReferencedFunctions(M& ir) { + // Loop over functions, recording the blocks that they are called from. + for (auto& func : ir.functions) { + if (!func) { + continue; + } + func->ForEachUseUnsorted([&](const Usage& use) { + if (auto* call = use.instruction->As()) { + block_to_direct_calls_.GetOrAddZero(call->Block()).Add(func); + } else { + TINT_ASSERT(use.instruction->Is()); + } + }); + } + } + + /// Get the set of transitively referenced functions for a function. + /// @param func the function + /// @returns the set of transitively reference functions + FunctionSet& TransitiveReferences(FunctionT* func) { + return transitive_references_.GetOrAdd(func, [&] { + FunctionSet functions; + if (!func) { + return functions; + } + + // Walk blocks in the function to find function calls. + Vector block_queue{func->Block()}; + while (!block_queue.IsEmpty()) { + auto* next = block_queue.Pop(); + if (!next) { + continue; + } + + // Add directly referenced functions. + if (auto itr = block_to_direct_calls_.Get(next)) { + for (auto& callee : *itr) { + if (functions.Add(callee)) { + // Add functions transitively referenced by the callee. + const auto& callee_functions = TransitiveReferences(callee); + for (auto& transitive_func : callee_functions) { + functions.Add(transitive_func); + } + } + } + } + + // Loop over instructions in the block to find nested blocks. + for (auto* inst : *next) { + if (auto* ctrl = inst->template As()) { + // Add nested blocks to the queue. + ctrl->ForeachBlock([&](BlockT* blk) { block_queue.Push(blk); }); + } + } + } + + return functions; + }); + } + + private: + /// A map from blocks to their directly called functions. + Hashmap block_to_direct_calls_{}; + + /// A map from functions to their transitively referenced functions. + Hashmap transitive_references_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_REFERENCED_FUNCTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/referenced_module_decls.h b/3rdparty/dawn/src/tint/lang/core/ir/referenced_module_decls.h new file mode 100644 index 000000000..0e43ccd31 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/referenced_module_decls.h @@ -0,0 +1,258 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_DECLS_H_ +#define SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_DECLS_H_ + +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/type/array_count.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/rtti/switch.h" + +// Forward declarations. +namespace tint::core::ir { +class Block; +class Function; +} // namespace tint::core::ir + +/// Utility that helps guarantee the same const-ness is applied to both types. +template +using TranscribeConst = std::conditional_t{}, std::add_const_t, Dst>; + +namespace tint::core::ir { + +/// ReferencedModuleDecls is a helper to determine the set of module-scope declarations that are +/// transitively referenced by functions in a module. +/// +/// References are determined lazily and cached for future requests. +/// +/// Note: +/// The template param M is used to ensure that inputs and outputs of this class have the same +/// const-ness. If 'Module' is supplied then the internal operations and output will not be +/// const, which is needed for transforms. Whereas if the param is 'const Module' the internals +/// and outputs will be const, which is needed for the IR validator. +/// Note: +/// Changes to the module can invalidate the cached data. This is intended to be created by +/// operations that need this information, and discarded when they complete. Tracking this +/// information inside the IR module would add overhead any time an instruction is added or +/// removed from the module. Since only a few operations need this information, it is expected +/// to be more efficient to generate it on demand. +template +class ReferencedModuleDecls { + // Replace this with concepts when C++20 is available + static_assert(std::is_same, Module>()); + + public: + /// Short form aliases for types that have the same constant-ness as M. + /// (The single use types are not aliased) + using BlockT = TranscribeConst; + using DeclT = TranscribeConst; + using FunctionT = TranscribeConst; + + /// A set of a declarations referenced by a function (in declaration order). + using DeclSet = UniqueVector; + + /// Constructor. + /// @param ir the module + explicit ReferencedModuleDecls(M& ir) { + // Loop over module-scope declarations, recording the blocks that they are referenced from. + BlockT* root_block = ir.root_block; + for (auto* inst : *root_block) { + if (!inst || !inst->Result(0)) { + continue; + } + + inst->Result()->ForEachUseUnsorted([&](const Usage& use) { + if (use.instruction->Block() != root_block) { + AddToBlock(block_to_direct_decls_.GetOrAddZero(use.instruction->Block()), inst); + } + }); + + // If the instruction is a `var` we have to check the type. If the type is an + // array with a `ValueArrayCount` then we need to check the count. If it's not + // `Constant` we need to add the instruction and any referenced instructions to the used + // set. + auto* var = inst->template As(); + if (!var) { + continue; + } + auto* ptr = var->Result()->Type()->template As(); + TINT_ASSERT(ptr); + + if (ptr->AddressSpace() != core::AddressSpace::kWorkgroup) { + continue; + } + auto* ary = ptr->UnwrapPtr()->template As(); + if (!ary) { + continue; + } + auto* cnt = ary->Count()->template As(); + if (!cnt || cnt->value->template Is()) { + continue; + } + + auto* cnt_inst = cnt->value->template As(); + TINT_ASSERT(cnt_inst); + + // The usage of the var is as a `let` initializer. The array count needs to + // propagate to the `let` block. + var->Result()->ForEachUseUnsorted([&](const Usage& use) { + AddToBlock(block_to_direct_decls_.GetOrAddZero(use.instruction->Block()), + cnt_inst->Instruction()); + }); + } + } + + /// Get the set of transitively referenced module-scope declarations for a function. + /// @param func the function + /// @returns the set of transitively reference module-scope declarations + DeclSet& TransitiveReferences(FunctionT* func) { + return transitive_references_.GetOrAdd(func, [&] { + DeclSet decls; + GetTransitiveReferences(func ? func->Block() : nullptr, decls); + + // For a compute entry point, we need to check if subgroup size or any of the workgroup + // sizes are built on overrides. + if (func && func->Stage() == core::ir::Function::PipelineStage::kCompute) { + TINT_ASSERT(func->WorkgroupSize().has_value()); + + const auto workgroup_size = func->WorkgroupSize(); + for (auto wg_size : *workgroup_size) { + if (wg_size->template Is()) { + continue; + } + + // Workgroup size is based on instructions, walk up the chain adding those + // instructions to the `decls` list. + auto* inst = wg_size->template As(); + TINT_ASSERT(inst); + + AddToBlock(decls, inst->Instruction()); + } + const auto subgroup_size = func->SubgroupSize(); + if (subgroup_size.has_value() && + !((*subgroup_size)->template Is())) { + auto* inst = (*subgroup_size)->template As(); + TINT_ASSERT(inst); + AddToBlock(decls, inst->Instruction()); + } + } + return decls; + }); + } + + void AddToBlock(DeclSet& decls, core::ir::Instruction* inst) { + Vector worklist; + worklist.Push(inst); + + while (!worklist.IsEmpty()) { + auto* wl_inst = worklist.Pop(); + if (decls.Add(wl_inst)) { + for (auto* operand : wl_inst->Operands()) { + if (!operand) { + continue; + } + auto* res = operand->template As(); + if (!res) { + continue; + } + worklist.Push(res->Instruction()); + } + + // ConstExprIf instruction is special because it use to be a short circuiting binary + // operation that was converted to a specialized if instruction. + if (auto* const_expr_if = wl_inst->template As()) { + auto add_block_instructions = [&worklist](Block* block) { + if (!block) { + return; + } + for (auto* block_inst : *block) { + worklist.Push(block_inst); + } + }; + + add_block_instructions(const_expr_if->True()); + add_block_instructions(const_expr_if->False()); + } + } + } + } + + private: + /// A map from blocks to their directly referenced declarations. + Hashmap block_to_direct_decls_{}; + + /// A map from functions to their transitively referenced declarations. + Hashmap transitive_references_; + + /// Get the set of transitively referenced module-scope declarations for a block. + /// @param block the block + /// @param decls the set of transitively reference module-scope declarations to populate + void GetTransitiveReferences(BlockT* block, DeclSet& decls) { + if (!block) { + return; + } + + // Add directly referenced declarations. + if (auto itr = block_to_direct_decls_.Get(block)) { + for (auto& decl : *itr) { + decls.Add(decl); + } + } + + // Loop over instructions in the block to find indirectly referenced vars. + for (auto* inst : *block) { + tint::Switch( + inst, + [&](TranscribeConst* call) { + // Get declarations referenced by a function called from this block. + const auto& callee_decls = TransitiveReferences(call->Target()); + for (auto* decl : callee_decls) { + decls.Add(decl); + } + }, + [&](TranscribeConst* ctrl) { + // Recurse into control instructions and gather their referenced declarations. + ctrl->ForeachBlock([&](BlockT* blk) { GetTransitiveReferences(blk, decls); }); + }); + } + } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_DECLS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/referenced_module_vars.h b/3rdparty/dawn/src/tint/lang/core/ir/referenced_module_vars.h new file mode 100644 index 000000000..524c13b57 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/referenced_module_vars.h @@ -0,0 +1,171 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_VARS_H_ +#define SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_VARS_H_ + +#include + +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/rtti/switch.h" + +// Forward declarations. +namespace tint::core::ir { +class Block; +class Function; +} // namespace tint::core::ir + +/// Utility that helps guarantee the same const-ness is applied to both types. +template +using TranscribeConst = std::conditional_t{}, std::add_const_t, Dst>; + +namespace tint::core::ir { + +/// ReferencedModuleVars is a helper to determine the set of module-scope variables that are +/// transitively referenced by functions in a module. +/// References are determined lazily and cached for future requests. +/// +/// Note: +/// The template param M is used to ensure that inputs and outputs of this class have the same +/// const-ness. If 'Module' is supplied then the internal operations and output will not be +/// const, which is needed for transforms. Whereas if the param is 'const Module' the internals +/// and outputs will be const, which is needed for the IR validator. +/// Note: +/// Changes to the module can invalidate the cached data. This is intended to be created by +/// operations that need this information, and discarded when they complete. Tracking this +/// information inside the IR module would add overhead any time an instruction is added or +/// removed from the module. Since only a few operations need this information, it is expected +/// to be more efficient to generate it on demand. +template +class ReferencedModuleVars { + // Replace this with concepts when C++20 is available + static_assert(std::is_same, Module>()); + + public: + /// Short form aliases for types that have the same constant-ness as M. + /// (The single use types are not aliased) + using BlockT = TranscribeConst; + using VarT = TranscribeConst; + using FunctionT = TranscribeConst; + + /// A set of a variables referenced by a function (in declaration order). + using VarSet = UniqueVector; + + /// Constructor. + /// @param ir the module + /// @param pred an predicate function for filtering variables + /// Note: @p pred is not stored by the class, so can be a lambda that captures by reference. + template + ReferencedModuleVars(M& ir, Predicate&& pred) { + // Loop over module-scope variables, recording the blocks that they are referenced from. + BlockT* root_block = ir.root_block; + for (auto* inst : *root_block) { + if (!inst) { + continue; + } + if (auto* var = inst->template As()) { + if (pred(var)) { + // One of the locations this class is constructed, is by the validator during + // its own constructor, which means this can run before validation occurs. So + // skipping malformed Vars here, since the validator will reject the shader + // later. + if (!var->Result(0) || var->Results().Length() != 1) { + continue; + } + var->Result()->ForEachUseUnsorted([&](const Usage& use) { + block_to_direct_vars_.GetOrAddZero(use.instruction->Block()).Add(var); + }); + } + } + } + } + + /// Constructor. + /// Provided default predicate that accepts all variables. + explicit ReferencedModuleVars(M& ir) : ReferencedModuleVars(ir, [](VarT*) { return true; }) {} + + /// Get the set of transitively referenced module-scope variables for a function, filtered by + /// the predicate function if provided. + /// @param func the function + /// @returns the set of (possibly filtered) transitively reference module-scope variables + VarSet& TransitiveReferences(FunctionT* func) { + return transitive_references_.GetOrAdd(func, [&] { + VarSet vars; + GetTransitiveReferences(func ? func->Block() : nullptr, vars); + return vars; + }); + } + + private: + /// A map from blocks to their directly referenced variables. + Hashmap block_to_direct_vars_{}; + + /// A map from functions to their transitively referenced variables. + Hashmap transitive_references_; + + /// Get the set of transitively referenced module-scope variables for a block. + /// @param block the block + /// @param vars the set of transitively reference module-scope variables to populate + void GetTransitiveReferences(BlockT* block, VarSet& vars) { + if (!block) { + return; + } + + // Add directly referenced vars. + if (auto itr = block_to_direct_vars_.Get(block)) { + for (auto& var : *itr) { + vars.Add(var); + } + } + + // Loop over instructions in the block to find indirectly referenced vars. + for (auto* inst : *block) { + tint::Switch( + inst, + [&](TranscribeConst* call) { + // Get variables referenced by a function called from this block. + const auto& callee_vars = TransitiveReferences(call->Target()); + for (auto* var : callee_vars) { + vars.Add(var); + } + }, + [&](TranscribeConst* ctrl) { + // Recurse into control instructions and gather their referenced vars. + ctrl->ForeachBlock([&](BlockT* blk) { GetTransitiveReferences(blk, vars); }); + }); + } + } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_VARS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/reflection.cc b/3rdparty/dawn/src/tint/lang/core/ir/reflection.cc new file mode 100644 index 000000000..25d4d749d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/reflection.cc @@ -0,0 +1,71 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/reflection.h" + +#include +#include + +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/pointer.h" + +namespace tint::core::ir { + +Result GetWorkgroupInfo(core::ir::Module& ir) { + std::optional> const_wg_size; + for (auto func : ir.functions) { + if (!func->IsEntryPoint()) { + continue; + } + const_wg_size = func->WorkgroupSizeAsConst(); + } + + if (!const_wg_size) { + return Failure{"IR GetWorkgroupInfo: Could not find workgroup size"}; + } + + size_t wg_storage_size = 0u; + for (auto* inst : *ir.root_block) { + if (auto* as_var = inst->As()) { + auto* ptr = as_var->Result()->Type()->As(); + if (ptr->AddressSpace() != core::AddressSpace::kWorkgroup) { + continue; + } + auto* ty = ptr->StoreType(); + uint32_t align = ty->Align(); + uint32_t size = ty->Size(); + + // This essentially matches std430 layout rules from GLSL, which are in + // turn specified as an upper bound for Vulkan layout sizing. + wg_storage_size += tint::RoundUp(16u, tint::RoundUp(align, size)); + } + } + return WorkgroupInfo{(*const_wg_size)[0], (*const_wg_size)[1], (*const_wg_size)[2], + wg_storage_size}; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/reflection.h b/3rdparty/dawn/src/tint/lang/core/ir/reflection.h new file mode 100644 index 000000000..a44040f3d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/reflection.h @@ -0,0 +1,55 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_REFLECTION_H_ +#define SRC_TINT_LANG_CORE_IR_REFLECTION_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/result.h" + +namespace tint::core::ir { +/// Workgroup size information +struct WorkgroupInfo { + /// The x-component + uint32_t x = 0; + /// The y-component + uint32_t y = 0; + /// The z-component + uint32_t z = 0; + + /// The needed workgroup storage size + size_t storage_size = 0; +}; + +/// Generate WorkgroupInfo for an IR module input. +/// @param ir the workgroup info for the IR module +/// @returns the resulting WorkgroupInfo for the IR, or failure. +Result GetWorkgroupInfo(core::ir::Module& ir); + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_REFLECTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/return.cc b/3rdparty/dawn/src/tint/lang/core/ir/return.cc new file mode 100644 index 000000000..cc3aef29b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/return.cc @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/return.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Return); + +namespace tint::core::ir { + +Return::Return(Id id) : Base(id) {} + +Return::Return(Id id, Function* func) : Base(id) { + AddOperand(Return::kFunctionOperandOffset, func); +} + +Return::Return(Id id, Function* func, ir::Value* arg) : Base(id) { + AddOperand(Return::kFunctionOperandOffset, func); + AddOperand(Return::kArgsOperandOffset, arg); +} + +Return::~Return() = default; + +Return* Return::Clone(CloneContext& ctx) { + auto* fn = ctx.Remap(Func()); + if (auto* val = Value()) { + return ctx.ir.CreateInstruction(fn, ctx.Remap(val)); + } + return ctx.ir.CreateInstruction(fn); +} + +Function* Return::Func() { + return tint::As(Operand(kFunctionOperandOffset)); +} + +const Function* Return::Func() const { + return tint::As(Operand(kFunctionOperandOffset)); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/return.h b/3rdparty/dawn/src/tint/lang/core/ir/return.h new file mode 100644 index 000000000..574dccfb1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/return.h @@ -0,0 +1,103 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_RETURN_H_ +#define SRC_TINT_LANG_CORE_IR_RETURN_H_ + +#include + +#include "src/tint/lang/core/ir/terminator.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Function; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A return instruction. +class Return final : public Castable { + 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 kArgsOperandOffset = 1; + + /// The minimum number of operands accepted by return instructions + static constexpr size_t kMinOperands = 1; + + /// The maximum number of operands accepted by return instructions + static constexpr size_t kMaxOperands = 2; + + /// Constructor (no operands) + /// @param id the instruction id + explicit Return(Id id); + + /// Constructor (no return value) + /// @param id the instruction id + /// @param func the function being returned + Return(Id id, Function* func); + + /// Constructor + /// @param id the instruction id + /// @param func the function being returned + /// @param arg the return value + Return(Id id, Function* func, ir::Value* arg); + + ~Return() override; + + /// @copydoc Instruction::Clone() + Return* Clone(CloneContext& ctx) override; + + /// @returns the function being returned + Function* Func(); + + /// @returns the function being returned + const Function* Func() const; + + /// @returns true if the return has a value set + bool HasValue() const { return operands_.Length() > kArgsOperandOffset; } + + /// @returns the return value, or nullptr + ir::Value* Value() const { return HasValue() ? operands_[kArgsOperandOffset] : nullptr; } + + /// Sets the return value + /// @param val the new return value + void SetValue(ir::Value* val) { SetOperand(kArgsOperandOffset, val); } + + /// @returns the offset of the arguments in Operands() + size_t ArgsOperandOffset() const override { return kArgsOperandOffset; } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "return"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_RETURN_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/store.cc b/3rdparty/dawn/src/tint/lang/core/ir/store.cc new file mode 100644 index 000000000..0acd27bcd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/store.cc @@ -0,0 +1,56 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/store.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Store); + +namespace tint::core::ir { + +Store::Store(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +Store::Store(Id id, Value* to, Value* from) : Base(id) { + flags_.Add(Flag::kSequenced); + + AddOperand(Store::kToOperandOffset, to); + AddOperand(Store::kFromOperandOffset, from); +} + +Store::~Store() = default; + +Store* Store::Clone(CloneContext& ctx) { + auto* to = ctx.Remap(To()); + auto* from = ctx.Remap(From()); + return ctx.ir.CreateInstruction(to, from); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/store.h b/3rdparty/dawn/src/tint/lang/core/ir/store.h new file mode 100644 index 000000000..24e7ee781 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/store.h @@ -0,0 +1,95 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_STORE_H_ +#define SRC_TINT_LANG_CORE_IR_STORE_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A store instruction in the IR. +class Store final : public Castable> { + 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; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 0; + + /// The fixed number of operands used by this instruction + static constexpr size_t kNumOperands = 2; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Store(Id id); + + /// Constructor + /// @param id the instruction id + /// @param to the value to store too + /// @param from the value being stored from + Store(Id id, Value* to, Value* from); + + ~Store() override; + + /// @copydoc Instruction::Clone() + Store* Clone(CloneContext& ctx) override; + + /// @returns the value being stored to + Value* To() { return Operand(kToOperandOffset); } + + /// @returns the value being stored to + const Value* To() const { return Operand(kToOperandOffset); } + + /// @param to the value being stored to + void SetTo(Value* to) { SetOperand(kToOperandOffset, to); } + + /// @returns the value being stored + Value* From() { return Operand(kFromOperandOffset); } + + /// @returns the value being stored + const Value* From() const { return Operand(kFromOperandOffset); } + + /// @param from the value being stored + void SetFrom(Value* from) { SetOperand(kFromOperandOffset, from); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "store"; } + + /// @returns the side effects for this instruction + Accesses GetSideEffects() const override { return Accesses{Access::kStore}; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_STORE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.cc b/3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.cc new file mode 100644 index 000000000..849500361 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.cc @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/store_vector_element.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::StoreVectorElement); + +namespace tint::core::ir { + +StoreVectorElement::StoreVectorElement(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +StoreVectorElement::StoreVectorElement(Id id, ir::Value* to, ir::Value* index, ir::Value* value) + : Base(id) { + flags_.Add(Flag::kSequenced); + + AddOperand(StoreVectorElement::kToOperandOffset, to); + AddOperand(StoreVectorElement::kIndexOperandOffset, index); + AddOperand(StoreVectorElement::kValueOperandOffset, value); +} + +StoreVectorElement::~StoreVectorElement() = default; + +StoreVectorElement* StoreVectorElement::Clone(CloneContext& ctx) { + auto* to = ctx.Remap(To()); + auto* idx = ctx.Remap(Index()); + auto* val = ctx.Remap(Value()); + return ctx.ir.CreateInstruction(to, idx, val); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.h b/3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.h new file mode 100644 index 000000000..92baed009 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/store_vector_element.h @@ -0,0 +1,99 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_STORE_VECTOR_ELEMENT_H_ +#define SRC_TINT_LANG_CORE_IR_STORE_VECTOR_ELEMENT_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A store instruction for a single vector element in the IR. +class StoreVectorElement final : public Castable> { + public: + /// The offset in Operands() for the `to` value + static constexpr size_t kToOperandOffset = 0; + + /// The offset in Operands() for the `index` value + static constexpr size_t kIndexOperandOffset = 1; + + /// The offset in Operands() for the `value` value + static constexpr size_t kValueOperandOffset = 2; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 0; + + /// The fixed number of operands used by this instruction + static constexpr size_t kNumOperands = 3; + + /// Constructor (no operands) + /// @param id the instruction id + explicit StoreVectorElement(Id id); + + /// Constructor + /// @param id the instruction id + /// @param to the vector pointer + /// @param index the new vector element index + /// @param value the new vector element value + StoreVectorElement(Id id, ir::Value* to, ir::Value* index, ir::Value* value); + + ~StoreVectorElement() override; + + /// @copydoc Instruction::Clone() + StoreVectorElement* Clone(CloneContext& ctx) override; + + /// @returns the vector pointer value + ir::Value* To() { return Operand(kToOperandOffset); } + + /// @returns the vector pointer value + const ir::Value* To() const { return Operand(kToOperandOffset); } + + /// @returns the new vector element index + ir::Value* Index() { return Operand(kIndexOperandOffset); } + + /// @returns the new vector element index + const ir::Value* Index() const { return Operand(kIndexOperandOffset); } + + /// @returns the new vector element value + ir::Value* Value() { return Operand(kValueOperandOffset); } + + /// @returns the new vector element value + const ir::Value* Value() const { return Operand(kValueOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "store_vector_element"; } + + /// @returns the side effects for this instruction + Accesses GetSideEffects() const override { return Accesses{Access::kStore}; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_STORE_VECTOR_ELEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/switch.cc b/3rdparty/dawn/src/tint/lang/core/ir/switch.cc new file mode 100644 index 000000000..bf7e9edfa --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/switch.cc @@ -0,0 +1,87 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/switch.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Switch); + +namespace tint::core::ir { + +Switch::Switch(Id id) : Base(id) {} + +Switch::Switch(Id id, Value* cond) : Base(id) { + TINT_ASSERT(cond); + + AddOperand(Switch::kConditionOperandOffset, cond); +} + +Switch::~Switch() = default; + +void Switch::ForeachBlock(const std::function& cb) { + for (auto& c : cases_) { + cb(c.block); + } +} + +void Switch::ForeachBlock(const std::function& cb) const { + for (auto& c : cases_) { + cb(c.block); + } +} + +Switch* Switch::Clone(CloneContext& ctx) { + auto* cond = ctx.Remap(Condition()); + auto* new_switch = ctx.ir.CreateInstruction(cond); + ctx.Replace(this, new_switch); + + new_switch->cases_.Reserve(cases_.Length()); + for (auto& cse : cases_) { + Switch::Case new_case{}; + new_case.block = ctx.ir.blocks.Create(); + new_case.block->SetParent(new_switch); + cse.block->CloneInto(ctx, new_case.block); + + new_case.selectors.Reserve(cse.selectors.Length()); + for (auto& sel : cse.selectors) { + auto* new_val = sel.val ? ctx.Clone(sel.val) : nullptr; + new_case.selectors.Push(Switch::CaseSelector{new_val}); + } + new_switch->cases_.Push(std::move(new_case)); + } + + new_switch->SetResults(ctx.Clone(results_)); + + return new_switch; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/switch.h b/3rdparty/dawn/src/tint/lang/core/ir/switch.h new file mode 100644 index 000000000..09900f259 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/switch.h @@ -0,0 +1,145 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_SWITCH_H_ +#define SRC_TINT_LANG_CORE_IR_SWITCH_H_ + +#include +#include + +#include "src/tint/lang/core/ir/control_instruction.h" + +// Forward declarations +namespace tint::core::ir { +class Constant; +class MultiInBlock; +} // namespace tint::core::ir + +namespace tint::core::ir { +/// Switch instruction. +/// +/// ``` +/// in +/// ┃ +/// ╌╌╌╌╌╌╌╌┲━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━┱╌╌╌╌╌╌╌╌ +/// ▼ ▼ ▼ +/// ┌────────┐ ┌────────┐ ┌────────┐ +/// │ Case A │ │ Case B │ │ Case C │ +/// └────────┘ └────────┘ └────────┘ +/// ExitSwitch ┃ ExitSwitch ┃ ExitSwitch ┃ +/// ┃ ┃ ┃ +/// ╌╌╌╌╌╌╌╌┺━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━┹╌╌╌╌╌╌╌╌ +/// ┃ +/// ▼ +/// out +/// ``` +class Switch final : public Castable { + public: + /// The number of supported operands + static constexpr size_t kNumOperands = 1; + /// 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 + bool IsDefault() const { return val == nullptr; } + + /// The selector value, or nullptr if this is the default selector + Constant* val = nullptr; + }; + + /// A case label in the struct + struct Case { + /// The case selector for this node + Vector selectors; + + /// The case block. + ir::Block* block = nullptr; + }; + + /// Constructor (no results, no operands, no cases) + /// @param id the instruction id + explicit Switch(Id id); + + /// Constructor + /// @param id the instruction id + /// @param cond the condition + Switch(Id id, Value* cond); + + ~Switch() override; + + /// @copydoc Instruction::Clone() + Switch* Clone(CloneContext& ctx) override; + + /// @copydoc ControlInstruction::ForeachBlock + void ForeachBlock(const std::function& cb) override; + + /// @copydoc ControlInstruction::ForeachBlock + void ForeachBlock(const std::function& cb) const override; + + /// @returns the switch cases + Vector& Cases() { return cases_; } + + /// @returns the switch cases by moving them + Vector TakeCases() { + auto rtn = std::move(cases_); + cases_.Clear(); + return rtn; + } + + /// @returns the switch cases + VectorRef Cases() const { return cases_; } + + /// @returns the condition + Value* Condition() { return Operand(kConditionOperandOffset); } + + /// @returns the condition + const Value* Condition() const { return Operand(kConditionOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "switch"; } + + /// @returns the default block for the switch, or nullptr if non-exists + ir::Block* DefaultBlock() { + for (auto& c : cases_) { + for (auto& s : c.selectors) { + if (s.IsDefault()) { + return c.block; + } + } + } + return nullptr; + } + + private: + Vector cases_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_SWITCH_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/swizzle.cc b/3rdparty/dawn/src/tint/lang/core/ir/swizzle.cc new file mode 100644 index 000000000..fe8b54636 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/swizzle.cc @@ -0,0 +1,63 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/swizzle.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Swizzle); + +namespace tint::core::ir { + +Swizzle::Swizzle(Id id) : Base(id) {} + +Swizzle::Swizzle(Id id, InstructionResult* result, Value* object, VectorRef indices) + : Base(id), indices_(std::move(indices)) { + TINT_ASSERT(!indices_.IsEmpty()); + TINT_ASSERT(indices_.Length() <= Swizzle::kMaxNumIndices); + + AddOperand(Swizzle::kObjectOperandOffset, object); + AddResult(result); + + for (auto idx : indices_) { + TINT_ASSERT(idx <= Swizzle::kMaxIndexValue); + } +} + +Swizzle::~Swizzle() = default; + +Swizzle* Swizzle::Clone(CloneContext& ctx) { + auto* result = ctx.Clone(Result()); + auto* obj = ctx.Remap(Object()); + return ctx.ir.CreateInstruction(result, obj, indices_); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/swizzle.h b/3rdparty/dawn/src/tint/lang/core/ir/swizzle.h new file mode 100644 index 000000000..b29db4518 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/swizzle.h @@ -0,0 +1,98 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_SWIZZLE_H_ +#define SRC_TINT_LANG_CORE_IR_SWIZZLE_H_ + +#include +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A swizzle instruction in the IR. +class Swizzle final : public Castable> { + public: + /// The offset in Operands() for the object being swizzled + static constexpr size_t kObjectOperandOffset = 0; + + /// The fixed number of results returned by swizzle instructions + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands expected for swizzle instructions + /// @note indices for swizzle are handled separately from the operands, so not included here + static constexpr size_t kNumOperands = 1; + + /// Minimum number of indices expected for swizzle instructions + static constexpr size_t kMinNumIndices = 1; + + /// Maximum number of indices expected for swizzle instructions + static constexpr size_t kMaxNumIndices = 4; + + /// Maximum value of any indices for swizzle instructions + static constexpr uint32_t kMaxIndexValue = 3; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Swizzle(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param object the object being swizzled + /// @param indices the indices to swizzle + Swizzle(Id id, InstructionResult* result, Value* object, VectorRef indices); + + ~Swizzle() override; + + /// @copydoc Instruction::Clone() + Swizzle* Clone(CloneContext& ctx) override; + + /// @returns the object used for the access + Value* Object() { return Operand(kObjectOperandOffset); } + + /// @returns the object used for the access + const Value* Object() const { return Operand(kObjectOperandOffset); } + + /// @returns the swizzle indices + VectorRef Indices() const { return indices_; } + + /// @param indices the new swizzle indices + void SetIndices(VectorRef indices) { indices_ = std::move(indices); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "swizzle"; } + + private: + Vector indices_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_SWIZZLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.cc b/3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.cc new file mode 100644 index 000000000..e007988e6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.cc @@ -0,0 +1,45 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/terminate_invocation.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::TerminateInvocation); + +namespace tint::core::ir { + +TerminateInvocation::TerminateInvocation(Id id) : Base(id) {} + +TerminateInvocation::~TerminateInvocation() = default; + +TerminateInvocation* TerminateInvocation::Clone(CloneContext& ctx) { + return ctx.ir.CreateInstruction(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.h b/3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.h new file mode 100644 index 000000000..5a126250a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/terminate_invocation.h @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TERMINATE_INVOCATION_H_ +#define SRC_TINT_LANG_CORE_IR_TERMINATE_INVOCATION_H_ + +#include + +#include "src/tint/lang/core/ir/terminator.h" + +namespace tint::core::ir { + +/// An terminate invocation instruction in the IR. +class TerminateInvocation final : public Castable { + public: + /// Constructor + /// @param id the instruction id + explicit TerminateInvocation(Id id); + + ~TerminateInvocation() override; + + /// @copydoc Instruction::Clone() + TerminateInvocation* Clone(CloneContext& ctx) override; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "terminate_invocation"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_TERMINATE_INVOCATION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/terminator.cc b/3rdparty/dawn/src/tint/lang/core/ir/terminator.cc new file mode 100644 index 000000000..c511eabb8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/terminator.cc @@ -0,0 +1,40 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/terminator.h" + +#include + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Terminator); + +namespace tint::core::ir { + +Terminator::Terminator(Id id) : Base(id) {} + +Terminator::~Terminator() = default; + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/terminator.h b/3rdparty/dawn/src/tint/lang/core/ir/terminator.h new file mode 100644 index 000000000..f1ff39959 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/terminator.h @@ -0,0 +1,65 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TERMINATOR_H_ +#define SRC_TINT_LANG_CORE_IR_TERMINATOR_H_ + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class Block; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// The base class of all instructions that terminate a block. +class Terminator : public Castable> { + public: + /// Constructor + /// @param id the instruction id + explicit Terminator(Id id); + + ~Terminator() override; + + /// @returns the offset of the arguments in Operands() + virtual size_t ArgsOperandOffset() const { return 0; } + + /// @returns the call arguments + tint::Slice Args() { return operands_.Slice().Offset(ArgsOperandOffset()); } + + /// @returns the call arguments + tint::Slice Args() const { + return operands_.Slice().Offset(ArgsOperandOffset()); + } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_TERMINATOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.cc new file mode 100644 index 000000000..50c9b723c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.cc @@ -0,0 +1,365 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/array_length_from_immediate.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/transform/prepare_immediate_data.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// Immediate data layout contains all immediate block info. + const core::ir::transform::ImmediateDataLayout& immediate_data_layout; + + /// The offset in immediate block for buffer sizes array. + uint32_t buffer_sizes_offset = 0; + + /// The total number of vec4s used to store buffer sizes provided in the immediate block. + uint32_t buffer_sizes_array_elements_num = 0; + + /// The map from binding point to the element index which holds the size of that buffer. + const std::unordered_map& bindpoint_to_size_index; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The construct instruction that creates the array lengths structure in the entry point. + Construct* lengths_constructor = nullptr; + + /// A map from an array function parameter to the function parameter that holds its length. + Hashmap array_param_to_length_param{}; + + /// A map from a function to the structure that holds all of the array lengths. + Hashmap function_to_lengths_structure{}; + + /// A list of structure members for the array lengths structure. + Vector lengths_structure_members{}; + + /// A map from a binding point to its index in the array length structure. + Hashmap bindpoint_to_length_member_index{}; + + /// An ordered list of binding points that map to the structure members. + struct BindingPointInfo { + BindingPoint binding_point{}; + const type::Type* store_type = nullptr; + }; + Vector ordered_bindpoints{}; + + /// A map from block to its containing function. + Hashmap block_to_function{}; + + /// Process the module. + void Process() { + // Seed the block-to-function map with the function entry blocks. + // This is used to determine the owning function for any given instruction. + for (auto& func : ir.functions) { + block_to_function.Add(func->Block(), func); + } + + // Look for and replace calls to the array length builtin. + for (auto* inst : ir.Instructions()) { + if (auto* call = inst->As()) { + if (call->Func() == BuiltinFn::kArrayLength) { + MaybeReplace(call); + } + } + } + + // Create the lengths structure and update all of the places that need to use it. + // We can only do this after we have replaced all of the array length callsites, now that we + // know all of the structure members that we need. + CreateLengthsStructure(); + } + + /// Replace a call to an array length builtin, if the variable appears in the bindpoint map. + /// @param call the arrayLength call to replace + void MaybeReplace(CoreBuiltinCall* call) { + if (auto* length = GetComputedLength(call->Args()[0], call)) { + call->Result()->ReplaceAllUsesWith(length); + call->Destroy(); + } + } + + /// Get the computed length value for a runtime-sized array pointer. + /// @param ptr the pointer to the runtime-sized array + /// @param insertion_point the insertion point for new instructions + /// @returns the computed length, or nullptr if the original builtin should be used + Value* GetComputedLength(Value* ptr, Instruction* insertion_point) { + // Trace back from the value until we reach the originating variable. + while (true) { + if (auto* param = ptr->As()) { + // The length of an array pointer passed as a function parameter will be passed as + // an additional parameter to the function. + return GetArrayLengthParam(param); + } + + if (auto* result = ptr->As()) { + if (auto* var = result->Instruction()->As()) { + // We found the originating variable, so compute its array length. + return ComputeArrayLength(var, insertion_point); + } + if (auto* access = result->Instruction()->As()) { + ptr = access->Object(); + continue; + } + if (auto* let = result->Instruction()->As()) { + ptr = let->Value(); + continue; + } + TINT_IR_UNREACHABLE(ir) << "unhandled source of a storage buffer pointer: " + << result->Instruction()->TypeInfo().name; + } + TINT_IR_UNREACHABLE(ir) + << "unhandled source of a storage buffer pointer: " << ptr->TypeInfo().name; + } + } + + /// Get (or create) the array length parameter that corresponds to an array parameter. + /// @param array_param the array parameter + /// @returns the array length parameter + FunctionParam* GetArrayLengthParam(FunctionParam* array_param) { + return array_param_to_length_param.GetOrAdd(array_param, [&] { + // Add a new parameter to receive the array length. + auto* length = b.FunctionParam("tint_array_length"); + array_param->Function()->AppendParam(length); + + // Update callsites of this function to pass the array length to it. + array_param->Function()->ForEachUseUnsorted([&](core::ir::Usage use) { + if (auto* call = use.instruction->As()) { + // Get the length of the array in the calling function and pass that. + auto* arg = call->Args()[array_param->Index()]; + auto* len = GetComputedLength(arg, call); + if (!len) { + // The originating variable was not in the bindpoint map, so we need to call + // the original arrayLength builtin as the callee is expecting a value. + b.InsertBefore(call, [&] { + len = b.Call(BuiltinFn::kArrayLength, arg)->Result(); + }); + } + call->AppendArg(len); + } + }); + + return length; + }); + } + + /// Get (or create) the array lengths structure for a function. + /// @param func the function that needs the structure + /// @returns the array lengths structure + Value* GetArrayLengthsStructure(Function* func) { + return function_to_lengths_structure.GetOrAdd(func, [&]() -> Value* { + if (func->IsEntryPoint()) { + // Create a placeholder construct instruction for the lengths structure that will be + // filled in later when we know all of the structure members. + TINT_IR_ASSERT(ir, lengths_constructor == nullptr); + lengths_constructor = b.ConstructWithResult(ir.CreateValue()); + lengths_constructor->InsertBefore(func->Block()->Front()); + return lengths_constructor->Result(); + } + + // Add a new parameter to receive the array lengths structure. + // The type is a placeholder and will be filled in later when we create the struct type. + auto* lengths = b.FunctionParam("tint_array_lengths", nullptr); + func->AppendParam(lengths); + + // Update callsites of this function to pass the structure to it. + func->ForEachUseUnsorted([&](core::ir::Usage use) { + if (auto* call = use.instruction->As()) { + // Get the structure in the calling function and pass that. + auto* caller = ContainingFunction(call); + call->AppendArg(GetArrayLengthsStructure(caller)); + } + }); + + return lengths; + }); + } + + /// Compute the array length of the runtime-sized array that is inside a storage buffer + /// variable. If the variable's binding point is not found in the bindpoint map, returns nullptr + /// to indicate that the original arrayLength builtin should be used instead. + /// + /// @param var the storage buffer variable that contains the runtime-sized array + /// @param insertion_point the insertion point for new instructions + /// @returns the length of the array, or nullptr if the original builtin should be used + Value* ComputeArrayLength(Var* var, Instruction* insertion_point) { + auto binding = var->BindingPoint(); + TINT_IR_ASSERT(ir, binding); + + auto idx_it = bindpoint_to_size_index.find(*binding); + if (idx_it == bindpoint_to_size_index.end()) { + // If the bindpoint_to_size_index map does not contain an entry for the storage buffer, + // then we preserve the arrayLength() call. + return nullptr; + } + + // Get the index of the structure member that holds the length for this binding point, + // creating the structure member descriptor if necessary. + auto member_index = bindpoint_to_length_member_index.GetOrAdd(*binding, [&]() { + auto index = static_cast(lengths_structure_members.Length()); + auto name = "tint_array_length_" + std::to_string(binding->group) + "_" + + std::to_string(binding->binding); + lengths_structure_members.Push(type::Manager::StructMemberDesc{ + .name = ir.symbols.Register(name), + .type = ty.u32(), + }); + ordered_bindpoints.Push(BindingPointInfo{ + .binding_point = *binding, + .store_type = var->Result()->Type()->UnwrapPtr(), + }); + return index; + }); + + // Extract the length from the structure. + auto* length = b.Access(GetArrayLengthsStructure(ContainingFunction(insertion_point)), + u32(member_index)); + length->InsertBefore(insertion_point); + return length->Result(); + } + + /// Create the structure to hold the array lengths and fill in the construct instruction that + /// sets all of the length values. + void CreateLengthsStructure() { + if (lengths_structure_members.IsEmpty()) { + return; + } + + // Create the lengths structure. + auto* lengths_struct = ty.Struct(ir.symbols.New("tint_array_lengths_struct"), + std::move(lengths_structure_members)); + + // Update all of the function parameters that need to receive the lengths structure. + for (auto s : function_to_lengths_structure) { + if (auto* param = s.value->As()) { + param->SetType(lengths_struct); + } + } + + // Insert code at the beginning of the entry point to initialize the array length members. + if (lengths_constructor == nullptr) { + return; + } + lengths_constructor->Result()->SetType(lengths_struct); + b.InsertBefore(lengths_constructor->Block()->Front(), [&] { + Vector constructor_values; + for (auto info : ordered_bindpoints) { + TINT_IR_ASSERT(ir, bindpoint_to_size_index.contains(info.binding_point)); + TINT_IR_ASSERT(ir, bindpoint_to_length_member_index.Contains(info.binding_point)); + + // Load the total storage buffer size from the immediate block. + // The sizes are packed into vec4s to satisfy the 16-byte alignment requirement for + // array elements in immediate block, so we have to find the vector and element that + // correspond to the index that we want. + const uint32_t size_index = bindpoint_to_size_index.at(info.binding_point); + const uint32_t array_index = size_index / 4; + const uint32_t vec_index = size_index % 4; + auto* buffer_sizes = b.Access( + ty.ptr(immediate, ty.array(ty.vec4u(), buffer_sizes_array_elements_num)), + immediate_data_layout.var, + u32(immediate_data_layout.IndexOf(buffer_sizes_offset))); + auto* vec_ptr = b.Access(ty.ptr(immediate, ty.vec4u()), buffer_sizes->Result(), + u32(array_index)); + auto* total_buffer_size = b.LoadVectorElement(vec_ptr, u32(vec_index))->Result(); + + // Calculate actual array length: + // total_buffer_size - array_offset + // array_length = -------------------------------- + // array_stride + auto* array_size = total_buffer_size; + const type::Array* array_type = nullptr; + if (auto* str = info.store_type->As()) { + // The variable is a struct, so subtract the byte offset of the array member. + auto* member = str->Members().Back(); + array_type = member->Type()->As(); + array_size = b.Subtract(total_buffer_size, u32(member->Offset()))->Result(); + } else { + array_type = info.store_type->As(); + } + TINT_IR_ASSERT(ir, array_type); + + auto* length = b.Divide(array_size, u32(array_type->ImplicitStride()))->Result(); + constructor_values.Push(length); + } + lengths_constructor->SetOperands(std::move(constructor_values)); + }); + } + + /// Get the function that contains an instruction. + /// @param inst the instruction + /// @returns the function + core::ir::Function* ContainingFunction(core::ir::Instruction* inst) { + return block_to_function.GetOrAdd(inst->Block(), [&] { // + return ContainingFunction(inst->Block()->Parent()); + }); + } + + /// @returns true if the transformed module needs a storage buffer sizes UBO + bool NeedsStorageBufferSizes() { + return !lengths_structure_members.IsEmpty() && lengths_constructor != nullptr; + } +}; + +} // namespace + +Result ArrayLengthFromImmediates( + Module& ir, + const core::ir::transform::ImmediateDataLayout& immediate_data_layout, + const uint32_t buffer_sizes_offset, + const uint32_t buffer_sizes_array_elements_num, + const std::unordered_map& bindpoint_to_size_index) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.ArrayLengthFromImmediates", + kArrayLengthFromImmediateCapabilities)); + + State state{ir, immediate_data_layout, buffer_sizes_offset, buffer_sizes_array_elements_num, + bindpoint_to_size_index}; + state.Process(); + + ArrayLengthFromImmediateResult result; + result.needs_storage_buffer_sizes = state.NeedsStorageBufferSizes(); + return result; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.h new file mode 100644 index 000000000..eeacc4125 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_immediate.h @@ -0,0 +1,89 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_IMMEDIATE_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_IMMEDIATE_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { +struct ImmediateDataLayout; + +/// The capabilities that the transform can support. +const Capabilities kArrayLengthFromImmediateCapabilities{Capability::kAllowDuplicateBindings}; + +/// The result of running the ArrayLengthFromUniform transform. +struct ArrayLengthFromImmediateResult { + /// `true` if the transformed module needs the storage buffer sizes immediate data. + bool needs_storage_buffer_sizes = false; +}; + +/// ArrayLengthFromImmediates is a transform that replaces calls to the arrayLength() builtin by +/// calculating the array length from the total size of the storage buffer, which is received via +/// immediate blocks. +/// +/// The generated immediate blocks will have the form: +/// ``` +/// @group(0) @binding(30) +/// struct tint_immediate_data_struct { +/// ... +/// buffer_sizes: array, 8>; // offset is provided via config +// }; +/// var tint_immediate_data : tint_immediate_data_struct; +/// ``` +/// The offset of `buffer_sizes` in the immediate block is provided by config. +/// The transform config also defines the mapping from a storage buffer's `BindingPoint` to the +/// element index that will be used to get the size of that buffer. +/// +/// @param module the module to transform +/// @param immediate_data_layout The immediate data layout information. +/// @param bindpoint_to_size_index The map from binding point to an index which holds the size +/// of that buffer. +/// @param buffer_sizes_offset The offset in immediate block where buffer sizes start. +/// @param buffer_sizes_array_elements_num the number of vec4s used to store buffer sizes that will +/// be set into the immediate block. +/// @returns the transform result or failure +/// TODO(crbug.com/366291600): Replace ArrayLengthFromUniform. +Result ArrayLengthFromImmediates( + Module& module, + const core::ir::transform::ImmediateDataLayout& immediate_data_layout, + const uint32_t buffer_sizes_offset, + const uint32_t buffer_sizes_array_elements_num, + const std::unordered_map& bindpoint_to_size_index); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_IMMEDIATE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.cc new file mode 100644 index 000000000..9337f434c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.cc @@ -0,0 +1,375 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/array_length_from_uniform.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The binding point to use for the uniform buffer. + BindingPoint ubo_binding; + + /// The map from binding point to the element index which holds the size of that buffer. + const std::unordered_map& bindpoint_to_size_index; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The uniform buffer variable that holds the total size of each storage buffer. + Var* buffer_sizes_var = nullptr; + + /// The construct instruction that creates the array lengths structure in the entry point. + Construct* lengths_constructor = nullptr; + + /// A map from an array function parameter to the function parameter that holds its length. + Hashmap array_param_to_length_param{}; + + /// A map from a function to the structure that holds all of the array lengths. + Hashmap function_to_lengths_structure{}; + + /// A list of structure members for the array lengths structure. + Vector lengths_structure_members{}; + + /// A map from a binding point to its index in the array length structure. + Hashmap bindpoint_to_length_member_index{}; + + /// An ordered list of binding points that map to the structure members. + struct BindingPointInfo { + BindingPoint binding_point{}; + const type::Type* store_type = nullptr; + }; + Vector ordered_bindpoints{}; + + /// A map from block to its containing function. + Hashmap block_to_function{}; + + /// Process the module. + void Process() { + // Seed the block-to-function map with the function entry blocks. + // This is used to determine the owning function for any given instruction. + for (auto& func : ir.functions) { + block_to_function.Add(func->Block(), func); + } + + // Look for and replace calls to the array length builtin. + for (auto* inst : ir.Instructions()) { + if (auto* call = inst->As()) { + if (call->Func() == BuiltinFn::kArrayLength) { + MaybeReplace(call); + } + } + } + + // Create the lengths structure and update all of the places that need to use it. + // We can only do this after we have replaced all of the array length callsites, now that we + // know all of the structure members that we need. + CreateLengthsStructure(); + } + + /// Replace a call to an array length builtin, if the variable appears in the bindpoint map. + /// @param call the arrayLength call to replace + void MaybeReplace(CoreBuiltinCall* call) { + if (auto* length = GetComputedLength(call->Args()[0], call)) { + call->Result()->ReplaceAllUsesWith(length); + call->Destroy(); + } + } + + /// Get the computed length value for a runtime-sized array pointer. + /// @param ptr the pointer to the runtime-sized array + /// @param insertion_point the insertion point for new instructions + /// @returns the computed length, or nullptr if the original builtin should be used + Value* GetComputedLength(Value* ptr, Instruction* insertion_point) { + // Trace back from the value until we reach the originating variable. + while (true) { + if (auto* param = ptr->As()) { + // The length of an array pointer passed as a function parameter will be passed as + // an additional parameter to the function. + return GetArrayLengthParam(param); + } + + if (auto* result = ptr->As()) { + if (auto* var = result->Instruction()->As()) { + // We found the originating variable, so compute its array length. + return ComputeArrayLength(var, insertion_point); + } + if (auto* access = result->Instruction()->As()) { + ptr = access->Object(); + continue; + } + if (auto* let = result->Instruction()->As()) { + ptr = let->Value(); + continue; + } + TINT_IR_UNREACHABLE(ir) << "unhandled source of a storage buffer pointer: " + << result->Instruction()->TypeInfo().name; + } + TINT_IR_UNREACHABLE(ir) + << "unhandled source of a storage buffer pointer: " << ptr->TypeInfo().name; + } + } + + /// Get (or create) the array length parameter that corresponds to an array parameter. + /// @param array_param the array parameter + /// @returns the array length parameter + FunctionParam* GetArrayLengthParam(FunctionParam* array_param) { + return array_param_to_length_param.GetOrAdd(array_param, [&] { + // Add a new parameter to receive the array length. + auto* length = b.FunctionParam("tint_array_length"); + array_param->Function()->AppendParam(length); + + // Update callsites of this function to pass the array length to it. + array_param->Function()->ForEachUseUnsorted([&](core::ir::Usage use) { + if (auto* call = use.instruction->As()) { + // Get the length of the array in the calling function and pass that. + auto* arg = call->Args()[array_param->Index()]; + auto* len = GetComputedLength(arg, call); + if (!len) { + // The originating variable was not in the bindpoint map, so we need to call + // the original arrayLength builtin as the callee is expecting a value. + b.InsertBefore(call, [&] { + len = b.Call(BuiltinFn::kArrayLength, arg)->Result(); + }); + } + call->AppendArg(len); + } + }); + + return length; + }); + } + + /// Get (or create) the array lengths structure for a function. + /// @param func the function that needs the structure + /// @returns the array lengths structure + Value* GetArrayLengthsStructure(Function* func) { + return function_to_lengths_structure.GetOrAdd(func, [&]() -> Value* { + if (func->IsEntryPoint()) { + // Create a placeholder construct instruction for the lengths structure that will be + // filled in later when we know all of the structure members. + TINT_IR_ASSERT(ir, lengths_constructor == nullptr); + lengths_constructor = b.ConstructWithResult(ir.CreateValue()); + lengths_constructor->InsertBefore(func->Block()->Front()); + return lengths_constructor->Result(); + } + + // Add a new parameter to receive the array lengths structure. + // The type is a placeholder and will be filled in later when we create the struct type. + auto* lengths = b.FunctionParam("tint_array_lengths", nullptr); + func->AppendParam(lengths); + + // Update callsites of this function to pass the structure to it. + func->ForEachUseUnsorted([&](core::ir::Usage use) { + if (auto* call = use.instruction->As()) { + // Get the structure in the calling function and pass that. + auto* caller = ContainingFunction(call); + call->AppendArg(GetArrayLengthsStructure(caller)); + } + }); + + return lengths; + }); + } + + /// Compute the array length of the runtime-sized array that is inside a storage buffer + /// variable. If the variable's binding point is not found in the bindpoint map, returns nullptr + /// to indicate that the original arrayLength builtin should be used instead. + /// + /// @param var the storage buffer variable that contains the runtime-sized array + /// @param insertion_point the insertion point for new instructions + /// @returns the length of the array, or nullptr if the original builtin should be used + Value* ComputeArrayLength(Var* var, Instruction* insertion_point) { + auto binding = var->BindingPoint(); + TINT_IR_ASSERT(ir, binding); + + auto idx_it = bindpoint_to_size_index.find(*binding); + if (idx_it == bindpoint_to_size_index.end()) { + // If the bindpoint_to_size_index map does not contain an entry for the storage buffer, + // then we preserve the arrayLength() call. + return nullptr; + } + + // Get the index of the structure member that holds the length for this binding point, + // creating the structure member descriptor if necessary. + auto member_index = bindpoint_to_length_member_index.GetOrAdd(*binding, [&]() { + auto index = static_cast(lengths_structure_members.Length()); + auto name = "tint_array_length_" + std::to_string(binding->group) + "_" + + std::to_string(binding->binding); + lengths_structure_members.Push(type::Manager::StructMemberDesc{ + .name = ir.symbols.Register(name), + .type = ty.u32(), + }); + ordered_bindpoints.Push(BindingPointInfo{ + .binding_point = *binding, + .store_type = var->Result()->Type()->UnwrapPtr(), + }); + return index; + }); + + // Extract the length from the structure. + auto* length = b.Access(GetArrayLengthsStructure(ContainingFunction(insertion_point)), + u32(member_index)); + length->InsertBefore(insertion_point); + return length->Result(); + } + + /// Get (or create, on first call) the uniform buffer that contains the storage buffer sizes. + /// @returns the uniform buffer pointer + Value* BufferSizes() { + if (buffer_sizes_var) { + return buffer_sizes_var->Result(); + } + + // Find the largest index declared in the map, in order to determine the number of elements + // needed in the array of buffer sizes. + // The buffer sizes will be packed into vec4s to satisfy the 16-byte alignment requirement + // for array elements in uniform buffers. + uint32_t max_index = 0; + for (auto& entry : bindpoint_to_size_index) { + max_index = std::max(max_index, entry.second); + } + uint32_t num_elements = (max_index / 4) + 1; + b.Append(ir.root_block, [&] { + buffer_sizes_var = b.Var("tint_storage_buffer_sizes", + ty.ptr(ty.array(ty.vec4u(), num_elements))); + }); + buffer_sizes_var->SetBindingPoint(ubo_binding.group, ubo_binding.binding); + return buffer_sizes_var->Result(); + } + + /// Create the structure to hold the array lengths and fill in the construct instruction that + /// sets all of the length values. + void CreateLengthsStructure() { + if (lengths_structure_members.IsEmpty()) { + return; + } + + // Create the lengths structure. + auto* lengths_struct = ty.Struct(ir.symbols.New("tint_array_lengths_struct"), + std::move(lengths_structure_members)); + + // Update all of the function parameters that need to receive the lengths structure. + for (auto s : function_to_lengths_structure) { + if (auto* param = s.value->As()) { + param->SetType(lengths_struct); + } + } + + // Insert code at the beginning of the entry point to initialize the array length members. + if (lengths_constructor == nullptr) { + return; + } + lengths_constructor->Result()->SetType(lengths_struct); + b.InsertBefore(lengths_constructor->Block()->Front(), [&] { + Vector constructor_values; + for (auto info : ordered_bindpoints) { + TINT_IR_ASSERT(ir, bindpoint_to_size_index.contains(info.binding_point)); + TINT_IR_ASSERT(ir, bindpoint_to_length_member_index.Contains(info.binding_point)); + + // Load the total storage buffer size from the uniform buffer. + // The sizes are packed into vec4s to satisfy the 16-byte alignment requirement for + // array elements in uniform buffers, so we have to find the vector and element that + // correspond to the index that we want. + const uint32_t size_index = bindpoint_to_size_index.at(info.binding_point); + const uint32_t array_index = size_index / 4; + const uint32_t vec_index = size_index % 4; + auto* vec_ptr = b.Access>>(BufferSizes(), u32(array_index)); + auto* total_buffer_size = b.LoadVectorElement(vec_ptr, u32(vec_index))->Result(); + + // Calculate actual array length: + // total_buffer_size - array_offset + // array_length = -------------------------------- + // array_stride + auto* array_size = total_buffer_size; + const type::Array* array_type = nullptr; + if (auto* str = info.store_type->As()) { + // The variable is a struct, so subtract the byte offset of the array member. + auto* member = str->Members().Back(); + array_type = member->Type()->As(); + array_size = b.Subtract(total_buffer_size, u32(member->Offset()))->Result(); + } else { + array_type = info.store_type->As(); + } + TINT_IR_ASSERT(ir, array_type); + + auto* length = b.Divide(array_size, u32(array_type->ImplicitStride()))->Result(); + constructor_values.Push(length); + } + lengths_constructor->SetOperands(std::move(constructor_values)); + }); + } + + /// Get the function that contains an instruction. + /// @param inst the instruction + /// @returns the function + core::ir::Function* ContainingFunction(core::ir::Instruction* inst) { + return block_to_function.GetOrAdd(inst->Block(), [&] { // + return ContainingFunction(inst->Block()->Parent()); + }); + } + + /// @returns true if the transformed module needs a storage buffer sizes UBO + bool NeedsStorageBufferSizes() { return buffer_sizes_var != nullptr; } +}; + +} // namespace + +Result ArrayLengthFromUniform( + Module& ir, + BindingPoint ubo_binding, + const std::unordered_map& bindpoint_to_size_index) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.ArrayLengthFromUniform", + kArrayLengthFromUniformCapabilities)); + + State state{ir, ubo_binding, bindpoint_to_size_index}; + state.Process(); + + ArrayLengthFromUniformResult result; + result.needs_storage_buffer_sizes = state.NeedsStorageBufferSizes(); + return result; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.h new file mode 100644 index 000000000..e6e2cb1f4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/array_length_from_uniform.h @@ -0,0 +1,77 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_ + +#include +#include "src/tint/lang/core/ir/validator.h" + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kArrayLengthFromUniformCapabilities{Capability::kAllowDuplicateBindings}; + +/// The result of running the ArrayLengthFromUniform transform. +struct ArrayLengthFromUniformResult { + /// `true` if the transformed module needs the storage buffer sizes UBO. + bool needs_storage_buffer_sizes = false; +}; + +/// ArrayLengthFromUniform is a transform that replaces calls to the arrayLength() builtin by +/// calculating the array length from the total size of the storage buffer, which is received via a +/// uniform buffer. +/// +/// The generated uniform buffer will have the form: +/// ``` +/// @group(0) @binding(30) +/// var buffer_size_ubo : array, 8>; +/// ``` +/// The binding group and number used for this uniform buffer is provided via the transform config. +/// The transform config also defines the mapping from a storage buffer's `BindingPoint` to the +/// element index that will be used to get the size of that buffer. +/// +/// @param module the module to transform +/// @param ubo_binding the binding point to use for the uniform buffer +/// @param bindpoint_to_size_index the map from binding point to an index which holds the size +/// @returns the transform result or failure +Result ArrayLengthFromUniform( + Module& module, + BindingPoint ubo_binding, + const std::unordered_map& bindpoint_to_size_index); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc new file mode 100644 index 000000000..571c55223 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc @@ -0,0 +1,250 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/storage_texture.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + // Find module-scope variables that need to be replaced. + if (!ir.root_block->IsEmpty()) { + Vector to_remove; + for (auto inst : *ir.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + auto* ptr = var->Result()->Type()->As(); + if (!ptr) { + continue; + } + auto* storage_texture = ptr->StoreType()->As(); + if (storage_texture && + storage_texture->TexelFormat() == core::TexelFormat::kBgra8Unorm) { + ReplaceVar(var, storage_texture); + to_remove.Push(var); + continue; + } + + auto* texel_buffer = ptr->StoreType()->As(); + if (texel_buffer && texel_buffer->TexelFormat() == core::TexelFormat::kBgra8Unorm) { + ReplaceVar(var, texel_buffer); + to_remove.Push(var); + } + } + for (auto* remove : to_remove) { + remove->Destroy(); + } + } + + // Find function parameters that need to be replaced. + for (auto& func : ir.functions) { + for (uint32_t index = 0; index < func->Params().Length(); index++) { + auto* param = func->Params()[index]; + auto* storage_texture = param->Type()->As(); + if (storage_texture && + storage_texture->TexelFormat() == core::TexelFormat::kBgra8Unorm) { + ReplaceParameter(func, param, index, storage_texture); + continue; + } + + auto* texel_buffer = param->Type()->As(); + if (texel_buffer && texel_buffer->TexelFormat() == core::TexelFormat::kBgra8Unorm) { + ReplaceParameter(func, param, index, texel_buffer); + } + } + } + } + + /// Replace a variable declaration with one that uses rgba8unorm instead of bgra8unorm. + /// @param old_var the variable declaration to replace + /// @param bgra8 the bgra8unorm texture type + void ReplaceVar(Var* old_var, const core::type::StorageTexture* bgra8) { + // Redeclare the variable with a rgba8unorm texel format. + auto* rgba8 = + ty.storage_texture(bgra8->Dim(), core::TexelFormat::kRgba8Unorm, bgra8->Access()); + auto* new_var = b.Var(ty.ptr(handle, rgba8)); + auto bp = old_var->BindingPoint(); + new_var->SetBindingPoint(bp->group, bp->binding); + new_var->InsertBefore(old_var); + if (auto name = ir.NameOf(old_var)) { + ir.SetName(new_var, name.NameView()); + } + + // Replace all uses of the old variable with the new one. + ReplaceUses(old_var->Result(), new_var->Result()); + } + + /// Replace a variable declaration with one that uses rgba8unorm instead of bgra8unorm. + /// @param old_var the variable declaration to replace + /// @param bgra8 the bgra8unorm texel buffer type + void ReplaceVar(Var* old_var, const core::type::TexelBuffer* bgra8) { + // Redeclare the variable with a rgba8unorm texel format. + auto* rgba8 = ty.texel_buffer(core::TexelFormat::kRgba8Unorm, bgra8->Access()); + auto* new_var = b.Var(ty.ptr(handle, rgba8)); + auto bp = old_var->BindingPoint(); + new_var->SetBindingPoint(bp->group, bp->binding); + new_var->InsertBefore(old_var); + if (auto name = ir.NameOf(old_var)) { + ir.SetName(new_var, name.NameView()); + } + + // Replace all uses of the old variable with the new one. + ReplaceUses(old_var->Result(), new_var->Result()); + } + + /// Replace a function parameter with one that uses rgba8unorm instead of bgra8unorm. + /// @param func the function + /// @param old_param the function parameter to replace + /// @param index the index of the function parameter + /// @param bgra8 the bgra8unorm texture type + void ReplaceParameter(Function* func, + FunctionParam* old_param, + uint32_t index, + const core::type::StorageTexture* bgra8) { + // Redeclare the parameter with a rgba8unorm texel format. + auto* rgba8 = + ty.storage_texture(bgra8->Dim(), core::TexelFormat::kRgba8Unorm, bgra8->Access()); + auto* new_param = b.FunctionParam(rgba8); + if (auto name = ir.NameOf(old_param)) { + ir.SetName(new_param, name.NameView()); + } + + Vector new_params = func->Params(); + new_params[index] = new_param; + func->SetParams(std::move(new_params)); + + // Replace all uses of the old parameter with the new one. + ReplaceUses(old_param, new_param); + } + + /// Replace a function parameter with one that uses rgba8unorm instead of bgra8unorm. + /// @param func the function + /// @param old_param the function parameter to replace + /// @param index the index of the function parameter + /// @param bgra8 the bgra8unorm texel buffer type + void ReplaceParameter(Function* func, + FunctionParam* old_param, + uint32_t index, + const core::type::TexelBuffer* bgra8) { + // Redeclare the parameter with a rgba8unorm texel format. + auto* rgba8 = ty.texel_buffer(core::TexelFormat::kRgba8Unorm, bgra8->Access()); + auto* new_param = b.FunctionParam(rgba8); + if (auto name = ir.NameOf(old_param)) { + ir.SetName(new_param, name.NameView()); + } + + Vector new_params = func->Params(); + new_params[index] = new_param; + func->SetParams(std::move(new_params)); + + // Replace all uses of the old parameter with the new one. + ReplaceUses(old_param, new_param); + } + + /// Recursively replace the uses of @p value with @p new_value. + /// @param old_value the value whose usages should be replaced + /// @param new_value the value to use instead + void ReplaceUses(Value* old_value, Value* new_value) { + old_value->ForEachUseUnsorted([&](Usage use) { + tint::Switch( + use.instruction, + [&](Load* load) { + // Replace load instructions with new ones that have the updated type. + auto* new_load = b.Load(new_value); + new_load->InsertBefore(load); + ReplaceUses(load->Result(), new_load->Result()); + load->Destroy(); + }, + [&](CoreBuiltinCall* call) { + // Replace arguments to builtin functions and add swizzles if necessary. + call->SetOperand(use.operand_index, new_value); + if (call->Func() == core::BuiltinFn::kTextureStore) { + // Swizzle the value argument of a `textureStore()` builtin. + uint32_t index = 2u; + if (auto* tex = old_value->Type()->As()) { + index = core::type::IsTextureArray(tex->Dim()) ? 3u : 2u; + } + auto* value = call->Args()[index]; + auto* swizzle = b.Swizzle(value->Type(), value, Vector{2u, 1u, 0u, 3u}); + swizzle->InsertBefore(call); + call->SetOperand(index, swizzle->Result()); + } else if (call->Func() == core::BuiltinFn::kTextureLoad) { + // Swizzle the result of a `textureLoad()` builtin. + auto* swizzle = + b.Swizzle(call->Result()->Type(), nullptr, Vector{2u, 1u, 0u, 3u}); + call->Result()->ReplaceAllUsesWith(swizzle->Result()); + swizzle->InsertAfter(call); + swizzle->SetOperand(Swizzle::kObjectOperandOffset, call->Result()); + } + }, + [&](UserCall* call) { + // Just replace arguments to user functions and then stop. + call->SetOperand(use.operand_index, new_value); + }, + TINT_ICE_ON_NO_MATCH); + }); + } +}; + +} // namespace + +Result Bgra8UnormPolyfill(Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.Bgra8UnormPolyfill", kBgra8UnormPolyfillCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h new file mode 100644 index 000000000..de945ee51 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h @@ -0,0 +1,56 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_BGRA8UNORM_POLYFILL_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BGRA8UNORM_POLYFILL_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kBgra8UnormPolyfillCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// Bgra8UnormPolyfill is a transform that changes the texel format of storage textures from +/// bgra8unorm to rgba8unorm, inserting swizzles before and after texture accesses as necessary. +/// @param module the module to transform +/// @returns success or failure +Result Bgra8UnormPolyfill(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_BGRA8UNORM_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.cc new file mode 100644 index 000000000..ea5e18b2d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.cc @@ -0,0 +1,210 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/binary_polyfill.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The polyfill config. + const BinaryPolyfillConfig& config; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// Map from integer type to its divide helper function. + Hashmap int_div_helpers{}; + + /// Map from integer type to its modulo helper function. + Hashmap int_mod_helpers{}; + + /// Process the module. + void Process() { + // Find the binary instructions that need to be polyfilled. + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* binary = inst->As()) { + switch (binary->Op()) { + case BinaryOp::kDivide: + case BinaryOp::kModulo: + if (config.int_div_mod && + binary->Result()->Type()->IsIntegerScalarOrVector()) { + worklist.Push(binary); + } + break; + case BinaryOp::kShiftLeft: + case BinaryOp::kShiftRight: + if (config.bitshift_modulo) { + worklist.Push(binary); + } + break; + default: + break; + } + } + } + + // Polyfill the binary instructions that we found. + for (auto* binary : worklist) { + switch (binary->Op()) { + case BinaryOp::kDivide: + case BinaryOp::kModulo: + IntDivMod(binary); + break; + case BinaryOp::kShiftLeft: + case BinaryOp::kShiftRight: + MaskShiftAmount(binary); + break; + default: + break; + } + } + } + + /// Replace an integer divide or modulo with a call to helper function that prevents + /// divide-by-zero and signed integer overflow. + /// @param binary the binary instruction + void IntDivMod(ir::CoreBinary* binary) { + auto* result_ty = binary->Result()->Type(); + bool is_div = binary->Op() == BinaryOp::kDivide; + bool is_signed = result_ty->IsSignedIntegerScalarOrVector(); + + auto& helpers = is_div ? int_div_helpers : int_mod_helpers; + auto* helper = helpers.GetOrAdd(result_ty, [&] { + // Generate a name for the helper function. + StringStream name; + name << "tint_" << (is_div ? "div_" : "mod_"); + if (auto* vec = result_ty->As()) { + name << "v" << vec->Width() << vec->Type()->FriendlyName(); + } else { + name << result_ty->FriendlyName(); + } + + // Create the helper function. + auto* func = b.Function(name.str(), result_ty); + auto* lhs = b.FunctionParam("lhs", result_ty); + auto* rhs = b.FunctionParam("rhs", result_ty); + func->SetParams({lhs, rhs}); + b.Append(func->Block(), [&] { + // Generate constants for zero and one with types that match the result type. + ir::Constant* one = nullptr; + ir::Constant* zero = nullptr; + if (is_signed) { + one = b.MatchWidth(1_i, result_ty); + zero = b.MatchWidth(0_i, result_ty); + } else { + one = b.MatchWidth(1_u, result_ty); + zero = b.MatchWidth(0_u, result_ty); + } + + // Select either the RHS or a constant one value if the RHS is zero. + // If this is a signed operation, we also check for `INT_MIN / -1`. + auto* cond = b.Equal(rhs, zero); + if (is_signed) { + auto* lowest = b.MatchWidth(i32::Lowest(), result_ty); + auto* minus_one = b.MatchWidth(-1_i, result_ty); + auto* lhs_is_lowest = b.Equal(lhs, lowest); + auto* rhs_is_minus_one = b.Equal(rhs, minus_one); + cond = b.Or(cond, b.And(lhs_is_lowest, rhs_is_minus_one)); + } + auto* rhs_or_one = b.Call(result_ty, core::BuiltinFn::kSelect, rhs, one, cond); + + if (binary->Op() == BinaryOp::kDivide) { + // Perform the divide with the modified RHS. + b.Return(func, b.Divide(lhs, rhs_or_one)->Result()); + } else if (binary->Op() == BinaryOp::kModulo) { + // Calculate the modulo manually, as modulo with negative operands is undefined + // behavior for many backends: + // result = lhs - ((lhs / rhs_or_one) * rhs_or_one) + auto* whole = b.Divide(lhs, rhs_or_one); + auto* remainder = b.Subtract(lhs, b.Multiply(whole, rhs_or_one)); + b.Return(func, remainder->Result()); + } + }); + return func; + }); + + /// Helper to splat a value to match the vector width of the result type if necessary. + auto maybe_splat = [&](ir::Value* value) -> ir::Value* { + if (value->Type()->Is() && result_ty->Is()) { + return b.Construct(result_ty, value)->Result(); + } + return value; + }; + + // Call the helper function, splatting the arguments to match the target vector width. + b.InsertBefore(binary, [&] { + auto* lhs = maybe_splat(binary->LHS()); + auto* rhs = maybe_splat(binary->RHS()); + b.CallWithResult(binary->DetachResult(), helper, lhs, rhs); + }); + binary->Destroy(); + } + + /// Mask the RHS of a shift instruction to ensure it is modulo the bitwidth of the LHS. + /// @param binary the binary instruction + void MaskShiftAmount(ir::CoreBinary* binary) { + auto* lhs = binary->LHS(); + auto* rhs = binary->RHS(); + auto mask = u32(lhs->Type()->DeepestElement()->Size() * 8 - 1); + auto* masked = b.And(rhs, b.MatchWidth(mask, rhs->Type())); + masked->InsertBefore(binary); + binary->SetOperand(ir::CoreBinary::kRhsOperandOffset, masked->Result()); + } +}; + +} // namespace + +Result BinaryPolyfill(Module& ir, const BinaryPolyfillConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.BinaryPolyfill", kBinaryPolyfillCapabilities)); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.h new file mode 100644 index 000000000..c6626cd01 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/binary_polyfill.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_BINARY_POLYFILL_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BINARY_POLYFILL_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kBinaryPolyfillCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// The set of polyfills that should be applied. +struct BinaryPolyfillConfig { + /// Should the RHS of a shift be masked to make it modulo the bit-width of the LHS? + bool bitshift_modulo = false; + /// Should integer divide and modulo be polyfilled to avoid DBZ and integer overflow? + bool int_div_mod = false; + + /// Reflection for this class + TINT_REFLECT(BinaryPolyfillConfig, bitshift_modulo, int_div_mod); +}; + +/// BinaryPolyfill is a transform that modifies binary instructions to prepare them for raising to +/// backend dialects that may have different semantics. +/// @param module the module to transform +/// @param config the polyfill configuration +/// @returns success or failure +Result BinaryPolyfill(Module& module, const BinaryPolyfillConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_BINARY_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.cc new file mode 100644 index 000000000..ad394b0c6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.cc @@ -0,0 +1,83 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/binding_remapper.h" + +#include + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" + +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +void Run(ir::Module& ir, const std::unordered_map& binding_points) { + if (binding_points.empty()) { + return; + } + if (ir.root_block->IsEmpty()) { + return; + } + + // Find binding resources. + for (auto inst : *ir.root_block) { + auto* var = inst->As(); + if (!var || !var->Alive()) { + continue; + } + + auto bp = var->BindingPoint(); + if (!bp) { + continue; + } + + // Replace group and binding index if requested. + auto to = binding_points.find(bp.value()); + if (to != binding_points.end()) { + var->SetBindingPoint(to->second.group, to->second.binding); + } + } +} + +} // namespace + +Result BindingRemapper( + Module& ir, + const std::unordered_map& binding_points) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.BindingRemapper", kBindingRemapperCapabilities)); + + Run(ir, binding_points); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.h new file mode 100644 index 000000000..c9348ac1b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/binding_remapper.h @@ -0,0 +1,63 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_BINDING_REMAPPER_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BINDING_REMAPPER_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +/// +/// Note: BindingRemapper is the transform that introduces duplicate +/// bindings, so in theory shouldn't need the capability to allow +/// them. +const Capabilities kBindingRemapperCapabilities{ + Capability::kAllow8BitIntegers, +}; + +/// BindingRemapper is a transform that remaps binding point indices and access controls. +/// @param module the module to transform +/// @param binding_points the remapping data +/// @returns success or failure +Result BindingRemapper( + Module& module, + const std::unordered_map& binding_points); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_BINDING_REMAPPER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.cc new file mode 100644 index 000000000..9a060448a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.cc @@ -0,0 +1,129 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/block_decorated_structs.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/struct.h" + +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +void Run(Module& ir) { + Builder builder{ir}; + type::Manager& ty{ir.Types()}; + + if (ir.root_block->IsEmpty()) { + return; + } + + // Loop over module-scope declarations, looking for storage or uniform buffers. + Vector buffer_variables; + for (auto inst : *ir.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + auto* ptr = var->Result()->Type()->As(); + if (!ptr || !core::IsHostShareable(ptr->AddressSpace())) { + continue; + } + buffer_variables.Push(var); + } + + // Now process the buffer variables. + for (auto* var : buffer_variables) { + auto* ptr = var->Result()->Type()->As(); + auto* store_ty = ptr->StoreType(); + + if (auto* str = store_ty->As()) { + if (str->StructFlags().Contains(type::kBlock)) { + // The struct already has a block attribute, so we don't need to do anything here. + continue; + } + if (!str->HasFixedFootprint()) { + // We know the original struct will only ever be used as the store type of a buffer, + // so just mark it as a block-decorated struct. + // TODO(crbug.com/tint/745): Remove the const_cast. + const_cast(str)->SetStructFlag(type::kBlock); + continue; + } + } + + // The original struct might be used in other places, so create a new block-decorated + // struct that wraps the original struct. + // Use a consistent name for the inner struct member to satisfy GLSL's interface matching + // rules. Derive the struct name from the variable name to preserve any prefixes provided by + // Dawn, which are needed to avoid clashing between vertex and fragment shaders in GLSL. + auto inner_name = ir.symbols.Register("inner"); + Symbol wrapper_name; + if (auto var_name = ir.NameOf(var)) { + wrapper_name = ir.symbols.New(var_name.Name() + "_block"); + } else { + wrapper_name = ir.symbols.New(); + } + auto* block_struct = ty.Struct(wrapper_name, {{inner_name, store_ty}}); + block_struct->SetStructFlag(core::type::StructFlag::kBlock); + + // Replace the old variable declaration with one that uses the block-decorated struct type. + auto* new_var = builder.Var(ty.ptr(ptr->AddressSpace(), block_struct, ptr->Access())); + if (var->BindingPoint()) { + new_var->SetBindingPoint(var->BindingPoint()->group, var->BindingPoint()->binding); + } + var->ReplaceWith(new_var); + + // Replace uses of the old variable. + // The structure has been wrapped, so replace all uses of the old variable with a member + // accessor on the new variable. + var->Result()->ReplaceAllUsesWith([&](Usage use) -> Value* { + auto* access = builder.Access(var->Result()->Type(), new_var, 0_u); + access->InsertBefore(use.instruction); + return access->Result(); + }); + + var->Destroy(); + } +} + +} // namespace + +Result BlockDecoratedStructs(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.BlockDecoratedStructs", + kBlockDecoratedStructsCapabilities)); + + Run(ir); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.h new file mode 100644 index 000000000..675e4fba5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/block_decorated_structs.h @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_BLOCK_DECORATED_STRUCTS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BLOCK_DECORATED_STRUCTS_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kBlockDecoratedStructsCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// BlockDecoratedStructs is a transform that changes the store type of a buffer to be a special +/// structure that is recognized as needing a block decoration in SPIR-V, potentially wrapping the +/// existing store type in a new structure if necessary. +/// @param module the module to transform +/// @returns success or failure +Result BlockDecoratedStructs(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_BLOCK_DECORATED_STRUCTS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.cc new file mode 100644 index 000000000..e8bebbd8f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.cc @@ -0,0 +1,1231 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/builtin_polyfill.h" + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/texture.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// Constant value used to polyfill the radians() builtin. +static constexpr double kDegToRad = 0.017453292519943295474; + +/// Constant value used to polyfill the degrees() builtin. +static constexpr double kRadToDeg = 57.295779513082322865; + +/// PIMPL state for the transform. +struct State { + /// The polyfill config. + const BuiltinPolyfillConfig& config; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// Process the module. + void Process() { + // Find the builtin call instructions that may need to be polyfilled. + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* builtin = inst->As()) { + switch (builtin->Func()) { + case core::BuiltinFn::kClamp: + if ((config.clamp_int && + builtin->Result()->Type()->IsIntegerScalarOrVector()) || + (config.clamp_float && + builtin->Result()->Type()->IsFloatScalarOrVector())) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kAbs: + if (config.abs_signed_int && + builtin->Result()->Type()->IsSignedIntegerScalarOrVector()) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kCountLeadingZeros: + if (config.count_leading_zeros) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kCountTrailingZeros: + if (config.count_trailing_zeros) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kDegrees: + if (config.degrees) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kSmoothstep: + worklist.Push(builtin); + break; + case core::BuiltinFn::kExtractBits: + if (config.extract_bits != BuiltinPolyfillLevel::kNone) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kFirstLeadingBit: + if (config.first_leading_bit) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kFirstTrailingBit: + if (config.first_trailing_bit) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kFwidthFine: + if (config.fwidth_fine) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kInsertBits: + if (config.insert_bits != BuiltinPolyfillLevel::kNone) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kRadians: + if (config.radians) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kReflect: + if (config.reflect_vec2_f32) { + // Polyfill for vec2. See crbug.com/tint/1798 + auto* vec_ty = builtin->Result()->Type()->As(); + if (vec_ty->Width() == 2 && vec_ty->Type()->Is()) { + worklist.Push(builtin); + } + } + break; + case core::BuiltinFn::kSaturate: + if (config.saturate) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kTextureSampleBias: + worklist.Push(builtin); + break; + case core::BuiltinFn::kTextureSampleBaseClampToEdge: + if (config.texture_sample_base_clamp_to_edge_2d_f32) { + auto* tex = + builtin->Args()[0]->Type()->As(); + if (tex && tex->Dim() == core::type::TextureDimension::k2d && + tex->Type()->Is()) { + worklist.Push(builtin); + } + } + break; + case core::BuiltinFn::kDot4U8Packed: + case core::BuiltinFn::kDot4I8Packed: { + if (config.dot_4x8_packed) { + worklist.Push(builtin); + } + break; + } + case core::BuiltinFn::kPack4XI8: + case core::BuiltinFn::kPack4XU8: + case core::BuiltinFn::kPack4XI8Clamp: + case core::BuiltinFn::kUnpack4XI8: + case core::BuiltinFn::kUnpack4XU8: { + if (config.pack_unpack_4x8) { + worklist.Push(builtin); + } + break; + } + case core::BuiltinFn::kPack4XU8Clamp: { + if (config.pack_4xu8_clamp) { + worklist.Push(builtin); + } + break; + } + case core::BuiltinFn::kPack4X8Snorm: + case core::BuiltinFn::kPack4X8Unorm: + case core::BuiltinFn::kUnpack4X8Snorm: + case core::BuiltinFn::kUnpack4X8Unorm: + if (config.pack_unpack_4x8_norm) { + worklist.Push(builtin); + } + break; + case core::BuiltinFn::kSubgroupBroadcast: + if (config.subgroup_broadcast_f16 && + builtin->Result()->Type()->DeepestElement()->Is()) { + worklist.Push(builtin); + } + break; + default: + break; + } + } + } + + // Polyfill the builtin call instructions that we found. + for (auto* builtin : worklist) { + switch (builtin->Func()) { + case core::BuiltinFn::kClamp: + Clamp(builtin); + break; + case core::BuiltinFn::kAbs: + AbsSignedInt(builtin); + break; + case core::BuiltinFn::kCountLeadingZeros: + CountLeadingZeros(builtin); + break; + case core::BuiltinFn::kCountTrailingZeros: + CountTrailingZeros(builtin); + break; + case core::BuiltinFn::kDegrees: + Degrees(builtin); + break; + case core::BuiltinFn::kSmoothstep: + SmoothStep(builtin); + break; + case core::BuiltinFn::kExtractBits: + ExtractBits(builtin); + break; + case core::BuiltinFn::kFirstLeadingBit: + FirstLeadingBit(builtin); + break; + case core::BuiltinFn::kFirstTrailingBit: + FirstTrailingBit(builtin); + break; + case core::BuiltinFn::kFwidthFine: + FwidthFine(builtin); + break; + case core::BuiltinFn::kInsertBits: + InsertBits(builtin); + break; + case core::BuiltinFn::kRadians: + Radians(builtin); + break; + case core::BuiltinFn::kReflect: + Reflect(builtin); + break; + case core::BuiltinFn::kSaturate: + Saturate(builtin); + break; + case core::BuiltinFn::kTextureSampleBaseClampToEdge: + TextureSampleBaseClampToEdge_2d_f32(builtin); + break; + case core::BuiltinFn::kTextureSampleBias: + TextureSampleBiasClamp(builtin); + break; + case core::BuiltinFn::kDot4I8Packed: + Dot4I8Packed(builtin); + break; + case core::BuiltinFn::kDot4U8Packed: + Dot4U8Packed(builtin); + break; + case core::BuiltinFn::kPack4XI8: + Pack4xI8(builtin); + break; + case core::BuiltinFn::kPack4XU8: + Pack4xU8(builtin); + break; + case core::BuiltinFn::kPack4XI8Clamp: + Pack4xI8Clamp(builtin); + break; + case core::BuiltinFn::kPack4XU8Clamp: + Pack4xU8Clamp(builtin); + break; + case core::BuiltinFn::kUnpack4XI8: + Unpack4xI8(builtin); + break; + case core::BuiltinFn::kUnpack4XU8: + Unpack4xU8(builtin); + break; + case core::BuiltinFn::kPack4X8Snorm: + Pack4x8Snorm(builtin); + break; + case core::BuiltinFn::kPack4X8Unorm: + Pack4x8Unorm(builtin); + break; + case core::BuiltinFn::kUnpack4X8Snorm: + Unpack4x8Snorm(builtin); + break; + case core::BuiltinFn::kUnpack4X8Unorm: + Unpack4x8Unorm(builtin); + break; + case core::BuiltinFn::kSubgroupBroadcast: + SubgroupBroadcast(builtin); + break; + default: + break; + } + } + } + + /// Polyfill a `pack4x8snorm` builtin call + void Pack4x8Snorm(ir::CoreBuiltinCall* call) { + auto* arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* vec4f = ty.vec4f(); + auto* vec4u = ty.vec4u(); + + auto* neg_one = b.Splat(vec4f, -1_f); + auto* one = b.Splat(vec4f, 1_f); + + core::ir::Value* v = b.Clamp(arg, neg_one, one)->Result(); + v = b.Multiply(b.Splat(vec4f, 127_f), v)->Result(); + v = b.Add(b.Splat(vec4f, 0.5_f), v)->Result(); + v = b.Call(vec4f, core::BuiltinFn::kFloor, Vector{v})->Result(); + v = b.Convert(ty.vec4i(), v)->Result(); + v = b.Bitcast(vec4u, v)->Result(); + v = b.And(v, b.Splat(vec4u, 0xff_u))->Result(); + v = b.ShiftLeft(v, b.Construct(vec4u, 0_u, 8_u, 16_u, 24_u))->Result(); + + auto* x = b.Access(ty.u32(), v, 0_u); + auto* y = b.Access(ty.u32(), v, 1_u); + auto* z = b.Access(ty.u32(), v, 2_u); + auto* w = b.Access(ty.u32(), v, 3_u); + + v = b.Or(x, b.Or(y, b.Or(z, w)))->Result(); + + call->Result()->ReplaceAllUsesWith(v); + }); + call->Destroy(); + } + + /// Polyfill a `pack4x8unorm` builtin call + void Pack4x8Unorm(ir::CoreBuiltinCall* call) { + auto* arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* vec4f = ty.vec4f(); + auto* vec4u = ty.vec4u(); + + auto* zero = b.Zero(vec4f); + auto* one = b.Splat(vec4f, 1_f); + + auto* v = b.Clamp(arg, zero, one)->Result(); + v = b.Multiply(b.Splat(vec4f, 255_f), v)->Result(); + v = b.Add(b.Splat(vec4f, 0.5_f), v)->Result(); + v = b.Call(vec4f, core::BuiltinFn::kFloor, Vector{v})->Result(); + v = b.Convert(vec4u, v)->Result(); + v = b.And(v, b.Splat(vec4u, 0xff_u))->Result(); + v = b.ShiftLeft(v, b.Construct(vec4u, 0_u, 8_u, 16_u, 24_u))->Result(); + + auto* x = b.Access(ty.u32(), v, 0_u); + auto* y = b.Access(ty.u32(), v, 1_u); + auto* z = b.Access(ty.u32(), v, 2_u); + auto* w = b.Access(ty.u32(), v, 3_u); + + v = b.Or(x, b.Or(y, b.Or(z, w)))->Result(); + + call->Result()->ReplaceAllUsesWith(v); + }); + call->Destroy(); + } + + /// Polyfill a `unpack4x8snorm` builtin call + void Unpack4x8Snorm(ir::CoreBuiltinCall* call) { + auto* arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* vec4f = ty.vec4f(); + auto* vec4u = ty.vec4u(); + auto* vec4i = ty.vec4i(); + + auto* v = b.Construct(vec4u, arg)->Result(); + // Shift left to put the 8th bit of each number into the sign bit location, we then + // convert to an i32 and shift back, so the sign bit will be set as needed. The bits + // outside the bottom 8 are then masked off. + v = b.ShiftLeft(v, b.Construct(vec4u, 24_u, 16_u, 8_u, 0_u))->Result(); + v = b.Bitcast(vec4i, v)->Result(); + v = b.ShiftRight(v, b.Splat(vec4u, 24_u))->Result(); + v = b.Convert(vec4f, v)->Result(); + v = b.Divide(v, b.Splat(vec4f, 127_f))->Result(); + v = b.Max(v, b.Splat(vec4f, -1_f))->Result(); + + call->Result()->ReplaceAllUsesWith(v); + }); + call->Destroy(); + } + + /// Polyfill a `unpack4x8unorm` builtin call + void Unpack4x8Unorm(ir::CoreBuiltinCall* call) { + auto* arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* vec4f = ty.vec4f(); + auto* vec4u = ty.vec4u(); + + auto* v = b.Construct(vec4u, arg)->Result(); + v = b.ShiftRight(v, b.Construct(vec4u, 0_u, 8_u, 16_u, 24_u))->Result(); + v = b.And(v, b.Splat(vec4u, 0xff_u))->Result(); + v = b.Convert(vec4f, v)->Result(); + v = b.Divide(v, b.Splat(vec4f, 255_f))->Result(); + + call->Result()->ReplaceAllUsesWith(v); + }); + call->Destroy(); + } + + /// Polyfill a `clamp()` builtin call for integers and floats. + /// @param call the builtin call instruction + void Clamp(ir::CoreBuiltinCall* call) { + auto* e = call->Args()[0]; + auto* low = call->Args()[1]; + auto* high = call->Args()[2]; + + b.InsertBefore(call, [&] { + auto* max = b.Max(e, low); + b.Min(max, high)->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill a `abs()` builtin call for signed integers. + /// @param call the builtin call instruction + void AbsSignedInt(ir::CoreBuiltinCall* call) { + auto* e = call->Args()[0]; + b.InsertBefore(call, [&] { b.Max(e, b.Negation(e))->SetResult(call->DetachResult()); }); + call->Destroy(); + } + + /// Polyfill a `countLeadingZeros()` builtin call. + /// @param call the builtin call instruction + void CountLeadingZeros(ir::CoreBuiltinCall* call) { + auto* input = call->Args()[0]; + auto* result_ty = input->Type(); + auto* uint_ty = ty.MatchWidth(ty.u32(), result_ty); + + // Make an u32 constant with the same component count as result_ty. + auto V = [&](uint32_t u) { return b.MatchWidth(u32(u), result_ty); }; + + b.InsertBefore(call, [&] { + // %x = %input; + // if (%x is signed) { + // %x = bitcast(%x) + // } + // %b16 = select(0, 16, %x <= 0x0000ffff); + // %x <<= %b16; + // %b8 = select(0, 8, %x <= 0x00ffffff); + // %x <<= %b8; + // %b4 = select(0, 4, %x <= 0x0fffffff); + // %x <<= %b4; + // %b2 = select(0, 2, %x <= 0x3fffffff); + // %x <<= %b2; + // %b1 = select(0, 1, %x <= 0x7fffffff); + // %b0 = select(0, 1, %x == 0); + // %result = (%b16 | %b8 | %b4 | %b2 | %b1) + %b0; + + auto* x = input; + if (result_ty->IsSignedIntegerScalarOrVector()) { + x = b.Bitcast(uint_ty, x)->Result(); + } + auto* b16 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(16), + b.LessThanEqual(x, V(0x0000ffff))); + x = b.ShiftLeft(x, b16)->Result(); + auto* b8 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(8), + b.LessThanEqual(x, V(0x00ffffff))); + x = b.ShiftLeft(x, b8)->Result(); + auto* b4 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(4), + b.LessThanEqual(x, V(0x0fffffff))); + x = b.ShiftLeft(x, b4)->Result(); + auto* b2 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(2), + b.LessThanEqual(x, V(0x3fffffff))); + x = b.ShiftLeft(x, b2)->Result(); + auto* b1 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(1), + b.LessThanEqual(x, V(0x7fffffff))); + auto* b0 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(1), b.Equal(x, V(0))); + Instruction* result = b.Add(b.Or(b16, b.Or(b8, b.Or(b4, b.Or(b2, b.Or(b1, b0))))), b0); + if (result_ty->IsSignedIntegerScalarOrVector()) { + result = b.Bitcast(result_ty, result); + } + result->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill a `countTrailingZeros()` builtin call. + /// @param call the builtin call instruction + void CountTrailingZeros(ir::CoreBuiltinCall* call) { + auto* input = call->Args()[0]; + auto* result_ty = input->Type(); + auto* uint_ty = ty.MatchWidth(ty.u32(), result_ty); + + // Make an u32 constant with the same component count as result_ty. + auto V = [&](uint32_t u) { return b.MatchWidth(u32(u), result_ty); }; + + b.InsertBefore(call, [&] { + // %x = %input; + // if (%x is signed) { + // %x = bitcast(%x) + // } + // %b16 = select(0, 16, (%x & 0x0000ffff) == 0); + // %x >>= %b16; + // %b8 = select(0, 8, (%x & 0x000000ff) == 0); + // %x >>= %b8; + // %b4 = select(0, 4, (%x & 0x0000000f) == 0); + // %x >>= %b4; + // %b2 = select(0, 2, (%x & 0x00000003) == 0); + // %x >>= %b2; + // %b1 = select(0, 1, (%x & 0x00000001) == 0); + // %b0 = select(0, 1, (%x & 0x00000001) == 0); + // %result = (%b16 | %b8 | %b4 | %b2 | %b1) + %b0; + + auto* x = input; + if (result_ty->IsSignedIntegerScalarOrVector()) { + x = b.Bitcast(uint_ty, x)->Result(); + } + auto* b16 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(16), + b.Equal(b.And(x, V(0x0000ffff)), V(0))); + x = b.ShiftRight(x, b16)->Result(); + auto* b8 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(8), + b.Equal(b.And(x, V(0x000000ff)), V(0))); + x = b.ShiftRight(x, b8)->Result(); + auto* b4 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(4), + b.Equal(b.And(x, V(0x0000000f)), V(0))); + x = b.ShiftRight(x, b4)->Result(); + auto* b2 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(2), + b.Equal(b.And(x, V(0x00000003)), V(0))); + x = b.ShiftRight(x, b2)->Result(); + auto* b1 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(1), + b.Equal(b.And(x, V(0x00000001)), V(0))); + auto* b0 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(1), b.Equal(x, V(0))); + Instruction* result = b.Add(b.Or(b16, b.Or(b8, b.Or(b4, b.Or(b2, b1)))), b0); + if (result_ty->IsSignedIntegerScalarOrVector()) { + result = b.Bitcast(result_ty, result); + } + result->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill an `degrees()` builtin call. + /// @param call the builtin call instruction + void Degrees(ir::CoreBuiltinCall* call) { + auto* arg = call->Args()[0]; + auto* type = arg->Type()->DeepestElement(); + ir::Value* value = nullptr; + if (type->Is()) { + value = b.Constant(f16(kRadToDeg)); + } else if (type->Is()) { + value = b.Constant(f32(kRadToDeg)); + } + b.InsertBefore(call, [&] { + auto* mul = b.Multiply(arg, value); + mul->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill an `smoothStep()` builtin call. + /// @param call the builtin call instruction + void SmoothStep(ir::CoreBuiltinCall* call) { + auto* edge0_arg = call->Args()[0]; + auto* edge1_arg = call->Args()[1]; + auto* x_arg = call->Args()[2]; + auto* type = x_arg->Type(); + ir::Constant* zero = nullptr; + ir::Constant* one = nullptr; + ir::Constant* two = nullptr; + ir::Constant* three = nullptr; + if (type->DeepestElement()->Is()) { + zero = b.MatchWidth(0_f, type); + one = b.MatchWidth(1_f, type); + two = b.MatchWidth(2_f, type); + three = b.MatchWidth(3_f, type); + } else if (type->DeepestElement()->Is()) { + zero = b.MatchWidth(0_h, type); + one = b.MatchWidth(1_h, type); + two = b.MatchWidth(2_h, type); + three = b.MatchWidth(3_h, type); + } + + b.InsertBefore(call, [&] { + auto* dividend = b.Subtract(x_arg, edge0_arg); + auto* divisor = b.Subtract(edge1_arg, edge0_arg); + auto* quotient = b.Divide(dividend, divisor); + auto* t_clamped = b.Clamp(quotient, zero, one); + + // Smoothstep is a well defined function. + // result = t * t * (3.0 - 2.0 * t); + auto* smooth_result = b.Multiply( + t_clamped, b.Multiply(t_clamped, b.Subtract(three, b.Multiply(two, t_clamped)))); + smooth_result->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill an `extractBits()` builtin call. + /// @param call the builtin call instruction + void ExtractBits(ir::CoreBuiltinCall* call) { + auto* offset = call->Args()[1]; + auto* count = call->Args()[2]; + switch (config.extract_bits) { + case BuiltinPolyfillLevel::kClampOrRangeCheck: { + b.InsertBefore(call, [&] { + // Replace: + // extractBits(e, offset, count) + // With: + // let o = min(offset, 32); + // let c = min(count, w - o); + // extractBits(e, o, c); + auto* o = b.Min(offset, 32_u); + auto* c = b.Min(count, b.Subtract(32_u, o)); + call->SetOperand(ir::CoreBuiltinCall::kArgsOperandOffset + 1, o->Result()); + call->SetOperand(ir::CoreBuiltinCall::kArgsOperandOffset + 2, c->Result()); + }); + } break; + case BuiltinPolyfillLevel::kFull: { + // Replace: + // result = extractBits(e, offset, count) + // With: + // let s = min(offset, 32u); + // let t = min(32u, (s + count)); + // let shl = (32u - t); + // let shr = (shl + s + // let shl_result = select(i32(), (e << shl), (shl < 32u)); + // result = select(((shl_result >> 31u) >> 1u), (shl_result >> shr), (shr < 32u)); + // } + auto* e = call->Args()[0]; + auto* result_ty = e->Type(); + auto* uint_ty = ty.MatchWidth(ty.u32(), result_ty); + auto V = [&](uint32_t u) { return b.MatchWidth(u32(u), result_ty); }; + b.InsertBefore(call, [&] { + auto* s = b.Min(offset, 32_u); + auto* t = b.Min(32_u, b.Add(s, count)); + auto* shl = b.Subtract(32_u, t); + auto* shr = b.Add(shl, s); + auto* f1 = b.Zero(result_ty); + auto* t1 = b.ShiftLeft(e, b.Construct(uint_ty, shl)); + auto* shl_result = + b.Call(result_ty, core::BuiltinFn::kSelect, f1, t1, b.LessThan(shl, 32_u)); + auto* f2 = b.ShiftRight(b.ShiftRight(shl_result, V(31)), V(1)); + auto* t2 = b.ShiftRight(shl_result, b.Construct(uint_ty, shr)); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kSelect, f2, t2, + b.LessThan(shr, 32_u)); + }); + call->Destroy(); + } break; + default: + TINT_IR_UNIMPLEMENTED(ir) << "extractBits polyfill level"; + } + } + + /// Polyfill a `firstLeadingBit()` builtin call. + /// @param call the builtin call instruction + void FirstLeadingBit(ir::CoreBuiltinCall* call) { + auto* input = call->Args()[0]; + auto* result_ty = input->Type(); + auto* uint_ty = ty.MatchWidth(ty.u32(), result_ty); + + // Make an u32 constant with the same component count as result_ty. + auto V = [&](uint32_t u) { return b.MatchWidth(u32(u), result_ty); }; + + b.InsertBefore(call, [&] { + // %x = %input; + // if (%x is signed) { + // %x = select(u32(%x), ~u32(%x), x > 0x80000000); + // } + // %b16 = select(16, 0, (%x & 0xffff0000) == 0); + // %x >>= %b16; + // %b8 = select(8, 0, (%x & 0x0000ff00) == 0); + // %x >>= %b8; + // %b4 = select(4, 0, (%x & 0x000000f0) == 0); + // %x >>= %b4; + // %b2 = select(2, 0, (%x & 0x0000000c) == 0); + // %x >>= %b2; + // %b1 = select(1, 0, (%x & 0x00000002) == 0); + // %result = %b16 | %b8 | %b4 | %b2 | %b1; + // %result = select(%result, 0xffffffff, %x == 0); + + auto* x = input; + if (result_ty->IsSignedIntegerScalarOrVector()) { + x = b.Bitcast(uint_ty, x)->Result(); + auto* inverted = b.Complement(x); + x = b.Call(uint_ty, core::BuiltinFn::kSelect, inverted, x, + b.LessThan(x, V(0x80000000))) + ->Result(); + } + auto* b16 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(16), V(0), + b.Equal(b.And(x, V(0xffff0000)), V(0))); + x = b.ShiftRight(x, b16)->Result(); + auto* b8 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(8), V(0), + b.Equal(b.And(x, V(0x0000ff00)), V(0))); + x = b.ShiftRight(x, b8)->Result(); + auto* b4 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(4), V(0), + b.Equal(b.And(x, V(0x000000f0)), V(0))); + x = b.ShiftRight(x, b4)->Result(); + auto* b2 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(2), V(0), + b.Equal(b.And(x, V(0x0000000c)), V(0))); + x = b.ShiftRight(x, b2)->Result(); + auto* b1 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(1), V(0), + b.Equal(b.And(x, V(0x00000002)), V(0))); + Instruction* result = b.Or(b16, b.Or(b8, b.Or(b4, b.Or(b2, b1)))); + result = + b.Call(uint_ty, core::BuiltinFn::kSelect, result, V(0xffffffff), b.Equal(x, V(0))); + if (result_ty->IsSignedIntegerScalarOrVector()) { + result = b.Bitcast(result_ty, result); + } + result->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill a `firstTrailingBit()` builtin call. + /// @param call the builtin call instruction + void FirstTrailingBit(ir::CoreBuiltinCall* call) { + auto* input = call->Args()[0]; + auto* result_ty = input->Type(); + auto* uint_ty = ty.MatchWidth(ty.u32(), result_ty); + + // Make an u32 constant with the same component count as result_ty. + auto V = [&](uint32_t u) { return b.MatchWidth(u32(u), result_ty); }; + + b.InsertBefore(call, [&] { + // %x = %input; + // if (%x is signed) { + // %x = bitcast(%x) + // } + // %b16 = select(0, 16, (%x & 0x0000ffff) == 0); + // %x >>= %b16; + // %b8 = select(0, 8, (%x & 0x000000ff) == 0); + // %x >>= %b8; + // %b4 = select(0, 4, (%x & 0x0000000f) == 0); + // %x >>= %b4; + // %b2 = select(0, 2, (%x & 0x00000003) == 0); + // %x >>= %b2; + // %b1 = select(0, 1, (%x & 0x00000001) == 0); + // %result = %b16 | %b8 | %b4 | %b2 | %b1; + // %result = select(%result, 0xffffffff, %x == 0); + + auto* x = input; + if (result_ty->IsSignedIntegerScalarOrVector()) { + x = b.Bitcast(uint_ty, x)->Result(); + } + auto* b16 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(16), + b.Equal(b.And(x, V(0x0000ffff)), V(0))); + x = b.ShiftRight(x, b16)->Result(); + auto* b8 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(8), + b.Equal(b.And(x, V(0x000000ff)), V(0))); + x = b.ShiftRight(x, b8)->Result(); + auto* b4 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(4), + b.Equal(b.And(x, V(0x0000000f)), V(0))); + x = b.ShiftRight(x, b4)->Result(); + auto* b2 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(2), + b.Equal(b.And(x, V(0x00000003)), V(0))); + x = b.ShiftRight(x, b2)->Result(); + auto* b1 = b.Call(uint_ty, core::BuiltinFn::kSelect, V(0), V(1), + b.Equal(b.And(x, V(0x00000001)), V(0))); + Instruction* result = b.Or(b16, b.Or(b8, b.Or(b4, b.Or(b2, b1)))); + result = + b.Call(uint_ty, core::BuiltinFn::kSelect, result, V(0xffffffff), b.Equal(x, V(0))); + if (result_ty->IsSignedIntegerScalarOrVector()) { + result = b.Bitcast(result_ty, result); + } + result->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill a `fwidthFine()` builtin call. + /// @param call the builtin call instruction + void FwidthFine(ir::CoreBuiltinCall* call) { + auto* value = call->Args()[0]; + auto* type = value->Type(); + b.InsertBefore(call, [&] { + auto* dpdx = b.Call(type, core::BuiltinFn::kDpdxFine, value); + auto* dpdy = b.Call(type, core::BuiltinFn::kDpdyFine, value); + auto* abs_dpdx = b.Call(type, core::BuiltinFn::kAbs, dpdx); + auto* abs_dpdy = b.Call(type, core::BuiltinFn::kAbs, dpdy); + auto* result = b.Add(abs_dpdx, abs_dpdy); + call->Result()->ReplaceAllUsesWith(result->Result()); + }); + call->Destroy(); + } + + /// Polyfill an `insertBits()` builtin call. + /// @param call the builtin call instruction + void InsertBits(ir::CoreBuiltinCall* call) { + auto* offset = call->Args()[2]; + auto* count = call->Args()[3]; + + switch (config.insert_bits) { + case BuiltinPolyfillLevel::kClampOrRangeCheck: { + b.InsertBefore(call, [&] { + // Replace: + // insertBits(e, newbits, offset, count) + // With: + // let o = min(offset, 32); + // let c = min(count, w - o); + // insertBits(e, newbits, o, c); + auto* o = b.Min(offset, 32_u); + auto* c = b.Min(count, b.Subtract(32_u, o)); + call->SetOperand(ir::CoreBuiltinCall::kArgsOperandOffset + 2, o->Result()); + call->SetOperand(ir::CoreBuiltinCall::kArgsOperandOffset + 3, c->Result()); + }); + } break; + case BuiltinPolyfillLevel::kFull: { + // Replace: + // result = insertBits(e, newbits, offset, count) + // With: + // let oc = (offset + count); + // let mask = ((select(0u, (1u << offset), (offset < 32u)) - 1u) + // ^ (select(0u, (1u << oc), (oc < 32u)) - 1u)); + // result = ((select(i32(), (newbits << offset), (offset < 32u)) & i32(mask)) + // | (e & i32(~(mask)))); + auto* e = call->Args()[0]; + auto* newbits = call->Args()[1]; + auto* result_ty = e->Type(); + auto* uint_ty = ty.MatchWidth(ty.u32(), result_ty); + const bool result_is_signed = result_ty->DeepestElement()->Is(); + + auto mask_as_result_type = [&](Instruction* mask) { + if (result_is_signed) { + mask = b.Convert(mask); + } + if (auto* vec = result_ty->As()) { + mask = b.Construct(vec, mask); + } + return mask; + }; + + b.InsertBefore(call, [&] { + auto* oc = b.Add(offset, count); + auto* t1 = b.ShiftLeft(1_u, offset); + auto* s1 = b.Call(core::BuiltinFn::kSelect, b.Zero(), t1, + b.LessThan(offset, 32_u)); + auto* t2 = b.ShiftLeft(1_u, oc); + auto* s2 = b.Call(core::BuiltinFn::kSelect, b.Zero(), t2, + b.LessThan(oc, 32_u)); + auto* mask_lhs = b.Subtract(s1, 1_u); + auto* mask_rhs = b.Subtract(s2, 1_u); + auto* mask = b.Xor(mask_lhs, mask_rhs); + auto* f3 = b.Zero(result_ty); + auto* t3 = b.ShiftLeft(newbits, b.Construct(uint_ty, offset)); + auto* s3 = b.Call(result_ty, core::BuiltinFn::kSelect, f3, t3, + b.LessThan(offset, 32_u)); + auto* result_lhs = b.And(s3, mask_as_result_type(mask)); + auto* result_rhs = b.And(e, mask_as_result_type(b.Complement(mask))); + auto* result = b.Or(result_lhs, result_rhs); + result->SetResult(call->DetachResult()); + }); + call->Destroy(); + } break; + default: + TINT_IR_UNIMPLEMENTED(ir) << "insertBits polyfill level"; + } + } + + /// Polyfill an `radians()` builtin call. + /// @param call the builtin call instruction + void Radians(ir::CoreBuiltinCall* call) { + auto* arg = call->Args()[0]; + auto* type = arg->Type()->DeepestElement(); + ir::Value* value = nullptr; + if (type->Is()) { + value = b.Constant(f16(kDegToRad)); + } else if (type->Is()) { + value = b.Constant(f32(kDegToRad)); + } + b.InsertBefore(call, [&] { + auto* mul = b.Multiply(arg, value); + mul->SetResult(call->DetachResult()); + }); + call->Destroy(); + } + + /// Polyfill a `reflect()` builtin call. + /// @param call the builtin call instruction + void Reflect(ir::CoreBuiltinCall* call) { + auto* e1 = call->Args()[0]; + auto* e2 = call->Args()[1]; + auto* vec_ty = e1->Type()->As(); + // Only polyfills vec2 (crbug.com/tint/1798) + TINT_IR_ASSERT(ir, vec_ty && vec_ty->Width() == 2 && vec_ty->Type()->Is()); + + b.InsertBefore(call, [&] { + // The generated HLSL must effectively be emitted as: + // e1 + (-2 * dot(e1,e2) * e2) + // Rather than the mathemetically equivalent: + // e1 - 2 * dot(e2,e2) * e2 + // + // When FXC compiles HLSL reflect, or the second case above, + // it emits a `dp4` instruction for `2 * dot(e1,e2)`, which is + // miscompiled by certain Intel drivers. The workaround (first + // case above) results in FXC emitting a `dp2` for the dot, + // followed by a `mul 2`, which works around the bug. + auto* dot = b.Call(ty.f32(), core::BuiltinFn::kDot, e1, e2); + auto* factor = b.Multiply(-2.0_f, dot); + auto* vfactor = b.Construct(vec_ty, factor); + auto* mul = b.Multiply(vfactor, e2); + b.AddWithResult(call->DetachResult(), e1, mul); + }); + call->Destroy(); + } + + /// Polyfill a `saturate()` builtin call. + /// @param call the builtin call instruction + void Saturate(ir::CoreBuiltinCall* call) { + // Replace `saturate(x)` with `clamp(x, 0., 1.)`. + auto* type = call->Result()->Type(); + ir::Constant* zero = nullptr; + ir::Constant* one = nullptr; + if (type->DeepestElement()->Is()) { + zero = b.MatchWidth(0_f, type); + one = b.MatchWidth(1_f, type); + } else if (type->DeepestElement()->Is()) { + zero = b.MatchWidth(0_h, type); + one = b.MatchWidth(1_h, type); + } + auto* clamp = b.Clamp(call->Args()[0], zero, one); + clamp->SetResult(call->DetachResult()); + clamp->InsertBefore(call); + call->Destroy(); + } + + /// Polyfill a `textureSampleBaseClampToEdge()` builtin call for 2D F32 textures. + /// @param call the builtin call instruction + void TextureSampleBaseClampToEdge_2d_f32(ir::CoreBuiltinCall* call) { + // Replace `textureSampleBaseClampToEdge(%texture, %sample, %coords)` with: + // %dims = vec2f(textureDimensions(%texture)); + // %half_texel = vec2f(0.5) / dims; + // %clamped = clamp(%coord, %half_texel, 1.0 - %half_texel); + // %result = textureSampleLevel(%texture, %sampler, %clamped, 0); + auto* texture = call->Args()[0]; + auto* sampler = call->Args()[1]; + auto* coords = call->Args()[2]; + b.InsertBefore(call, [&] { + auto* dims = b.Call>(core::BuiltinFn::kTextureDimensions, texture); + auto* fdims = b.Convert>(dims); + auto* half_texel = b.Divide(b.Splat>(0.5_f), fdims); + auto* one_minus_half_texel = b.Subtract(b.Splat>(1_f), half_texel); + auto* clamped = b.Clamp(coords, half_texel, one_minus_half_texel); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kTextureSampleLevel, texture, + sampler, clamped, 0_f); + }); + call->Destroy(); + } + + /// Polyfill clamping for the (f32) bias parameter of TextureSampleBias + /// @param call the builtin call instruction + void TextureSampleBiasClamp(ir::CoreBuiltinCall* call) { + b.InsertBefore(call, [&] { + auto* texture_type = call->Args()[0]->Type()->As(); + bool is_array_texture = type::IsTextureArray(texture_type->Dim()); + const uint32_t kBiasParameterIndex = is_array_texture ? 4 : 3; + auto* bias_parameter = call->Args()[kBiasParameterIndex]; + // TODO(crbug.com/371033198): Consider applying clamp here if 'bias_parameter' is a + // constant. This might not be the most prudent idea for two reasons: 1. the platform + // compilers will perform this optimization 2. it will bifurcate the testing paths. + call->SetArg(kBiasParameterIndex, b.Clamp(bias_parameter, -16.00_f, 15.99_f)->Result()); + }); + } + + /// Polyfill a `dot4I8Packed()` builtin call + /// @param call the builtin call instruction + void Dot4I8Packed(ir::CoreBuiltinCall* call) { + // Replace `dot4I8Packed(%x,%y)` with: + // %unpacked_x = unpack4xI8(%x); + // %unpacked_y = unpack4xI8(%y); + // %result = dot(%unpacked_x, %unpacked_y); + auto* x = call->Args()[0]; + auto* y = call->Args()[1]; + auto* unpacked_x = Unpack4xI8OnValue(call, x); + auto* unpacked_y = Unpack4xI8OnValue(call, y); + b.InsertBefore(call, [&] { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kDot, unpacked_x, unpacked_y); + }); + call->Destroy(); + } + + /// Polyfill a `dot4U8Packed()` builtin call + /// @param call the builtin call instruction + void Dot4U8Packed(ir::CoreBuiltinCall* call) { + // Replace `dot4U8Packed(%x,%y)` with: + // %unpacked_x = unpack4xU8(%x); + // %unpacked_y = unpack4xU8(%y); + // %result = dot(%unpacked_x, %unpacked_y); + auto* x = call->Args()[0]; + auto* y = call->Args()[1]; + auto* unpacked_x = Unpack4xU8OnValue(call, x); + auto* unpacked_y = Unpack4xU8OnValue(call, y); + b.InsertBefore(call, [&] { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kDot, unpacked_x, unpacked_y); + }); + call->Destroy(); + } + + /// Polyfill a `pack4xI8()` builtin call + /// @param call the builtin call instruction + void Pack4xI8(ir::CoreBuiltinCall* call) { + // Replace `pack4xI8(%x)` with: + // %n = vec4u(0, 8, 16, 24); + // %x_u32 = bitcast(%x) + // %x_u8 = (%x_u32 & vec4u(0xff)) << n; + // %result = dot(%x_u8, vec4u(1)); + auto* x = call->Args()[0]; + b.InsertBefore(call, [&] { + auto* vec4u = ty.vec4u(); + + auto* n = b.Construct(vec4u, b.Constant(u32(0)), b.Constant(u32(8)), + b.Constant(u32(16)), b.Constant(u32(24))); + auto* x_u32 = b.Bitcast(vec4u, x); + auto* x_u8 = b.ShiftLeft(b.And(x_u32, b.Construct(vec4u, b.Constant(u32(0xff)))), n); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kDot, x_u8, + b.Construct(vec4u, (b.Constant(u32(1))))); + }); + call->Destroy(); + } + + /// Polyfill a `pack4xU8()` builtin call + /// @param call the builtin call instruction + void Pack4xU8(ir::CoreBuiltinCall* call) { + // Replace `pack4xU8(%x)` with: + // %n = vec4u(0, 8, 16, 24); + // %x_i8 = (%x & vec4u(0xff)) << %n; + // %result = dot(%x_i8, vec4u(1)); + auto* x = call->Args()[0]; + b.InsertBefore(call, [&] { + auto* vec4u = ty.vec4u(); + + auto* n = b.Construct(vec4u, b.Constant(u32(0)), b.Constant(u32(8)), + b.Constant(u32(16)), b.Constant(u32(24))); + auto* x_u8 = b.ShiftLeft(b.And(x, b.Construct(vec4u, b.Constant(u32(0xff)))), n); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kDot, x_u8, + b.Construct(vec4u, (b.Constant(u32(1))))); + }); + call->Destroy(); + } + + /// Polyfill a `pack4xI8Clamp()` builtin call + /// @param call the builtin call instruction + void Pack4xI8Clamp(ir::CoreBuiltinCall* call) { + // Replace `pack4xI8Clamp(%x)` with: + // %n = vec4u(0, 8, 16, 24); + // %min_i8_vec4 = vec4i(-128); + // %max_i8_vec4 = vec4i(127); + // %x_clamp = clamp(%x, %min_i8_vec4, %max_i8_vec4); + // %x_u32 = bitcast(%x_clamp); + // %x_u8 = (%x_u32 & vec4u(0xff)) << n; + // %result = dot(%x_u8, vec4u(1)); + auto* x = call->Args()[0]; + b.InsertBefore(call, [&] { + auto* vec4i = ty.vec4i(); + auto* vec4u = ty.vec4u(); + + auto* n = b.Construct(vec4u, b.Constant(u32(0)), b.Constant(u32(8)), + b.Constant(u32(16)), b.Constant(u32(24))); + auto* min_i8_vec4 = b.Construct(vec4i, b.Constant(i32(-128))); + auto* max_i8_vec4 = b.Construct(vec4i, b.Constant(i32(127))); + auto* x_clamp = b.Clamp(x, min_i8_vec4, max_i8_vec4); + auto* x_u32 = b.Bitcast(vec4u, x_clamp); + auto* x_u8 = b.ShiftLeft(b.And(x_u32, b.Construct(vec4u, b.Constant(u32(0xff)))), n); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kDot, x_u8, + b.Construct(vec4u, (b.Constant(u32(1))))); + }); + call->Destroy(); + } + + /// Polyfill a `pack4xU8Clamp()` builtin call + /// @param call the builtin call instruction + void Pack4xU8Clamp(ir::CoreBuiltinCall* call) { + // Replace `pack4xU8Clamp(%x)` with: + // %n = vec4u(0, 8, 16, 24); + // %min_u8_vec4 = vec4u(0); + // %max_u8_vec4 = vec4u(255); + // %x_clamp = clamp(%x, vec4u(0), vec4u(255)); + // %x_u8 = %x_clamp << n; + // %result = dot(%x_u8, vec4u(1)); + auto* x = call->Args()[0]; + b.InsertBefore(call, [&] { + auto* vec4u = ty.vec4u(); + + auto* n = b.Construct(vec4u, b.Constant(u32(0)), b.Constant(u32(8)), + b.Constant(u32(16)), b.Constant(u32(24))); + auto* min_u8_vec4 = b.Construct(vec4u, b.Constant(u32(0))); + auto* max_u8_vec4 = b.Construct(vec4u, b.Constant(u32(255))); + auto* x_clamp = b.Clamp(x, min_u8_vec4, max_u8_vec4); + auto* x_u8 = b.ShiftLeft(x_clamp, n); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kDot, x_u8, + b.Construct(vec4u, (b.Constant(u32(1))))); + }); + call->Destroy(); + } + + /// Emit code for `unpack4xI8` on u32 value `x`, before the given call. + /// @param call the instruction that should follow the emitted code + /// @param x the u32 value to be unpacked + ir::Instruction* Unpack4xI8OnValue(ir::CoreBuiltinCall* call, ir::Value* x) { + // Replace `unpack4xI8(%x)` with: + // %n = vec4u(24, 16, 8, 0); + // %x_splat = vec4u(%x); // splat the scalar to a vector + // %x_vec4i = bitcast(%x_splat << n); + // %result = %x_vec4i >> vec4u(24); + ir::Instruction* result = nullptr; + b.InsertBefore(call, [&] { + auto* vec4i = ty.vec4i(); + auto* vec4u = ty.vec4u(); + + auto* n = b.Construct(vec4u, b.Constant(u32(24)), b.Constant(u32(16)), + b.Constant(u32(8)), b.Constant(u32(0))); + auto* x_splat = b.Construct(vec4u, x); + auto* x_vec4i = b.Bitcast(vec4i, b.ShiftLeft(x_splat, n)); + result = b.ShiftRight(x_vec4i, b.Construct(vec4u, b.Constant(u32(24)))); + }); + return result; + } + + /// Polyfill a `unpack4xI8()` builtin call + /// @param call the builtin call instruction + void Unpack4xI8(ir::CoreBuiltinCall* call) { + auto* result = Unpack4xI8OnValue(call, call->Args()[0]); + result->SetResult(call->DetachResult()); + call->Destroy(); + } + + /// Emit code for `unpack4xU8` on u32 value `x`, before the given call. + /// @param call the instruction that should follow the emitted code + /// @param x the u32 value to be unpacked + Instruction* Unpack4xU8OnValue(ir::CoreBuiltinCall* call, ir::Value* x) { + // Replace `unpack4xU8(%x)` with: + // %n = vec4u(0, 8, 16, 24); + // %x_splat = vec4u(%x); // splat the scalar to a vector + // %x_vec4u = %x_splat >> n; + // %result = %x_vec4u & vec4u(0xff); + ir::Instruction* result = nullptr; + b.InsertBefore(call, [&] { + auto* vec4u = ty.vec4u(); + + auto* n = b.Construct(vec4u, b.Constant(u32(0)), b.Constant(u32(8)), + b.Constant(u32(16)), b.Constant(u32(24))); + auto* x_splat = b.Construct(vec4u, x); + auto* x_vec4u = b.ShiftRight(x_splat, n); + result = b.And(x_vec4u, b.Construct(vec4u, b.Constant(u32(0xff)))); + }); + return result; + } + + /// Polyfill a `unpack4xU8()` builtin call + /// @param call the builtin call instruction + void Unpack4xU8(ir::CoreBuiltinCall* call) { + auto* result = Unpack4xU8OnValue(call, call->Args()[0]); + result->SetResult(call->DetachResult()); + call->Destroy(); + } + + /// Polyfill a `subgroupBroadcast(f16)` builtin call. + /// @param call the builtin call instruction + void SubgroupBroadcast(ir::CoreBuiltinCall* call) { + // This polyfill is implemented by bitcasting f16 values to u32, performing the broadcast on + // the uint type, and then bitcasting back. Uses vec specific bit casting. + // + // f16 -> broadcast as u32 after packing with a zero, then unpack + // vec2 -> broadcast as u32 + // vec3 -> broadcast as one vec2 + // vec4 -> broadcast as one vec2 + + auto* value = call->Args()[0]; + auto* type = value->Type(); + + auto* lane_id = call->Args()[1]; + + b.InsertBefore(call, [&] { + ir::Value* result = nullptr; + + if (auto* vec_ty = type->As()) { + // Handle vector types. + switch (vec_ty->Width()) { + case 2: { // vec2 + auto* u32_val = b.Bitcast(ty.u32(), value); + auto* broadcasted_u32 = + b.Call(ty.u32(), core::BuiltinFn::kSubgroupBroadcast, u32_val, lane_id); + result = b.Bitcast(vec_ty, broadcasted_u32)->Result(); + break; + } + case 3: { // vec3 + auto* v4f16_val = b.Construct(ty.vec4h(), value, b.Zero(ty.f16())); + auto* v2u32_val = b.Bitcast(ty.vec2u(), v4f16_val); + auto* broadcasted_v2u32 = b.Call( + ty.vec2u(), core::BuiltinFn::kSubgroupBroadcast, v2u32_val, lane_id); + auto* broadcasted_v4f16 = b.Bitcast(ty.vec4h(), broadcasted_v2u32); + result = b.Swizzle(vec_ty, broadcasted_v4f16, {0u, 1u, 2u})->Result(); + break; + } + case 4: { // vec4 + auto* v2u32_val = b.Bitcast(ty.vec2u(), value); + auto* broadcasted_v2u32 = b.Call( + ty.vec2u(), core::BuiltinFn::kSubgroupBroadcast, v2u32_val, lane_id); + result = b.Bitcast(vec_ty, broadcasted_v2u32)->Result(); + break; + } + default: + TINT_IR_UNREACHABLE(ir) + << "unhandled f16 vector width in subgroupBroadcast polyfill"; + } + } else { // Scalar f16 + // Construct a vec2(0, value), then bitcast to u32. + auto* vec_val = b.Construct(ty.vec2h(), value, b.Zero(ty.f16())); + auto* u32_val = b.Bitcast(ty.u32(), vec_val); + auto* broadcasted_u32 = + b.Call(ty.u32(), core::BuiltinFn::kSubgroupBroadcast, u32_val, lane_id); + auto* broadcasted_vec = b.Bitcast(ty.vec2h(), broadcasted_u32); + result = b.Access(ty.f16(), broadcasted_vec, 0_u)->Result(); + } + + call->Result()->ReplaceAllUsesWith(result); + }); + call->Destroy(); + } +}; + +} // namespace + +Result BuiltinPolyfill(Module& ir, const BuiltinPolyfillConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.BuiltinPolyfill", kBuiltinPolyfillCapabilities)); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.h new file mode 100644 index 000000000..c4691fe52 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_polyfill.h @@ -0,0 +1,142 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_POLYFILL_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_POLYFILL_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kBuiltinPolyfillCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// Enumerator of polyfill levels. +enum class BuiltinPolyfillLevel { + /// No polyfill needed, supported by the backend. + kNone, + /// Clamp or range check the parameters. + kClampOrRangeCheck, + /// Polyfill the entire function. + kFull, +}; + +/// The set of polyfills that should be applied. +struct BuiltinPolyfillConfig { + /// Should `clamp()` be polyfilled for integer values? + bool clamp_int = false; + /// Should `clamp()` be polyfilled for floating values? + bool clamp_float = false; + /// Should `abs()` be polyfilled for signed integer values? + bool abs_signed_int = false; + /// Should `countLeadingZeros()` be polyfilled? + bool count_leading_zeros = false; + /// Should `countTrailingZeros()` be polyfilled? + bool count_trailing_zeros = false; + /// Should `degrees()` be polyfilled? + bool degrees = false; + /// How should `extractBits()` be polyfilled? + BuiltinPolyfillLevel extract_bits = BuiltinPolyfillLevel::kNone; + /// Should `firstLeadingBit()` be polyfilled? + bool first_leading_bit = false; + /// Should `firstTrailingBit()` be polyfilled? + bool first_trailing_bit = false; + /// Should `fwidthFine()` be polyfilled? + bool fwidth_fine = false; + /// How should `insertBits()` be polyfilled? + BuiltinPolyfillLevel insert_bits = BuiltinPolyfillLevel::kNone; + /// Should `radians()` be polyfilled? + bool radians = false; + /// Should `reflect()` be polyfilled for vec2? + bool reflect_vec2_f32 = false; + /// Should `saturate()` be polyfilled? + bool saturate = false; + /// Should `textureSampleBaseClampToEdge()` be polyfilled for texture_2d textures? + bool texture_sample_base_clamp_to_edge_2d_f32 = false; + /// Should `dot4U8Packed()` and `dot4I8Packed()` be polyfilled? + bool dot_4x8_packed = false; + /// Should `pack4xI8()`, `pack4xU8()`, `pack4xI8Clamp()`, `unpack4xI8()` and `unpack4xU8()` + /// be polyfilled? + bool pack_unpack_4x8 = false; + /// Should `pack4xU8Clamp()` be polyfilled? + /// TODO(tint:1497): remove the option once the bug in DXC is fixed. + bool pack_4xu8_clamp = false; + /// Should `pack4x8snorm`, `pack4x8unorm`, `unpack4x8snorm` and `unpack4x8unorm` be polyfilled? + bool pack_unpack_4x8_norm = false; + /// Should `subgroupBroadcast(f16)` be polyfilled? + bool subgroup_broadcast_f16 = false; + + /// Reflection for this class + TINT_REFLECT(BuiltinPolyfillConfig, + clamp_int, + count_leading_zeros, + count_trailing_zeros, + degrees, + extract_bits, + first_leading_bit, + first_trailing_bit, + fwidth_fine, + insert_bits, + radians, + reflect_vec2_f32, + saturate, + texture_sample_base_clamp_to_edge_2d_f32, + dot_4x8_packed, + pack_unpack_4x8, + pack_4xu8_clamp, + pack_unpack_4x8_norm, + subgroup_broadcast_f16); +}; + +/// BuiltinPolyfill is a transform that replaces calls to builtin functions and uses of other core +/// features with equivalent alternatives. +/// @param module the module to transform +/// @param config the polyfill configuration +/// @returns success or failure +Result BuiltinPolyfill(Module& module, const BuiltinPolyfillConfig& config); + +} // namespace tint::core::ir::transform + +namespace tint { + +/// Reflection for BuiltinPolyfillLevel +TINT_REFLECT_ENUM_RANGE(tint::core::ir::transform::BuiltinPolyfillLevel, kNone, kFull); + +} // namespace tint + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.cc new file mode 100644 index 000000000..80a145044 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.cc @@ -0,0 +1,145 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/builtin_scalarize.h" +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/texture.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The polyfill config. + const BuiltinScalarizeConfig& config; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + // We cannot arbitrarily allow the config to scalarize any builtin as this might cause + // semantically incorrect scalarizations. An example here is 'cross' which is a vec3 for all + // input and return parameters but cannot be scalarized. + bool ShouldAttemptScalarize(ir::CoreBuiltinCall* builtin) { + auto builtin_enum = builtin->Func(); + if (!builtin->Result()->Type()->Is()) { + // No vector found. Already scalar. + return false; + } + switch (builtin_enum) { + case core::BuiltinFn::kClamp: + return config.scalarize_clamp; + case core::BuiltinFn::kMax: + return config.scalarize_max; + case core::BuiltinFn::kMin: + return config.scalarize_min; + default: + return false; + } + } + + void Process() { + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* builtin = inst->As()) { + if (ShouldAttemptScalarize(builtin)) { + worklist.Push(builtin); + } + } + } + + for (auto* builtin : worklist) { + ScalarizeBuiltin(builtin); + } + } + + void ScalarizeBuiltin(ir::CoreBuiltinCall* builtin) { + uint32_t common_vec_width = builtin->Result()->Type()->As()->Width(); + b.InsertBefore(builtin, [&] { + const core::type::Type* scalar_return_type = + builtin->Result()->Type()->DeepestElement(); + Vector args; + for (uint32_t i = 0; i < common_vec_width; i++) { + Vector scalar_args; + + for (auto& e : builtin->Args()) { + if (auto* vec = e->Type()->As()) { + // It would be an error to scalarize over different sized vectors. + TINT_IR_ASSERT(ir, common_vec_width == vec->Width()); + auto* access_arg = b.Access(vec->DeepestElement(), e, u32(i)); + scalar_args.Push(access_arg->Result()); + } else { + TINT_IR_ASSERT(ir, e->Type()->IsScalar()); + // This code generalizes for vector functions that additionally take scalar + // inputs. And example of this is the second and third parameters of + // 'extract_bits'. + scalar_args.Push(e); + } + } + + auto* scalar_call = + b.Call(scalar_return_type, builtin->Func(), std::move(scalar_args)); + args.Push(scalar_call->Result()); + } + // Places result back into a vector. + b.ConstructWithResult(builtin->DetachResult(), std::move(args)); + }); + builtin->Destroy(); + } +}; + +} // namespace + +Result BuiltinScalarize(Module& ir, const BuiltinScalarizeConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.BuiltinScalarize", kBuiltinScalarizeCapabilities)); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.h new file mode 100644 index 000000000..63bb55456 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/builtin_scalarize.h @@ -0,0 +1,82 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_SCALARIZE_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_SCALARIZE_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kBuiltinScalarizeCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllow64BitIntegers, + core::ir::Capability::kAllowPointSizeBuiltin, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowAnyLetType, + core::ir::Capability::kMslAllowEntryPointInterface, + core::ir::Capability::kAllowModuleScopeLets, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, +}; + +/// The scalarizer configuration options +struct BuiltinScalarizeConfig { + // Set to true to scalarize clamp builtin + bool scalarize_clamp = false; + + // Set to true to scalarize max builtin + bool scalarize_max = false; + + // Set to true to scalarize min builtin + bool scalarize_min = false; + + /// Reflection for this class + TINT_REFLECT(BuiltinScalarizeConfig, scalarize_clamp, scalarize_max, scalarize_min); +}; + +/// BuiltinScalarize is a transform that replaces calls to builtin vector functions with scalar +/// equivalent alternatives. +/// @param module the module to transform +/// @param config the polyfill configuration +/// @returns success or failure +Result BuiltinScalarize(Module& module, const BuiltinScalarizeConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_SCALARIZE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.cc new file mode 100644 index 000000000..3de4faca3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.cc @@ -0,0 +1,166 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/change_immediate_to_uniform.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +namespace tint::core::ir::transform { +namespace { + +/// PIMPL state for the transform. +/// +struct State { + /// The transform config. + const ChangeImmediateToUniformConfig& config; + /// The IR module. + core::ir::Module& ir; + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + core::ir::Var* immediate = nullptr; + + // candidate group number if immediate_binding_point is not available. + uint32_t candidate_group = 0; + + for (auto* inst : *ir.root_block) { + // Allow this to run before or after PromoteInitializers by handling non-var root_block + // entries + auto* var = inst->As(); + if (!var) { + continue; + } + + // use the largest used group plus 1, or group 0 if no + // resources are bound as candidate group number. + if (const auto& bp_visited = var->BindingPoint()) { + candidate_group = std::max(candidate_group, bp_visited->group + 1); + } + + auto* var_ty = var->Result()->Type()->As(); + + // In HLSL backend, DecomposeStorageAccess transform may have converted the var pointers + // into ByteAddressBuffer objects. Since they've been changed, then they're Storage + // buffers and we don't care about them here. + if (!var_ty) { + continue; + } + + // Only care about immediate space variables. + if (var_ty->AddressSpace() != core::AddressSpace::kImmediate) { + continue; + } + + if (immediate) { + TINT_IR_ICE(ir) << "multiple immediate variables"; + } + + immediate = var; + } + + if (!immediate) { + return; + } + + BindingPoint bp = {}; + if (config.immediate_binding_point.has_value()) { + bp = *config.immediate_binding_point; + } else { + // Otherwise, use the binding 0 of candidate group. + bp = {candidate_group, 0}; + } + immediate->SetBindingPoint(bp.group, bp.binding); + + ReplaceImmediateAddressSpace(immediate); + } + + /// Replace an immediate variable's pointer address space to make it `uniform`. + /// @param var the immediate variable + void ReplaceImmediateAddressSpace(core::ir::Var* var) { + Vector to_replace; + to_replace.Push(var->Result()); + + // Update all uses of the module-scope variable. + while (!to_replace.IsEmpty()) { + auto* value = to_replace.Pop(); + + auto* ptr_type = value->Type()->As(); + if (ptr_type->AddressSpace() == AddressSpace::kUniform) { + // This value has already been replaced. This can happen for function parameters + // when the function is called multiple times. + continue; + } + value->SetType(ty.ptr(core::AddressSpace::kUniform, ptr_type->StoreType())); + + // Add all usages of the value to the queue. + for (auto usage : value->UsagesUnsorted()) { + if (auto* call = usage->instruction->As()) { + // The usage is a function call, so we need to add the target function parameter + // to the queue. + uint32_t param_index = static_cast(usage->operand_index - 1); + auto* param = call->Target()->Params()[param_index]; + to_replace.Push(param); + continue; + } + if (!usage->instruction->Is() && + !usage->instruction->Is()) { + continue; + } + to_replace.Push(usage->instruction->Result()); + } + } + } +}; + +} // namespace + +Result ChangeImmediateToUniform(core::ir::Module& ir, + const ChangeImmediateToUniformConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.ChangeImmediateToUniform", + core::ir::Capabilities{ + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllowPointSizeBuiltin, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kMslAllowEntryPointInterface, + })); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.h new file mode 100644 index 000000000..8c110df16 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/change_immediate_to_uniform.h @@ -0,0 +1,61 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_CHANGE_IMMEDIATE_TO_UNIFORM_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_CHANGE_IMMEDIATE_TO_UNIFORM_H_ + +#include +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::transform { + +struct ChangeImmediateToUniformConfig { + /// The binding point info. + std::optional immediate_binding_point; +}; + +/// ChangeImmediateToUniform is a transform used to replace immediate global var accesses to +/// uniform address space. This transform should apply after all immediate +/// related transforms. +/// +/// +/// @param module the module to transform +/// @returns success or failure +Result ChangeImmediateToUniform(core::ir::Module& module, + const ChangeImmediateToUniformConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_CHANGE_IMMEDIATE_TO_UNIFORM_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.cc new file mode 100644 index 000000000..8bfa3a503 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.cc @@ -0,0 +1,95 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/combine_access_instructions.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// Process the module. + void Process() { + // Loop over every instruction looking for access instructions. + for (auto* inst : ir.Instructions()) { + if (auto* access = inst->As()) { + // Look for places where the result of this access instruction is used as a base + // pointer for another access instruction. + access->Result()->ForEachUseUnsorted([&](Usage use) { + auto* child = use.instruction->As(); + if (child && use.operand_index == ir::Access::kObjectOperandOffset) { + // Push the indices of the parent access instruction into the child. + Vector operands; + operands.Push(access->Object()); + for (auto* idx : access->Indices()) { + operands.Push(idx); + } + for (auto* idx : child->Indices()) { + operands.Push(idx); + } + child->SetOperands(std::move(operands)); + } + }); + + // If there are no other uses of the access instruction, remove it. + if (!access->Result()->IsUsed()) { + access->Destroy(); + } + } + } + } +}; + +} // namespace + +Result CombineAccessInstructions(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.CombineAccessInstructions", + core::ir::Capabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.h new file mode 100644 index 000000000..cc5432b44 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/combine_access_instructions.h @@ -0,0 +1,47 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_COMBINE_ACCESS_INSTRUCTIONS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_COMBINE_ACCESS_INSTRUCTIONS_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// CombineAccessInstructions is a transform that combines chains of access instructions. +/// @param module the module to transform +/// @returns success or failure +Result CombineAccessInstructions(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_COMBINE_ACCESS_INSTRUCTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.cc new file mode 100644 index 000000000..1faf8b137 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.cc @@ -0,0 +1,177 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/conversion_polyfill.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The polyfill config. + const ConversionPolyfillConfig& config; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// Map from integer type to its f32toi helper function. + Hashmap f32toi_helpers{}; + + /// Map from integer type to its f16toi helper function. + Hashmap f16toi_helpers{}; + + /// Process the module. + void Process() { + // Find the conversion instructions that need to be polyfilled. + Vector ftoi_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* convert = inst->As()) { + auto* src_ty = convert->Args()[0]->Type(); + auto* res_ty = convert->Result()->Type(); + if (config.ftoi && // + src_ty->IsFloatScalarOrVector() && // + res_ty->IsIntegerScalarOrVector()) { + ftoi_worklist.Push(convert); + } + } + } + + // Polyfill the conversion instructions that we found. + for (auto* convert : ftoi_worklist) { + ftoi(convert); + convert->Destroy(); + } + } + + /// Replace a conversion instruction with a call to helper function that manually clamps the + /// result to within the limit of the destination type. + /// @param convert the conversion instruction + void ftoi(ir::Convert* convert) { + auto* res_ty = convert->Result()->Type(); + auto* src_ty = convert->Args()[0]->Type(); + auto* src_el_ty = src_ty->DeepestElement(); + + auto& helpers = src_el_ty->Is() ? f32toi_helpers : f16toi_helpers; + auto* helper = helpers.GetOrAdd(res_ty, [&] { + // Generate a name for the helper function. + StringStream name; + name << "tint_"; + if (auto* src_vec = src_ty->As()) { + name << "v" << src_vec->Width() << src_vec->Type()->FriendlyName(); + } else { + name << src_ty->FriendlyName(); + } + name << "_to_"; + if (auto* res_vec = res_ty->As()) { + name << "v" << res_vec->Width() << res_vec->Type()->FriendlyName(); + } else { + name << res_ty->FriendlyName(); + } + + // Generate constants for the limits. + struct { + ir::Constant* low_limit_f = nullptr; + ir::Constant* high_limit_f = nullptr; + } limits; + + + // Largest integers representable in the source floating point format. + if (src_el_ty->Is()) { + // These values are chosen specifically to enable f32 clamping. + // See https://github.com/gpuweb/gpuweb/issues/5043 + if (res_ty->IsSignedIntegerScalarOrVector()) { + limits.low_limit_f = b.MatchWidth(f32(INT32_MIN), res_ty); + limits.high_limit_f = + b.MatchWidth(f32(tint::core::kMaxI32WhichIsAlsoF32), res_ty); + } else { + limits.low_limit_f = b.MatchWidth(f32(0), res_ty); + limits.high_limit_f = + b.MatchWidth(f32(tint::core::kMaxU32WhichIsAlsoF32), res_ty); + } + } else if (src_el_ty->Is()) { + constexpr float MAX_F16 = 65504; + if (res_ty->IsSignedIntegerScalarOrVector()) { + limits.low_limit_f = b.MatchWidth(f16(-MAX_F16), res_ty); + limits.high_limit_f = b.MatchWidth(f16(MAX_F16), res_ty); + } else { + limits.low_limit_f = b.MatchWidth(f16(0), res_ty); + limits.high_limit_f = b.MatchWidth(f16(MAX_F16), res_ty); + } + } else { + TINT_IR_UNIMPLEMENTED(ir) << "unhandled floating-point type"; + } + + // Create the helper function. + auto* func = b.Function(name.str(), res_ty); + auto* value = b.FunctionParam("value", src_ty); + func->SetParams({value}); + b.Append(func->Block(), [&] { + auto* clamped = b.Clamp(value, limits.low_limit_f, limits.high_limit_f); + auto* converted = b.Convert(res_ty, clamped); + + b.Return(func, converted->Result()); + }); + return func; + }); + + // Call the helper function, splatting the arguments to match the target vector width. + auto* call = b.CallWithResult(convert->DetachResult(), helper, convert->Args()[0]); + call->InsertBefore(convert); + } +}; + +} // namespace + +Result ConversionPolyfill(Module& ir, const ConversionPolyfillConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.ConversionPolyfill", kConversionPolyfillCapabilities)); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.h new file mode 100644 index 000000000..efc183a9c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/conversion_polyfill.h @@ -0,0 +1,67 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_CONVERSION_POLYFILL_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_CONVERSION_POLYFILL_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kConversionPolyfillCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// The set of polyfills that should be applied. +struct ConversionPolyfillConfig { + /// Should converting floating point values to integers be polyfilled? + bool ftoi = false; + + /// Reflection for this class + TINT_REFLECT(ConversionPolyfillConfig, ftoi); +}; + +/// ConversionPolyfill is a transform that modifies convert instructions to prepare them for raising +/// to backend dialects that may have different semantics. +/// @param module the module to transform +/// @param config the polyfill configuration +/// @returns success or failure +Result ConversionPolyfill(Module& module, const ConversionPolyfillConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_CONVERSION_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.cc new file mode 100644 index 000000000..a35af45e0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.cc @@ -0,0 +1,116 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/dead_code_elimination.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/ice/ice.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir_; + + /// The IR builder. + Builder b_{ir_}; + + /// Process the module. + void Process() { + auto funcs = ir_.DependencyOrderedFunctions(); + for (auto iter = funcs.rbegin(); iter != funcs.rend(); ++iter) { + auto func = *iter; + if (func->IsEntryPoint()) { + continue; + } + + bool used = false; + for (auto usage : func->UsagesUnsorted()) { + if (usage->instruction->Is()) { + used = true; + break; + } + } + + if (!used) { + ir_.Destroy(func); + } + } + + // Find any unused vars, do this after removing functions in case the usage was in a + // function which is unused. + auto* next = ir_.root_block->Front(); + while (next) { + auto* inst = next; + next = inst->next; + + if (inst->Result()->IsUsed()) { + continue; + } + + // Only want to process `var`s + auto* var = inst->As(); + if (!var) { + continue; + } + + auto* ptr = var->Result()->Type()->As(); + TINT_IR_ASSERT(ir_, ptr); + + auto space = ptr->AddressSpace(); + if (space != core::AddressSpace::kOut && space != core::AddressSpace::kIn && + space != core::AddressSpace::kPrivate) { + continue; + } + + inst->Destroy(); + } + } +}; + +} // namespace + +Result DeadCodeElimination(Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.DeadCodeElimination", kDeadCodeEliminationCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.h new file mode 100644 index 000000000..1c73d8a12 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/dead_code_elimination.h @@ -0,0 +1,67 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_DEAD_CODE_ELIMINATION_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_DEAD_CODE_ELIMINATION_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kDeadCodeEliminationCapabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowPhonyInstructions, + core::ir::Capability::kAllowUnannotatedModuleIOVariables, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowStructMatrixDecorations, + core::ir::Capability::kAllowLocationForNumericElements, + core::ir::Capability::kAllowPointerToHandle, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// DeadCodeElimination is a transform that removes dead code from the given IR module. +/// +/// Currently the eliminator will try to remove: +/// * Unused functions. +/// * Unused `private`, `__in` and `__out` module scoped variables. +/// +/// @param module the module to transform +/// @returns success or failure +Result DeadCodeElimination(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_DEAD_CODE_ELIMINATION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.cc new file mode 100644 index 000000000..262b2c65c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.cc @@ -0,0 +1,624 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/decompose_uniform_access.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/validator.h" + +namespace tint::core::ir::transform { +namespace { + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +/// PIMPL state for the transform. +/// +/// Each uniform buffer variable is rewritten so its store type is an array of vec4u +/// elements. Accesses to original store type contents are rewritten to pick out the +/// right set of vec4u elements and then use bitcasts as needed to construct the originally +/// loaded value. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + using VarTypePair = std::pair; + /// Maps a struct to the load function + Hashmap var_and_type_to_load_fn_{}; + + /// Process the module. + void Process() { + Vector var_worklist; + for (auto* inst : *ir.root_block) { + // Allow this to run before or after PromoteInitializers by handling non-var root_block + // entries + auto* var = inst->As(); + if (!var) { + continue; + } + + // DecomposeStorageAccess maybe have converte the var pointers into ByteAddressBuffer + // objects. Since they've been changed, then they're Storage buffers and we don't care + // about them here. + auto* var_ty = var->Result()->Type()->As(); + if (!var_ty) { + continue; + } + + // Only care about uniform address space variables. + if (var_ty->AddressSpace() != core::AddressSpace::kUniform) { + continue; + } + + var_worklist.Push(var); + } + + for (auto* var : var_worklist) { + auto* result = var->Result(); + + auto usage_worklist = result->UsagesSorted(); + auto* var_ty = result->Type()->As(); + while (!usage_worklist.IsEmpty()) { + auto usage = usage_worklist.Pop(); + auto* inst = usage.instruction; + + // Load instructions can be destroyed by the replacing access function + if (!inst->Alive()) { + continue; + } + + OffsetData od{}; + tint::Switch( + inst, // + [&](core::ir::LoadVectorElement* l) { LoadVectorElement(l, var, od); }, + [&](core::ir::Load* l) { Load(l, var, od); }, + [&](core::ir::Access* a) { Access(a, var, a->Object()->Type(), od); }, + [&](core::ir::Let* let) { + // The `let` is, essentially, an alias for the `var` as it's assigned + // directly. Gather all the `let` usages into our worklist, and then replace + // the `let` with the `var` itself. + for (auto& use : let->Result()->UsagesSorted()) { + usage_worklist.Push(use); + } + let->Result()->ReplaceAllUsesWith(result); + let->Destroy(); + }, + TINT_ICE_ON_NO_MATCH); + } + + // Swap the result type of the `var` to the new result type + auto array_length = (var_ty->StoreType()->Size() + 15) / 16; + result->SetType(ty.ptr(var_ty->AddressSpace(), ty.array(ty.vec4u(), array_length), + var_ty->Access())); + } + } + + // OffsetData represents an unsigned integer expression. + // The value is the sum of a const part, held in `byte_offset`, and + // non-const parts in `byte_offset_expr`. + struct OffsetData { + uint32_t byte_offset = 0; + Vector byte_offset_expr{}; + }; + + // Note, must be called inside a builder insert block (Append, InsertBefore, etc) + core::ir::Value* OffsetToValue(OffsetData offset) { + core::ir::Value* val = nullptr; + + // If the offset is zero, skip setting val. This way, we won't add `0 +` and create useless + // addition expressions, but if the offset is zero, and there are no expressions, make sure + // we return the 0 value. + if (offset.byte_offset != 0) { + val = b.Value(u32(offset.byte_offset)); + } else if (offset.byte_offset_expr.IsEmpty()) { + return b.Value(0_u); + } + + for (core::ir::Value* expr : offset.byte_offset_expr) { + if (!val) { + val = expr; + } else { + val = b.Add(val, expr)->Result(); + } + } + + return val; + } + + // Converts a byte offset to an index into a vec4u array. + // After the transform runs the store type of the uniform buffer variable is an + // array of vec4u. + // Note, this must be called inside a builder insert block (Append, InsertBefore, etc) + core::ir::Value* OffsetValueToArrayIndex(core::ir::Value* val) { + if (auto* cnst = val->As()) { + auto v = cnst->Value()->ValueAs(); + return b.Value(u32(v / 16u)); + } + return b.Divide(val, 16_u)->Result(); + } + + // Calculates the index of the vec4u element containing the byte at (byte_idx % 16). + // Assumes the upper bits of byte_idx have already been used to access the correct + // vec4u array element in the underlying variable. + core::ir::Value* CalculateVectorOffset(core::ir::Value* byte_idx) { + if (auto* byte_cnst = byte_idx->As()) { + return b.Value(u32((byte_cnst->Value()->ValueAs() % 16u) / 4u)); + } + // Note: Using bitwise-and and shift instead of modulo and divide here was necessary to + // avoid an FXC miscompile. See https://crbug.com/454366353. + return b.ShiftRight(b.And(byte_idx, 15_u), 2_u)->Result(); + } + + void Access(core::ir::Access* a, + core::ir::Var* var, + const core::type::Type* obj_ty, + OffsetData offset) { + // Note, because we recurse through the `access` helper, the object passed in isn't + // necessarily the originating `var` object, but maybe a partially resolved access chain + // object. + if (auto* view = obj_ty->As()) { + obj_ty = view->StoreType(); + } + + auto update_offset = [&](core::ir::Value* idx_value, uint32_t size) { + tint::Switch( + idx_value, + [&](core::ir::Constant* cnst) { + uint32_t idx = cnst->Value()->ValueAs(); + offset.byte_offset += size * idx; + }, + [&](core::ir::Value* val) { + b.InsertBefore(a, [&] { + offset.byte_offset_expr.Push( + b.Multiply(u32(size), b.InsertConvertIfNeeded(ty.u32(), val)) + ->Result()); + }); + }); + }; + + for (auto* idx_value : a->Indices()) { + tint::Switch( + obj_ty, + [&](const core::type::Vector* v) { + update_offset(idx_value, v->Type()->Size()); + obj_ty = v->Type(); + }, + [&](const core::type::Matrix* m) { + update_offset(idx_value, m->ColumnStride()); + obj_ty = m->ColumnType(); + }, + [&](const core::type::Array* ary) { + update_offset(idx_value, ary->ImplicitStride()); + obj_ty = ary->ElemType(); + }, + [&](const core::type::Struct* s) { + auto* cnst = idx_value->As(); + + // A struct index must be a constant + TINT_IR_ASSERT(ir, cnst); + + uint32_t idx = cnst->Value()->ValueAs(); + auto* mem = s->Members()[idx]; + obj_ty = mem->Type(); + offset.byte_offset += mem->Offset(); + }, + TINT_ICE_ON_NO_MATCH); + } + + auto usages = a->Result()->UsagesSorted(); + while (!usages.IsEmpty()) { + auto usage = usages.Pop(); + tint::Switch( + usage.instruction, + [&](core::ir::Let* let) { + // The `let` is essentially an alias to the `access`. So, add the `let` + // usages into the usage worklist, and replace the let with the access chain + // directly. + for (auto& u : let->Result()->UsagesSorted()) { + usages.Push(u); + } + let->Result()->ReplaceAllUsesWith(a->Result()); + let->Destroy(); + }, + [&](core::ir::Access* sub_access) { + // Treat an access chain of the access chain as a continuation of the outer + // chain. Pass through the object we stopped at and the current byte_offset + // and then restart the access chain replacement for the new access chain. + Access(sub_access, var, obj_ty, offset); + }, + [&](core::ir::Load* ld) { + a->Result()->RemoveUsage(usage); + Load(ld, var, offset); + }, + [&](core::ir::LoadVectorElement* lve) { + a->Result()->RemoveUsage(usage); + LoadVectorElement(lve, var, offset); + }, + TINT_ICE_ON_NO_MATCH); + } + a->Destroy(); + } + + void Load(core::ir::Load* ld, core::ir::Var* var, OffsetData offset) { + b.InsertBefore(ld, [&] { + auto* byte_idx = OffsetToValue(offset); + auto* result = MakeLoad(ld, var, ld->Result()->Type(), byte_idx); + ld->Result()->ReplaceAllUsesWith(result->Result()); + }); + ld->Destroy(); + } + + void LoadVectorElement(core::ir::LoadVectorElement* lve, + core::ir::Var* var, + OffsetData offset) { + b.InsertBefore(lve, [&] { + // Add the byte count from the start of the vector to the requested element to the + // current offset calculation + auto elem_byte_size = lve->Result()->Type()->DeepestElement()->Size(); + if (auto* cnst = lve->Index()->As()) { + offset.byte_offset += (cnst->Value()->ValueAs() * elem_byte_size); + } else { + offset.byte_offset_expr.Push( + b.Multiply(b.InsertConvertIfNeeded(ty.u32(), lve->Index()), u32(elem_byte_size)) + ->Result()); + } + + auto* byte_idx = OffsetToValue(offset); + auto* result = MakeLoad(lve, var, lve->Result()->Type(), byte_idx); + lve->Result()->ReplaceAllUsesWith(result->Result()); + }); + lve->Destroy(); + } + + // Creates the appropriate load instructions for the given result type. + core::ir::Instruction* MakeLoad(core::ir::Instruction* inst, + core::ir::Var* var, + const core::type::Type* result_ty, + core::ir::Value* byte_idx) { + if (result_ty->IsFloatScalar() || result_ty->IsIntegerScalar()) { + return MakeScalarLoad(var, result_ty, byte_idx); + } + + return tint::Switch( + result_ty, + [&](const core::type::Struct* s) { + auto* fn = GetLoadFunctionFor(inst, var, s); + return b.Call(fn, byte_idx); + }, + [&](const core::type::Matrix* m) { + auto* fn = GetLoadFunctionFor(inst, var, m); + return b.Call(fn, byte_idx); + }, + [&](const core::type::Array* a) { + auto* fn = GetLoadFunctionFor(inst, var, a); + return b.Call(fn, byte_idx); + }, + [&](const core::type::Vector* v) { return MakeVectorLoad(var, v, byte_idx); }, + TINT_ICE_ON_NO_MATCH); + } + + core::ir::Instruction* MakeScalarLoad(core::ir::Var* var, + const core::type::Type* result_ty, + core::ir::Value* byte_idx) { + auto* array_idx = OffsetValueToArrayIndex(byte_idx); + auto* access = b.Access(ty.ptr(uniform, ty.vec4u()), var, array_idx); + + auto* vec_idx = CalculateVectorOffset(byte_idx); + core::ir::Instruction* load = b.LoadVectorElement(access, vec_idx); + if (result_ty->Is()) { + return ExtractScalarF16(load, byte_idx); + } + return b.Bitcast(result_ty, load); + } + + core::ir::Access* ExtractScalarF16(core::ir::Instruction* load, core::ir::Value* byte_idx) { + // We will bitcast the u32 to a vec2h and then extract the element that we want. + core::ir::Value* element_index = nullptr; + if (auto* cnst = byte_idx->As()) { + if (cnst->Value()->ValueAs() % 4 == 0) { + element_index = b.Constant(0_u); + } else { + element_index = b.Constant(1_u); + } + } else { + auto* false_ = b.Value(1_u); + auto* true_ = b.Value(0_u); + auto* cond = b.Equal(b.Modulo(byte_idx, 4_u), 0_u); + + Vector args{false_, true_, cond->Result()}; + element_index = b.Call(ty.u32(), core::BuiltinFn::kSelect, args)->Result(); + } + + auto* bitcast = b.Bitcast>(load); + return b.Access(bitcast, element_index); + } + + // When loading a vector we have to take the alignment into account to determine which part of + // the `uint4` to load. A `vec` of `u32`, `f32` or `i32` has an alignment requirement of + // a multiple of 8-bytes (`f16` is 4-bytes). So, this means we'll have memory like: + // + // Byte: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | + // Value:| v1 | v2 | v3 | v4 | + // Scalar Index: 0 1 2 3 + // + // Start with a byte address which is `offset + (column * columnStride)`, the array index is + // `byte_address / 16`. This gives us the `uint4` which contains our values. We can then + // calculate the vector offset as `(byte_address % 16) / 4`. + // + // * A 4-element row we access all 4-elements at the `array_idx` + // * A 3-element row we access `array_idx` at `.xyz` as it must be padded to a vec4. + // * A 2-element row, we have to decide if we want the `xy` or `zw` element. We have a minimum + // alignment of 8-bytes as per the WGSL spec. So if the `vector_idx != 2` is `0` then we + // access the `.xy` component, otherwise it is in the `.zw` component. + core::ir::Instruction* MakeVectorLoad(core::ir::Var* var, + const core::type::Vector* result_ty, + core::ir::Value* byte_idx) { + auto* array_idx = OffsetValueToArrayIndex(byte_idx); + auto* access = b.Access(ty.ptr(uniform, ty.vec4u()), var, array_idx); + + if (result_ty->DeepestElement()->Is()) { + return MakeVectorLoadF16(access, result_ty, byte_idx); + } + + TINT_IR_ASSERT(ir, result_ty->DeepestElement()->Size() == 4); + core::ir::Instruction* load = nullptr; + if (result_ty->Width() == 4) { + load = b.Load(access); + } else if (result_ty->Width() == 3) { + load = b.Swizzle(ty.vec3u(), b.Load(access), {0, 1, 2}); + } else if (result_ty->Width() == 2) { + auto* vec_idx = CalculateVectorOffset(byte_idx); + if (auto* cnst = vec_idx->As()) { + if (cnst->Value()->ValueAs() == 2u) { + load = b.Swizzle(ty.vec2u(), b.Load(access), {2, 3}); + } else { + load = b.Swizzle(ty.vec2u(), b.Load(access), {0, 1}); + } + } else { + auto* ubo = b.Load(access); + // if vec_idx == 2 -> zw + auto* sw_lhs = b.Swizzle(ty.vec2u(), ubo, {2, 3}); + // else -> xy + auto* sw_rhs = b.Swizzle(ty.vec2u(), ubo, {0, 1}); + auto* cond = b.Equal(vec_idx, 2_u); + + Vector args{sw_rhs->Result(), sw_lhs->Result(), + cond->Result()}; + + load = b.Call(ty.vec2u(), core::BuiltinFn::kSelect, args); + } + } else { + TINT_IR_UNREACHABLE(ir); + } + return b.Bitcast(result_ty, load); + } + + // Returns the instruction for getting a vector-of-f16 value of type `result_ty` + // out of the pointer-to-vec4u value `access`. Get the components starting + // at byte offset (byte_idx % 16). + // A `vec4` or `vec3` of `f16` has 8-byte alignment, while a `vec2` of `f16` has 4-byte + // alignment. So, this means we'll have memory like: + // + // Byte: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + // Scalar Index: 0 | 1 | 2 | 3 | + // vec4:| x | y | z | w | + // vec4:| x | y | z | w | x | y | z | w | + // vec3:| x | y | z | | x | y | z | | + // vec2:| x | y | x | y | x | y | x | y | + core::ir::Instruction* MakeVectorLoadF16(core::ir::Access* access, + const core::type::Vector* result_ty, + core::ir::Value* byte_idx) { + // Vec4 ends up being the same as a bitcast of vec2 to a vec4. + // A vec3 will be stored as a vec4, so we can bitcast as if we're a vec4 + // and swizzle out the last element. + if (result_ty->Width() == 3 || result_ty->Width() == 4) { + core::ir::Instruction* load = nullptr; + auto* vec_idx = CalculateVectorOffset(byte_idx); // 0 or 2 + if (auto* cnst = vec_idx->As()) { + if (cnst->Value()->ValueAs() == 2u) { + load = b.Swizzle(ty.vec2u(), b.Load(access), {2, 3}); + } else { + load = b.Swizzle(ty.vec2u(), b.Load(access), {0, 1}); + } + } else { + auto* ubo = b.Load(access); + // if vec_idx == 2 -> zw + auto* sw_lhs = b.Swizzle(ty.vec2u(), ubo, {2, 3}); + // else -> xy + auto* sw_rhs = b.Swizzle(ty.vec2u(), ubo, {0, 1}); + auto* cond = b.Equal(vec_idx, 2_u); + auto args = Vector{sw_rhs->Result(), sw_lhs->Result(), cond->Result()}; + load = b.Call(ty.vec2u(), core::BuiltinFn::kSelect, std::move(args)); + } + if (result_ty->Width() == 3) { + auto* bc = b.Bitcast(ty.vec4(result_ty->Type()), load); + return b.Swizzle(result_ty, bc, {0, 1, 2}); + } + return b.Bitcast(result_ty, load); + } + + // Vec2 ends up being the same as a bitcast u32 to vec2 + if (result_ty->Width() == 2) { + core::ir::Instruction* load = nullptr; + auto* vec_idx = CalculateVectorOffset(byte_idx); // 0, 1, 2, or 3 + if (auto* cnst = vec_idx->As()) { + const auto vec_idx_val = cnst->Value()->ValueAs(); + load = b.Swizzle(ty.u32(), b.Load(access), {vec_idx_val}); + } else { + load = b.Access(ty.u32(), b.Load(access), vec_idx); + } + return b.Bitcast(result_ty, load); + } + + TINT_IR_UNREACHABLE(ir); + } + + // Creates a load function for the given `var` and `matrix` combination. Essentially creates + // a function similar to: + // + // fn custom_load_M(offset: u32) { + // const uint scalar_offset = ((offset + 0u)) / 4; + // const uint scalar_offset_1 = ((offset + (1 * ColumnStride))) / 4; + // const uint scalar_offset_2 = ((offset + (2 * ColumnStride))) / 4; + // const uint scalar_offset_3 = ((offset + (3 * ColumnStride)))) / 4; + // return float4x4( + // asfloat(v[scalar_offset / 4]), + // asfloat(v[scalar_offset_1 / 4]), + // asfloat(v[scalar_offset_2 / 4]), + // asfloat(v[scalar_offset_3 / 4]) + // ); + // } + core::ir::Function* GetLoadFunctionFor(core::ir::Instruction* inst, + core::ir::Var* var, + const core::type::Matrix* mat) { + return var_and_type_to_load_fn_.GetOrAdd(VarTypePair{var, mat}, [&] { + auto* start_byte_offset = b.FunctionParam("start_byte_offset", ty.u32()); + auto* fn = b.Function(mat); + fn->SetParams({start_byte_offset}); + + b.Append(fn->Block(), [&] { + Vector values; + for (size_t i = 0; i < mat->Columns(); ++i) { + uint32_t stride = static_cast(i * mat->ColumnStride()); + + OffsetData od{stride, {start_byte_offset}}; + auto* byte_idx = OffsetToValue(od); + values.Push(MakeLoad(inst, var, mat->ColumnType(), byte_idx)->Result()); + } + b.Return(fn, b.Construct(mat, values)); + }); + + return fn; + }); + } + + // Creates a load function for the given `var` and `array` combination. Essentially creates + // a function similar to: + // + // fn custom_load_A(offset: u32) { + // A a = A(); + // u32 i = 0; + // loop { + // if (i >= A length) { + // break; + // } + // offset = (offset + (i * A->ImplicitStride())) / 16 + // a[i] = cast(v[offset].xyz) + // i = i + 1; + // } + // return a; + // } + core::ir::Function* GetLoadFunctionFor(core::ir::Instruction* inst, + core::ir::Var* var, + const core::type::Array* arr) { + return var_and_type_to_load_fn_.GetOrAdd(VarTypePair{var, arr}, [&] { + auto* start_byte_offset = b.FunctionParam("start_byte_offset", ty.u32()); + auto* fn = b.Function(arr); + fn->SetParams({start_byte_offset}); + + b.Append(fn->Block(), [&] { + auto* result_arr = b.Var("a", b.Zero(arr)); + + auto* count = arr->Count()->As(); + TINT_IR_ASSERT(ir, count); + + b.LoopRange(0_u, u32(count->value), 1_u, [&](core::ir::Value* idx) { + auto* stride = b.Multiply(idx, u32(arr->ImplicitStride()))->Result(); + OffsetData od{0, {start_byte_offset, stride}}; + auto* byte_idx = OffsetToValue(od); + auto* access = b.Access(ty.ptr(arr->ElemType()), result_arr, idx); + b.Store(access, MakeLoad(inst, var, arr->ElemType(), byte_idx)); + }); + + b.Return(fn, b.Load(result_arr)); + }); + + return fn; + }); + } + + // Creates a load function for the given `var` and `struct` combination. Essentially creates + // a function similar to: + // + // fn custom_load_S(start_offset: u32) { + // let a = load object at (start_offset + member_offset) + // let b = load object at (start_offset + member 1 offset); + // ... + // return S(a, b, ..., z); + // } + core::ir::Function* GetLoadFunctionFor(core::ir::Instruction* inst, + core::ir::Var* var, + const core::type::Struct* s) { + return var_and_type_to_load_fn_.GetOrAdd(VarTypePair{var, s}, [&] { + auto* start_byte_offset = b.FunctionParam("start_byte_offset", ty.u32()); + auto* fn = b.Function(s); + fn->SetParams({start_byte_offset}); + + b.Append(fn->Block(), [&] { + Vector values; + for (const auto* mem : s->Members()) { + uint32_t stride = static_cast(mem->Offset()); + + OffsetData od{stride, {start_byte_offset}}; + auto* byte_idx = OffsetToValue(od); + values.Push(MakeLoad(inst, var, mem->Type(), byte_idx)->Result()); + } + + b.Return(fn, b.Construct(s, values)); + }); + + return fn; + }); + } +}; + +} // namespace + +Result DecomposeUniformAccess(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.DecomposeUniformAccess", + core::ir::Capabilities{ + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.h new file mode 100644 index 000000000..55adb65e7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/decompose_uniform_access.h @@ -0,0 +1,49 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_DECOMPOSE_UNIFORM_ACCESS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_DECOMPOSE_UNIFORM_ACCESS_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::transform { + +/// DecomposeUniformAccess is a transform used to replace uniform buffer accesses with a +/// the correct load of the HLSL primitive objects +/// +/// @param module the module to transform +/// @returns success or failure +Result DecomposeUniformAccess(core::ir::Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_DECOMPOSE_UNIFORM_ACCESS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.cc new file mode 100644 index 000000000..0e5c61a1f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.cc @@ -0,0 +1,225 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/demote_to_helper.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/ice/ice.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The global "has not discarded" flag. + Var* continue_execution = nullptr; + + /// Map from function to a flag that indicates whether it (transitively) contains a discard. + Hashmap function_discard_status{}; + + /// Set of functions that have been processed. + Hashset processed_functions{}; + + /// Process the module. + void Process() { + // Check each function for discard instructions, potentially inside other functions called + // (transitively) by the function. + Vector to_process; + for (auto& func : ir.functions) { + // If the function contains a discard (directly or indirectly), we need to process it. + if (HasDiscard(func)) { + to_process.Push(func); + } + } + if (to_process.IsEmpty()) { + return; + } + + // Create a boolean variable that can be used to check whether the shader has discarded. + continue_execution = b.Var("continue_execution", ty.ptr()); + continue_execution->SetInitializer(b.Constant(true)); + ir.root_block->Append(continue_execution); + + // Process each function that directly or indirectly discards. + for (auto* ep : to_process) { + ProcessFunction(ep); + } + } + + /// Check if a function (transitively) contains a discard instruction. + /// @param func the function to check + /// @returns true if @p func contains a discard instruction + bool HasDiscard(Function* func) { + return function_discard_status.GetOrAdd(func, [&] { return HasDiscard(func->Block()); }); + } + + /// Check if a block (transitively) contains a discard instruction. + /// @param block the block to check + /// @returns true if @p block contains a discard instruction + bool HasDiscard(Block* block) { + // Loop over all instructions in the block. + for (auto* inst : *block) { + bool discard = false; + tint::Switch( + inst, + [&](Discard*) { + // Found a discard. + discard = true; + }, + [&](UserCall* call) { + // Check if we are calling a function that contains a discard. + discard = HasDiscard(call->Target()); + }, + [&](ControlInstruction* ctrl) { + // Recurse into control instructions and check their blocks. + ctrl->ForeachBlock([&](Block* blk) { discard = discard || HasDiscard(blk); }); + }); + if (discard) { + return true; + } + } + return false; + } + + /// Process a function to replace its discard instruction and conditionalize its stores. + /// @param func the function to process + void ProcessFunction(Function* func) { + if (processed_functions.Add(func)) { + ProcessBlock(func->Block()); + } + } + + /// Process a block to replace its discard instruction and conditionalize its stores. + /// @param block the block to process + void ProcessBlock(Block* block) { + // Helper that wraps an instruction in an if statement so that it only executes if the + // invocation has not discarded. + auto conditionalize = [&](Instruction* inst) { + // Create an if instruction in place of the original instruction. + auto* cond = b.Load(continue_execution); + auto* ifelse = b.If(cond); + cond->InsertBefore(inst); + inst->ReplaceWith(ifelse); + + // Move the original instruction into the if-true block. + auto* result = ifelse->True()->Append(inst); + + auto results = inst->Results(); + TINT_IR_ASSERT(ir, results.Length() < 2); + if (!results.IsEmpty() && !results[0]->Type()->Is()) { + // The original instruction had a result, so return it from the if instruction. + ifelse->SetResult(b.InstructionResult(results[0]->Type())); + results[0]->ReplaceAllUsesWith(ifelse->Result()); + ifelse->True()->Append(b.ExitIf(ifelse, result)); + } else { + ifelse->True()->Append(b.ExitIf(ifelse)); + } + }; + + // Loop over all instructions in the block. + for (auto* inst = *block->begin(); inst;) { + // As we're (potentially) modifying the block that we're iterating over, grab a pointer + // to the next instruction before we make any changes. + auto* next = inst->next; + TINT_DEFER(inst = next); + + tint::Switch( + inst, + [&](Discard* discard) { + // Replace every discard instruction with a store to the global flag. + discard->ReplaceWith(b.Store(continue_execution, false)); + discard->Destroy(); + }, + [&](UserCall* call) { + // Recurse into user functions. + ProcessFunction(call->Target()); + }, + [&](Store* store) { + // Conditionalize stores to host-visible address spaces. + auto* ptr = store->To()->Type()->As(); + if (ptr && ptr->AddressSpace() == core::AddressSpace::kStorage) { + conditionalize(store); + } + }, + [&](CoreBuiltinCall* builtin) { + // Conditionalize calls to builtins that have side effects. + if (core::HasSideEffects(builtin->Func())) { + conditionalize(builtin); + } + }, + [&](Return* ret) { + // Insert a conditional terminate invocation instruction before each return + // instruction in the entry point function. + if (ret->Func()->IsFragment()) { + b.InsertBefore(ret, [&] { + auto* cond = b.Load(continue_execution); + auto* ifelse = b.If(b.Not(cond)); + b.Append(ifelse->True(), [&] { // + b.TerminateInvocation(); + }); + }); + } + }, + [&](ControlInstruction* ctrl) { + // Recurse into control instructions. + ctrl->ForeachBlock([&](Block* blk) { ProcessBlock(blk); }); + }, + [&](BuiltinCall*) { + // TODO(crbug.com/tint/2102): Catch this with the validator instead. + TINT_IR_UNREACHABLE(ir) << "unexpected non-core instruction"; + }); + } + } +}; + +} // namespace + +Result DemoteToHelper(Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.DemoteToHelper", kDemoteToHelperCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.h new file mode 100644 index 000000000..6bb3f7c52 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/demote_to_helper.h @@ -0,0 +1,62 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_DEMOTE_TO_HELPER_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_DEMOTE_TO_HELPER_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kDemoteToHelperCapabilities{ + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// DemoteToHelper is a transform that emulates demote-to-helper semantics for discard instructions. +/// +/// For backend targets that implement discard by terminating the invocation, we need to change the +/// program to ensure that discarding the fragment does not affect uniformity with respect to +/// derivative operations. We do this by setting a global flag and masking all writes to storage +/// buffers and textures. +/// @param module the module to transform +/// @returns success or failure +Result DemoteToHelper(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_DEMOTE_TO_HELPER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.cc new file mode 100644 index 000000000..07f623ab1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.cc @@ -0,0 +1,683 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/direct_variable_access.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/utils/containers/reverse.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { +namespace { + +/// An access root, originating from a module-scope var. +/// These roots are not passed by parameter, but instead the callee references the module-scope var +/// directly. +struct RootModuleScopeVar { + /// The module-scope var + Var* var = nullptr; + + /// @return a hash value for this object + tint::HashCode HashCode() const { return Hash(var); } + + /// Inequality operator + bool operator!=(const RootModuleScopeVar& other) const { return var != other.var; } +}; + +/// An access root, originating from a pointer parameter or function-scope var. +/// These roots are passed by pointer parameter. +struct RootPtrParameter { + /// The parameter pointer type + const type::Pointer* type = nullptr; + + /// @return a hash value for this object + tint::HashCode HashCode() const { return Hash(type); } + + /// Inequality operator + bool operator!=(const RootPtrParameter& other) const { return type != other.type; } +}; + +/// An access root. Either a RootModuleScopeVar or RootPtrParameter. +using AccessRoot = std::variant; + +/// MemberAccess is an access operator to a struct member. +struct MemberAccess { + /// The member being accessed + const type::StructMember* member; + + /// @return a hash member for this object + tint::HashCode HashCode() const { return Hash(member); } + + /// Inequality operator + bool operator!=(const MemberAccess& other) const { return member != other.member; } +}; + +/// IndexAccess is an access operator to an array element or matrix column. +/// The ordered list of indices is passed by parameter. +struct IndexAccess { + /// @return a hash value for this object + tint::HashCode HashCode() const { return 42; } + + /// Inequality operator + bool operator!=(const IndexAccess&) const { return false; } +}; + +/// An access operation. Either a MemberAccess or IndexAccess. +using AccessOp = std::variant; + +/// A AccessShape describes the static "path" from a root variable to an element within the +/// variable. +/// +/// Functions that have parameters which need transforming will be forked into one or more +/// 'variants'. Each variant has different AccessShapes for the parameters - the transform will only +/// emit one variant when the shapes of the parameter accesses match. +/// +/// Array accessors index expressions are held externally to the AccessShape, so +/// AccessShape will be considered equal even if the array or matrix index values differ. +/// +/// For example, consider the following: +/// +/// ``` +/// struct A { +/// x : array, +/// y : u32, +/// }; +/// struct B { +/// x : i32, +/// y : array +/// }; +/// var C : B; +/// ``` +/// +/// The following AccessShape would describe the following: +/// +/// +====================================+===============+=================================+ +/// | AccessShape | Type | Expression | +/// +====================================+===============+=================================+ +/// | [ Var 'C', MemberAccess 'x' ] | i32 | C.x | +/// +------------------------------------+---------------+---------------------------------+ +/// | [ Var 'C', MemberAccess 'y' ] | array | C.y | +/// +------------------------------------+---------------+---------------------------------+ +/// | [ Var 'C', MemberAccess 'y', | A | C.y[indices[0]] | +/// | IndexAccess ] | | | +/// +------------------------------------+---------------+---------------------------------+ +/// | [ Var 'C', MemberAccess 'y', | array | C.y[indices[0]].x | +/// | IndexAccess, MemberAccess 'x' ] | | | +/// +------------------------------------+---------------+---------------------------------+ +/// | [ Var 'C', MemberAccess 'y', | i32 | C.y[indices[0]].x[indices[1]] | +/// | IndexAccess, MemberAccess 'x', | | | +/// | IndexAccess ] | | | +/// +------------------------------------+---------------+---------------------------------+ +/// | [ Var 'C', MemberAccess 'y', | u32 | C.y[indices[0]].y | +/// | IndexAccess, MemberAccess 'y' ] | | | +/// +------------------------------------+---------------+---------------------------------+ +/// +/// Where: `indices` is the AccessChain::indices. +struct AccessShape { + /// The access root. + AccessRoot root; + /// The access operations. + Vector ops; + + /// @returns the number of IndexAccess operations in #ops. + uint32_t NumIndexAccesses() const { + uint32_t count = 0; + for (auto& op : ops) { + if (std::holds_alternative(op)) { + count++; + } + } + return count; + } + + /// @return a hash value for this object + tint::HashCode HashCode() const { return Hash(root, ops); } + + /// Inequality operator + bool operator!=(const AccessShape& other) const { + return root != other.root || ops != other.ops; + } +}; + +/// AccessChain describes a chain of access expressions originating from a variable. +struct AccessChain { + /// The shape of the access chain + AccessShape shape; + /// The originating pointer + Value* root_ptr = nullptr; + /// The array of dynamic indices + Vector indices; +}; + +/// A variant signature describes the access shape of all the function's pointer parameters. +/// This is a map of pointer parameter index to access shape. +using VariantSignature = Hashmap; + +/// FnInfo describes a function that has pointer parameters which need replacing. +/// This function will be replaced by zero, one or many variants. Each variant will have a unique +/// access shape for the function's the pointer arguments. +struct FnInfo { + /// A map of variant signature to the variant's unique IR function. + Hashmap variants_by_sig; + /// The order to emit the variants in the final module. + Vector ordered_variants; +}; + +/// FnVariant describes a unique variant of a function that has pointer parameters that need +/// replacing. +struct FnVariant { + /// The signature of the variant. + VariantSignature signature; + /// The IR function for this variant. + Function* fn = nullptr; + /// The function information of the original function that this variant is based off. + FnInfo* info = nullptr; +}; + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The transform options + const DirectVariableAccessOptions& options; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// The functions that have pointer parameters that need transforming. + /// These functions will be replaced with zero, one or many forked variants. + Hashmap need_forking{}; + + /// Queue of variants that need building + Vector variants_to_build{}; + + /// Allocator for FnInfo + BlockAllocator fn_info_allocator{}; + + /// Process the module. + void Process() { + // Make a copy of all the functions in the IR module. + auto input_fns = ir.functions; + + // Populate #need_forking + GatherFnsThatNeedForking(); + + // Transform the functions that make calls to #need_forking, which aren't in #need_forking + // themselves. + BuildRootFns(); + + // Build variants of the functions in #need_forking. + BuildFnVariants(); + + // Rebuild ir.functions. + EmitFunctions(input_fns); + } + + /// Populates #need_forking with all the functions that have pointer parameters which need + /// transforming. These functions will be replaced with variants based on the access shapes. + void GatherFnsThatNeedForking() { + for (auto& fn : ir.functions) { + if (!fn->Alive()) { + continue; + } + for (auto* param : fn->Params()) { + if (!NeedsTransforming(param)) { + continue; + } + need_forking.Add(fn, fn_info_allocator.Create()); + break; + } + } + } + + /// Adjusts the calls of all the functions that make calls to #need_forking, which aren't in + /// #need_forking themselves. This populates #variants_to_build with the called functions. + void BuildRootFns() { + for (auto& fn : ir.functions) { + if (!need_forking.Contains(fn)) { + TransformCalls(fn); + } + } + } + + /// Applies the necessary transformations to all the pointer arguments of calls made to + /// functions in #need_forking. Also populates #variants_to_build with the variants of the + /// callee functions. + /// @param fn the function to transform + void TransformCalls(Function* fn) { + // For all the function calls in the function... + Traverse(fn->Block(), [&](UserCall* call) { + auto* target = call->Target(); + auto target_info = need_forking.Get(target); + if (!target_info) { + // Not a call to a function in #need_forking. Leave alone. + return; + } + + // Found a call to a function in #need_forking. + // This call needs transforming to call the generated variant. + + // New arguments to the call. This includes transformed and untransformed arguments. + Vector new_args; + + // Pointer arguments that are being replaced. + Vector replaced_args; + + // Signature of the callee variant + VariantSignature signature; + + // For each argument / parameter... + for (size_t i = 0, n = call->Args().Length(); i < n; i++) { + auto* arg = call->Args()[i]; + auto* param = target->Params()[i]; + + // Argument does not need transformation, push the existing argument to new_args. + if (!NeedsTransforming(param)) { + new_args.Push(arg); + continue; + } + + // This argument needs replacing with: + // * Nothing: root is a module-scope var and the access chain has no indices. + // * A single pointer argument to the root variable: The root is a pointer + // parameter or a function-scoped variable, and the access chain has no + // indices. + // * A single indices array argument: The root is a module-scope var and the + // access chain has indices. + // * Both a pointer argument and indices array argument: The root is a pointer + // parameter or a function-scoped variable and the access chain has indices. + b.InsertBefore(call, [&] { + // Get the access chain for the pointer argument. + auto chain = AccessChainFor(arg); + // If the root is not a module-scope variable, then pass this root pointer + // as an argument. + if (std::holds_alternative(chain.shape.root)) { + new_args.Push(chain.root_ptr); + } + // If the chain access contains indices, then pass these as an array of u32. + if (size_t array_len = chain.indices.Length(); array_len > 0) { + auto* array = ty.array(ty.u32(), static_cast(array_len)); + auto* indices = b.Construct(array, std::move(chain.indices)); + new_args.Push(indices->Result()); + } + // Record the parameter shape for the variant's signature. + signature.Add(i, chain.shape); + }); + + // Record that this pointer argument has been replaced. + replaced_args.Push(arg); + } + + // Replace the call's arguments with new_args. + call->SetArgs(std::move(new_args)); + + // Clean up instructions that provided the now unused argument values. + for (auto* old_arg : replaced_args) { + DeleteDeadInstructions(old_arg); + } + + // Look to see if this callee signature already has a variant created. + auto* new_target = (*target_info)->variants_by_sig.GetOrAdd(signature, [&] { + // New signature. + + // Clone the original function to seed the new variant. + auto* variant_fn = CloneContext{ir}.Clone(target); + (*target_info)->ordered_variants.Push(variant_fn); + + // Copy the original name for the variant + if (auto fn_name = ir.NameOf(fn)) { + ir.SetName(fn, fn_name); + } + + // Create an entry for the variant, and add it to the queue of variants that need to + // be built. We don't do this here to avoid unbounded stack usage. + variants_to_build.Push(FnVariant{/* signature */ signature, + /* fn */ variant_fn, + /* info */ *target_info}); + return variant_fn; + }); + + // Re-point the target of the call to the variant. + call->SetTarget(new_target); + }); + } + + /// Builds all the variants in #variants_to_build by: + /// * Replacing the pointer parameters with zero, one or two parameters (root pointer, indices). + /// * Transforming any calls made by that variant to other functions found in #need_forking. + /// Note: The transformation of calls can add more variants to #variants_to_build. + /// BuildFnVariants() will continue to build variants until #variants_to_build is empty. + void BuildFnVariants() { + while (!variants_to_build.IsEmpty()) { + auto variant = variants_to_build.Pop(); + BuildFnVariantParams(variant); + TransformCalls(variant.fn); + } + } + + /// Walks the instructions that built #value to obtain the root variable and the pointer + /// accesses. + /// @param value the pointer value to get the access chain for + /// @return an AccessChain + AccessChain AccessChainFor(Value* value) { + AccessChain chain; + while (value) { + TINT_IR_ASSERT(ir, value->Alive()); + value = tint::Switch( + value, // + [&](InstructionResult* res) { + // value was emitted by an instruction + auto* inst = res->Instruction(); + return tint::Switch( + inst, + [&](Access* access) { + // The AccessOp of this access instruction + Vector ops; + // The ordered, non-member accesses performed by this access instruction + Vector indices; + // The pointee-type that each access is being performed on + auto* obj_ty = access->Object()->Type()->UnwrapPtr(); + + // For each access operation... + for (auto idx : access->Indices()) { + if (auto* str = obj_ty->As()) { + // Struct type accesses must be constant, representing the index + // of the member being accessed. + TINT_IR_ASSERT(ir, idx->Is()); + auto i = idx->As()->Value()->ValueAs(); + auto* member = str->Members()[i]; + ops.Push(MemberAccess{member}); + obj_ty = member->Type(); + continue; + } + + // Array or matrix access. + // Convert index to u32 if it isn't already. + if (!idx->Type()->Is()) { + idx = b.Convert(ty.u32(), idx)->Result(); + } + + ops.Push(IndexAccess{}); + indices.Push(idx); + obj_ty = obj_ty->Elements().type; + } + + // Push the ops and indices in reverse order to the chain. This is done + // so we can continue to walk the IR values and push accesses (without + // insertion) that bring us closer to the pointer root. These are + // reversed again once the root variable is found. + for (auto& op : Reverse(ops)) { + chain.shape.ops.Push(op); + } + for (auto& idx : Reverse(indices)) { + chain.indices.Push(idx); + } + + TINT_IR_ASSERT(ir, obj_ty == access->Result()->Type()->UnwrapPtr()); + return access->Object(); + }, + [&](Load* load) { return load->From(); }, // + [&](Var* var) { + // A 'var' is a pointer root. + if (var->Block() == ir.root_block) { + // Root pointer is a module-scope 'var' + chain.shape.root = RootModuleScopeVar{var}; + } else { + // Root pointer is a function-scope 'var' + chain.shape.root = + RootPtrParameter{var->Result()->Type()->As()}; + } + chain.root_ptr = var->Result(); + return nullptr; + }, + [&](Let* let) { return let->Value(); }, // + TINT_ICE_ON_NO_MATCH); + }, + [&](FunctionParam* param) { + // Root pointer is a parameter of the caller + chain.shape.root = RootPtrParameter{param->Type()->As()}; + chain.root_ptr = param; + return nullptr; + }, // + TINT_ICE_ON_NO_MATCH); + } + + // Reverse the chain's ops and indices. See above for why. + chain.shape.ops.Reverse(); + chain.indices.Reverse(); + + return chain; + } + + /// Replaces the pointer parameters that need transforming of the variant function @p variant. + /// Instructions are inserted at the top of the @p variant function block to reconstruct the + /// pointer parameters from the access chain using the root pointer and access ops. + /// @param variant the variant function to transform + void BuildFnVariantParams(const FnVariant& variant) { + // Insert new instructions at the top of the function block... + b.InsertBefore(variant.fn->Block()->Front(), [&] { + // The replacement parameters for the variant function + Vector new_params; + const auto& old_params = variant.fn->Params(); + // For each parameter in the original function... + for (size_t param_idx = 0; param_idx < old_params.Length(); param_idx++) { + auto* old_param = old_params[param_idx]; + + // Parameter does not need transforming. + if (!NeedsTransforming(old_param)) { + new_params.Push(old_param); + continue; + } + + // Pointer parameter that needs transforming + // Grab the access shape of the pointer parameter from the signature + auto shape = variant.signature.Get(param_idx); + // The pointer value for the root of the chain. + Value* root_ptr = nullptr; + + // Build the root pointer parameter, if required. + FunctionParam* root_ptr_param = nullptr; + if (auto* ptr_param = std::get_if(&shape->root)) { + // Root pointer is passed as a parameter + root_ptr_param = b.FunctionParam(ptr_param->type); + new_params.Push(root_ptr_param); + root_ptr = root_ptr_param; + } else if (auto* global = std::get_if(&shape->root)) { + // Root pointer is a module-scope var + root_ptr = global->var->Result(); + } else { + TINT_IR_ICE(ir) << "unhandled AccessShape root variant"; + } + + // Build the access indices parameter, if required. + ir::FunctionParam* indices_param = nullptr; + if (uint32_t n = shape->NumIndexAccesses(); n > 0) { + // Indices are passed as an array of u32 + indices_param = b.FunctionParam(ty.array(ty.u32(), n)); + new_params.Push(indices_param); + } + + // Generate names for the new parameter(s) based on the replaced parameter name. + if (auto param_name = ir.NameOf(old_param); param_name.IsValid()) { + // Propagate old parameter name to the new parameters + if (root_ptr_param) { + ir.SetName(root_ptr_param, param_name.Name() + "_root"); + } + if (indices_param) { + ir.SetName(indices_param, param_name.Name() + "_indices"); + } + } + + // Use the newly added parameters to recompute the equivalent of old_param. + auto* replacement = root_ptr; + + // Emit the access chain if needed. + if (!shape->ops.IsEmpty()) { + // Handle types are passed by value, turn them into a pointer type for the + // access chain call. + auto* access_type = old_param->Type(); + if (!access_type->Is()) { + TINT_IR_ASSERT(ir, access_type->IsHandle()); + access_type = ty.ptr(access_type); + } + + // Rebuild the pointer from the root pointer and accesses. + uint32_t index_index = 0; + auto chain = Transform(shape->ops, [&](const AccessOp& op) -> Value* { + if (auto* m = std::get_if(&op)) { + return b.Constant(u32(m->member->Index())); + } + auto* access = b.Access(ty.u32(), indices_param, u32(index_index++)); + return access->Result(); + }); + + replacement = b.Access(access_type, root_ptr, std::move(chain))->Result(); + } + + // Replaced handles need the final load after the access chain. + if (!old_param->Type()->Is()) { + replacement = b.Load(replacement)->Result(); + } + + // Replace the now removed parameter value with the access instruction. + old_param->ReplaceAllUsesWith(replacement); + old_param->Destroy(); + } + + // Replace the function's parameters + variant.fn->SetParams(std::move(new_params)); + }); + } + + /// Repopulates #ir.functions with the functions in #need_forking replaced with their generated + /// variants. + /// @param input_fns the content of #ir.functions before transformation began. + void EmitFunctions(VectorRef input_fns) { + ir.functions.Clear(); + for (auto& fn : input_fns) { + if (auto info = need_forking.Get(fn)) { + fn->Destroy(); + for (auto variant : (*info)->ordered_variants) { + ir.functions.Push(variant); + } + } else { + ir.functions.Push(fn); + } + } + } + + /// @return true if @p param is a parameter that requires transforming, based on the + /// transform options. + /// @param param the function parameter + bool NeedsTransforming(FunctionParam* param) const { + auto* param_type = param->Type(); + + if (auto* ptr = param_type->As()) { + // DVA needs to be updated if handles start to be passed by pointer. + TINT_IR_ASSERT(ir, ptr->AddressSpace() != core::AddressSpace::kHandle); + switch (ptr->AddressSpace()) { + case core::AddressSpace::kImmediate: + case core::AddressSpace::kStorage: + case core::AddressSpace::kUniform: + case core::AddressSpace::kWorkgroup: + return true; + case core::AddressSpace::kFunction: + return options.transform_function; + case core::AddressSpace::kPrivate: + return options.transform_private; + default: + break; + } + } + + if (param_type->IsHandle()) { + return options.transform_handle; + } + + return false; + } + + /// Walks the instructions that built @p value, deleting those that are no longer used. + /// @param value the pointer value that was used as a now replaced pointer argument. + void DeleteDeadInstructions(ir::Value* value) { + // While value has no uses... + while (value && !value->IsUsed()) { + auto* inst_res = value->As(); + if (!inst_res) { + return; // Only instructions can be removed. + } + value = tint::Switch( + inst_res->Instruction(), // + [&](Access* access) { + TINT_DEFER(access->Destroy()); + return access->Object(); + }, + [&](Let* let) { + TINT_DEFER(let->Destroy()); + return let->Value(); + }, + [&](Load* load) { + if (options.transform_handle) { + TINT_DEFER(load->Destroy()); + return load->From(); + } + return load->From(); + }); + } + } +}; + +} // namespace + +Result DirectVariableAccess(Module& ir, const DirectVariableAccessOptions& options) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.DirectVariableAccess", + kDirectVariableAccessCapabilities)); + + State{ir, options}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.h new file mode 100644 index 000000000..1e95d4187 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/direct_variable_access.h @@ -0,0 +1,85 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_DIRECT_VARIABLE_ACCESS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_DIRECT_VARIABLE_ACCESS_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kDirectVariableAccessCapabilities{ + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// DirectVariableAccessOptions adjusts the behaviour of the transform. +struct DirectVariableAccessOptions { + /// If true, then 'private' sub-object pointer arguments will be transformed. + bool transform_private = false; + /// If true, then 'function' sub-object pointer arguments will be transformed. + bool transform_function = false; + /// If true, then 'handle' sub-object handle type arguments will be transformed. + bool transform_handle = false; + + /// Reflection for this class + TINT_REFLECT(DirectVariableAccessOptions, + transform_private, + transform_function, + transform_handle); +}; + +/// DirectVariableAccess is a transform that transforms parameters in the 'storage', +/// 'uniform' and 'workgroup' address space so that they're accessed directly by the function, +/// instead of being passed by pointer. It will potentially also transform `private`, `handle` or +/// `function` parameters depending on provided options. +/// +/// DirectVariableAccess works by creating specializations of functions that have matching +/// parameters, one specialization for each argument's unique access chain 'shape' from a unique +/// variable. Calls to specialized functions are transformed so that the arguments are replaced with +/// an array of access-chain indices, and if the parameter is in the 'function' or 'private' +/// address space, also with a pointer to the root object. +/// +/// @param module the module to transform +/// @param options the options +/// @returns error on failure +Result DirectVariableAccess(Module& module, + const DirectVariableAccessOptions& options); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_DIRECT_VARIABLE_ACCESS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc new file mode 100644 index 000000000..8d035c0fc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc @@ -0,0 +1,612 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/multiplanar_external_texture.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/sampled_texture.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The external texture options. + const tint::transform::multiplanar::BindingsMap& multiplanar_map; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// The gamma transfer parameters structure. + const core::type::Struct* gamma_transfer_params_struct = nullptr; + + /// The external texture parameters structure. + const core::type::Struct* external_texture_params_struct = nullptr; + + /// The helper function that implements `textureLoad()`. + Function* texture_load_external = nullptr; + + /// The helper function that implements `textureSampleBaseClampToEdge()`. + Function* texture_sample_external = nullptr; + + /// The gamma correction helper function. + Function* gamma_correction = nullptr; + + /// Process the module. + Result Process() { + // Find module-scope variables that need to be replaced. + if (!ir.root_block->IsEmpty()) { + Vector to_remove; + for (auto inst : *ir.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + auto* ptr = var->Result()->Type()->As(); + if (ptr->StoreType()->Is()) { + TINT_CHECK_RESULT(ReplaceVar(var)); + to_remove.Push(var); + } + } + for (auto* remove : to_remove) { + remove->Destroy(); + } + } + + // Find function parameters that need to be replaced. + auto functions = ir.functions; + for (auto& func : functions) { + for (uint32_t index = 0; index < func->Params().Length(); index++) { + auto* param = func->Params()[index]; + if (param->Type()->Is()) { + ReplaceParameter(func, param, index); + } + } + } + + return Success; + } + + /// @returns a 2D sampled texture type with a f32 sampled type + const core::type::SampledTexture* SampledTexture() { + return ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()); + } + + /// Replace an external texture variable declaration. + /// @param old_var the variable declaration to replace + Result ReplaceVar(Var* old_var) { + auto name = ir.NameOf(old_var); + auto bp = old_var->BindingPoint(); + auto itr = multiplanar_map.find(bp.value()); + if (DAWN_UNLIKELY(itr == multiplanar_map.end())) { + std::stringstream err; + err << "ExternalTextureOptions missing binding entry for " << bp.value(); + return Failure{err.str()}; + } + const auto& new_binding_points = itr->second; + + // Create a sampled texture for the first plane. + auto* plane_0 = b.Var(ty.ptr(handle, SampledTexture())); + plane_0->SetBindingPoint(bp->group, bp->binding); + plane_0->InsertBefore(old_var); + if (name) { + ir.SetName(plane_0, name.Name() + "_plane0"); + } + + // Create a sampled texture for the second plane. + auto* plane_1 = b.Var(ty.ptr(handle, SampledTexture())); + plane_1->SetBindingPoint(new_binding_points.plane_1.group, + new_binding_points.plane_1.binding); + plane_1->InsertBefore(old_var); + if (name) { + ir.SetName(plane_1, name.Name() + "_plane1"); + } + + // Create a uniform buffer for the external texture parameters. + auto* external_texture_params = b.Var(ty.ptr(uniform, ExternalTextureParams())); + external_texture_params->SetBindingPoint(new_binding_points.params.group, + new_binding_points.params.binding); + external_texture_params->InsertBefore(old_var); + if (name) { + ir.SetName(external_texture_params, name.Name() + "_params"); + } + + // Replace all uses of the old variable with the new ones. + ReplaceUses(old_var->Result(), plane_0->Result(), plane_1->Result(), + external_texture_params->Result()); + + return Success; + } + + /// Replace an external texture function parameter. + /// @param func the function + /// @param old_param the function parameter to replace + /// @param index the index of the function parameter + void ReplaceParameter(Function* func, FunctionParam* old_param, uint32_t index) { + auto name = ir.NameOf(old_param); + + // Create a sampled texture for the first plane. + auto* plane_0 = b.FunctionParam(SampledTexture()); + if (name) { + ir.SetName(plane_0, name.Name() + "_plane0"); + } + + // Create a sampled texture for the second plane. + auto* plane_1 = b.FunctionParam(SampledTexture()); + if (name) { + ir.SetName(plane_1, name.Name() + "_plane1"); + } + + // Create the external texture parameters struct. + auto* external_texture_params = b.FunctionParam(ExternalTextureParams()); + if (name) { + ir.SetName(external_texture_params, name.Name() + "_params"); + } + + Vector new_params; + for (uint32_t i = 0; i < func->Params().Length(); i++) { + if (i == index) { + new_params.Push(plane_0); + new_params.Push(plane_1); + new_params.Push(external_texture_params); + } else { + new_params.Push(func->Params()[i]); + } + } + func->SetParams(std::move(new_params)); + + // Replace all uses of the old parameter with the new ones. + ReplaceUses(old_param, plane_0, plane_1, external_texture_params); + } + + /// Recursively replace the uses of @p value with @p new_value. + /// @param old_value the external texture value whose usages should be replaced + /// @param plane_0 the first plane of the replacement texture + /// @param plane_1 the second plane of the replacement texture + /// @param params the parameters of the replacement texture + void ReplaceUses(Value* old_value, Value* plane_0, Value* plane_1, Value* params) { + old_value->ForEachUseUnsorted([&](Usage use) { + tint::Switch( + use.instruction, + [&](Load* load) { + // Load both of the planes and the parameters struct. + Value* plane_0_load = nullptr; + Value* plane_1_load = nullptr; + Value* params_load = nullptr; + b.InsertBefore(load, [&] { + plane_0_load = b.Load(plane_0)->Result(); + plane_1_load = b.Load(plane_1)->Result(); + params_load = b.Load(params)->Result(); + }); + ReplaceUses(load->Result(), plane_0_load, plane_1_load, params_load); + load->Destroy(); + }, + [&](CoreBuiltinCall* call) { + if (call->Func() == core::BuiltinFn::kTextureDimensions) { + // Use params.apparentSize + vec2u(1, 1) instead of the textureDimensions. + b.InsertBefore(call, [&] { + auto* apparent_size = b.Access>(params, 12_u); + auto* vec2u_1_1 = b.Splat>(1_u); + auto* dimensions = b.Add(apparent_size, vec2u_1_1); + dimensions->SetResult(call->DetachResult()); + }); + call->Destroy(); + } else if (call->Func() == core::BuiltinFn::kTextureLoad) { + // Convert the coordinates to unsigned integers if necessary. + auto* coords = call->Args()[1]; + if (coords->Type()->IsSignedIntegerVector()) { + auto* convert = b.Convert(ty.vec2u(), coords); + convert->InsertBefore(call); + coords = convert->Result(); + } + + // Call the `TextureLoadExternal()` helper function. + auto* helper = b.CallWithResult(call->DetachResult(), TextureLoadExternal(), + plane_0, plane_1, params, coords); + helper->InsertBefore(call); + call->Destroy(); + } else if (call->Func() == core::BuiltinFn::kTextureSampleBaseClampToEdge) { + // Call the `TextureSampleExternal()` helper function. + auto* sampler = call->Args()[1]; + auto* coords = call->Args()[2]; + auto* helper = + b.CallWithResult(call->DetachResult(), TextureSampleExternal(), plane_0, + plane_1, params, sampler, coords); + helper->InsertBefore(call); + call->Destroy(); + } else { + TINT_IR_ICE(ir) + << "unhandled texture_external builtin call: " << call->Func(); + } + }, + [&](UserCall* call) { + // Decompose the external texture operand into both planes and the parameters. + Vector operands; + for (uint32_t i = 0; i < call->Operands().Length(); i++) { + if (i == use.operand_index) { + operands.Push(plane_0); + operands.Push(plane_1); + operands.Push(params); + } else { + operands.Push(call->Operands()[i]); + } + } + call->SetOperands(std::move(operands)); + }, // + TINT_ICE_ON_NO_MATCH); + }); + } + + /// @returns the gamma transfer parameters struct + const core::type::Struct* GammaTransferParams() { + if (!gamma_transfer_params_struct) { + gamma_transfer_params_struct = ty.Struct(sym.Register("tint_GammaTransferParams"), + { + {sym.Register("G"), ty.f32()}, + {sym.Register("A"), ty.f32()}, + {sym.Register("B"), ty.f32()}, + {sym.Register("C"), ty.f32()}, + {sym.Register("D"), ty.f32()}, + {sym.Register("E"), ty.f32()}, + {sym.Register("F"), ty.f32()}, + {sym.Register("padding"), ty.u32()}, + }); + } + return gamma_transfer_params_struct; + } + + /// @returns the external textures parameters struct + const core::type::Struct* ExternalTextureParams() { + if (!external_texture_params_struct) { + external_texture_params_struct = + ty.Struct(sym.Register("tint_ExternalTextureParams"), + {{sym.Register("numPlanes"), ty.u32()}, + {sym.Register("doYuvToRgbConversionOnly"), ty.u32()}, + {sym.Register("yuvToRgbConversionMatrix"), ty.mat3x4()}, + {sym.Register("gammaDecodeParams"), GammaTransferParams()}, + {sym.Register("gammaEncodeParams"), GammaTransferParams()}, + {sym.Register("gamutConversionMatrix"), ty.mat3x3()}, + {sym.Register("sampleTransform"), ty.mat3x2()}, + {sym.Register("loadTransform"), ty.mat3x2()}, + {sym.Register("samplePlane0RectMin"), ty.vec2f()}, + {sym.Register("samplePlane0RectMax"), ty.vec2f()}, + {sym.Register("samplePlane1RectMin"), ty.vec2f()}, + {sym.Register("samplePlane1RectMax"), ty.vec2f()}, + {sym.Register("apparentSize"), ty.vec2u()}, + {sym.Register("plane1CoordFactor"), ty.vec2f()}}); + } + return external_texture_params_struct; + } + + /// Gets or creates the gamma correction helper function. + /// @returns the function + Function* GammaCorrection() { + if (gamma_correction) { + return gamma_correction; + } + + // The helper function implements the following: + // fn tint_GammaCorrection(v : vec3f, params : GammaTransferParams) -> vec3f { + // let abs_v = abs(v); + // let sign_v = sign(v); + // let cond = abs_v < vec3f(params.D); + // let t = sign_v * ((params.C * abs_v) + params.F); + // let f = sign_v * (pow((params.A * abs_v) + params.B, vec3f(params.G)) + params.E); + // return select(f, t, cond); + // } + gamma_correction = b.Function("tint_GammaCorrection", ty.vec3f()); + auto* v = b.FunctionParam("v", ty.vec3f()); + auto* params = b.FunctionParam("params", GammaTransferParams()); + gamma_correction->SetParams({v, params}); + b.Append(gamma_correction->Block(), [&] { + auto* vec3f = ty.vec3f(); + auto* G = b.Access(ty.f32(), params, 0_u); + auto* A = b.Access(ty.f32(), params, 1_u); + auto* B = b.Access(ty.f32(), params, 2_u); + auto* C = b.Access(ty.f32(), params, 3_u); + auto* D = b.Access(ty.f32(), params, 4_u); + auto* E = b.Access(ty.f32(), params, 5_u); + auto* F = b.Access(ty.f32(), params, 6_u); + auto* G_splat = b.Construct(vec3f, G); + auto* D_splat = b.Construct(vec3f, D); + auto* abs_v = b.Call(vec3f, core::BuiltinFn::kAbs, v); + auto* sign_v = b.Call(vec3f, core::BuiltinFn::kSign, v); + auto* cond = b.LessThan(abs_v, D_splat); + auto* t = b.Multiply(sign_v, b.Add(b.Multiply(C, abs_v), F)); + auto* f = b.Multiply(sign_v, b.Add(b.Call(vec3f, core::BuiltinFn::kPow, + b.Add(b.Multiply(A, abs_v), B), G_splat), + E)); + b.Return(gamma_correction, b.Call(vec3f, core::BuiltinFn::kSelect, f, t, cond)); + }); + + return gamma_correction; + } + + /// Gets or creates the texture load helper function. + /// @returns the function + Function* TextureLoadExternal() { + if (texture_load_external) { + return texture_load_external; + } + + // The helper function implements the following: + // fn tint_TextureLoadExternal(plane0 : texture_2d, + // plane1 : texture_2d, + // coords : vec2, + // params : ExternalTextureParams) ->vec4f { + // let clampedCoords = min(coords, params.apparentSize); + // let plane0_clamped = vec2( + // round(params.loadTransform * vec3(vec2(clampedCoords), 1))); + // var color : vec4; + // if ((params.numPlanes == 1)) { + // color = textureLoad(plane0, plane0_clamped, 0).rgba; + // } else { + // let plane1_clamped = vec2(plane0_clamped) * params.plane1CoordFactor; + // + // color = vec4((vec4(textureLoad(plane0, plane0_clamped, 0).r, + // textureLoad(plane1, plane1_clamped, 0).rg, 1) * + // params.yuvToRgbConversionMatrix), + // 1); + // } + // if ((params.doYuvToRgbConversionOnly == 0)) { + // color = vec4(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a); + // color = vec4((params.gamutConversionMatrix * color.rgb), color.a); + // color = vec4(gammaCorrection(color.rgb, params.gammaEncodeParams), color.a); + // } + // return color; + // } + texture_load_external = b.Function("tint_TextureLoadExternal", ty.vec4f()); + auto* plane_0 = b.FunctionParam("plane_0", SampledTexture()); + auto* plane_1 = b.FunctionParam("plane_1", SampledTexture()); + auto* params = b.FunctionParam("params", ExternalTextureParams()); + auto* coords = b.FunctionParam("coords", ty.vec2u()); + texture_load_external->SetParams({plane_0, plane_1, params, coords}); + b.Append(texture_load_external->Block(), [&] { + auto* vec2f = ty.vec2f(); + auto* vec3f = ty.vec3f(); + auto* vec4f = ty.vec4f(); + auto* vec2u = ty.vec2u(); + auto* yuv_to_rgb_conversion_only = b.Access(ty.u32(), params, 1_u); + auto* yuv_to_rgb_conversion = b.Access(ty.mat3x4(), params, 2_u); + auto* load_transform_matrix = b.Access(ty.mat3x2(), params, 7_u); + auto* apparent_size = b.Access(ty.vec2u(), params, 12_u); + auto* plane1_coord_factor = b.Access(ty.vec2f(), params, 13_u); + + auto* clamped_coords = b.Min(coords, apparent_size); + auto* clamped_coords_f = b.Convert(vec2f, clamped_coords); + auto* modified_coords = + b.Multiply(load_transform_matrix, b.Construct(vec3f, clamped_coords_f, 1_f)); + auto* plane0_clamped_f = b.Call(vec2f, core::BuiltinFn::kRound, modified_coords); + + auto* plane0_clamped = b.Convert(vec2u, plane0_clamped_f); + + auto* rgb_result = b.InstructionResult(vec3f); + auto* alpha_result = b.InstructionResult(ty.f32()); + auto* num_planes = b.Access(ty.u32(), params, 0_u); + auto* if_planes_eq_1 = b.If(b.Equal(num_planes, 1_u)); + if_planes_eq_1->SetResults(rgb_result, alpha_result); + b.Append(if_planes_eq_1->True(), [&] { + // Load the texel from the first plane and split into separate rgb and a values. + auto* texel = + b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_0, plane0_clamped, 0_u); + auto* rgb = b.Swizzle(vec3f, texel, {0u, 1u, 2u}); + auto* a = b.Access(ty.f32(), texel, 3_u); + b.ExitIf(if_planes_eq_1, rgb, a); + }); + b.Append(if_planes_eq_1->False(), [&] { + // Load the y value from the first plane. + auto* y = b.Access( + ty.f32(), + b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_0, plane0_clamped, 0_u), + 0_u); + + // Load the uv value from the second plane. + auto* plane1_clamped_f = b.Multiply(plane0_clamped_f, plane1_coord_factor); + + auto* plane1_clamped = b.Convert(vec2u, plane1_clamped_f); + auto* uv = b.Swizzle( + vec2f, + b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_1, plane1_clamped, 0_u), + {0u, 1u}); + + // Convert the combined yuv value into rgb and set the alpha to 1.0. + b.ExitIf(if_planes_eq_1, + b.Multiply(b.Construct(vec4f, y, uv, 1_f), yuv_to_rgb_conversion), 1_f); + }); + + // Apply gamma correction if needed. + auto* final_result = b.InstructionResult(vec3f); + auto* if_gamma_correct = b.If(b.Equal(yuv_to_rgb_conversion_only, 0_u)); + if_gamma_correct->SetResult(final_result); + b.Append(if_gamma_correct->True(), [&] { + auto* gamma_decode_params = b.Access(GammaTransferParams(), params, 3_u); + auto* gamma_encode_params = b.Access(GammaTransferParams(), params, 4_u); + auto* gamut_conversion_matrix = b.Access(ty.mat3x3(), params, 5_u); + auto* decoded = b.Call(vec3f, GammaCorrection(), rgb_result, gamma_decode_params); + auto* converted = b.Multiply(gamut_conversion_matrix, decoded); + auto* encoded = b.Call(vec3f, GammaCorrection(), converted, gamma_encode_params); + b.ExitIf(if_gamma_correct, encoded); + }); + b.Append(if_gamma_correct->False(), [&] { // + b.ExitIf(if_gamma_correct, rgb_result); + }); + + b.Return(texture_load_external, b.Construct(vec4f, final_result, alpha_result)); + }); + + return texture_load_external; + } + + /// Gets or creates the texture sample helper function. + /// @returns the function + Function* TextureSampleExternal() { + if (texture_sample_external) { + return texture_sample_external; + } + + // The helper function implements the following: + // fn textureSampleExternal(plane0 : texture_2d, + // plane1 : texture_2d, + // smp : sampler, + // coord : vec2f, + // params : ExternalTextureParams) ->vec4f { + // let modifiedCoords = (params.sampleTransform * vec3(coord, 1)); + // let plane0_clamped = + // clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax); + // var color : vec4; + // + // if ((params.numPlanes == 1)) { + // color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba; + // } else { + // let plane1_clamped = + // clamp(modifiedCoords, params.samplePlane1RectMin, + // params.samplePlane1RectMax); + // color = vec4( + // vec4(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, + // textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * + // params.yuvToRgbConversionMatrix), 1); + // } + // + // if ((params.doYuvToRgbConversionOnly == 0)) { + // color = vec4(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a); + // color = vec4((params.gamutConversionMatrix * color.rgb), color.a); + // color = vec4(gammaCorrection(color.rgb, params.gammaEncodeParams), color.a); + // } + // + // return color; + // } + texture_sample_external = b.Function("tint_TextureSampleExternal", ty.vec4f()); + auto* plane_0 = b.FunctionParam("plane_0", SampledTexture()); + auto* plane_1 = b.FunctionParam("plane_1", SampledTexture()); + auto* params = b.FunctionParam("params", ExternalTextureParams()); + auto* sampler = b.FunctionParam("tint_sampler", ty.sampler()); + auto* coords = b.FunctionParam("coords", ty.vec2f()); + texture_sample_external->SetParams({plane_0, plane_1, params, sampler, coords}); + b.Append(texture_sample_external->Block(), [&] { + auto* vec2f = ty.vec2f(); + auto* vec3f = ty.vec3f(); + auto* vec4f = ty.vec4f(); + auto* yuv_to_rgb_conversion_only = b.Access(ty.u32(), params, 1_u); + auto* yuv_to_rgb_conversion = b.Access(ty.mat3x4(), params, 2_u); + auto* transformation_matrix = b.Access(ty.mat3x2(), params, 6_u); + auto* sample_plane0_rect_min = b.Access(ty.vec2f(), params, 8_u); + auto* sample_plane0_rect_max = b.Access(ty.vec2f(), params, 9_u); + auto* sample_plane1_rect_min = b.Access(ty.vec2f(), params, 10_u); + auto* sample_plane1_rect_max = b.Access(ty.vec2f(), params, 11_u); + + auto* modified_coords = + b.Multiply(transformation_matrix, b.Construct(vec3f, coords, 1_f)); + auto* plane0_clamped = + b.Clamp(modified_coords, sample_plane0_rect_min, sample_plane0_rect_max); + + auto* rgb_result = b.InstructionResult(vec3f); + auto* alpha_result = b.InstructionResult(ty.f32()); + auto* num_planes = b.Access(ty.u32(), params, 0_u); + auto* if_planes_eq_1 = b.If(b.Equal(num_planes, 1_u)); + if_planes_eq_1->SetResults(rgb_result, alpha_result); + b.Append(if_planes_eq_1->True(), [&] { + // Sample the texel from the first plane and split into separate rgb and a values. + auto* texel = b.Call(vec4f, core::BuiltinFn::kTextureSampleLevel, plane_0, sampler, + plane0_clamped, 0_f); + auto* rgb = b.Swizzle(vec3f, texel, {0u, 1u, 2u}); + auto* a = b.Access(ty.f32(), texel, 3_u); + b.ExitIf(if_planes_eq_1, rgb, a); + }); + b.Append(if_planes_eq_1->False(), [&] { + // Sample the y value from the first plane. + auto* y = b.Access(ty.f32(), + b.Call(vec4f, core::BuiltinFn::kTextureSampleLevel, plane_0, + sampler, plane0_clamped, 0_f), + 0_u); + auto* plane1_clamped = + b.Clamp(modified_coords, sample_plane1_rect_min, sample_plane1_rect_max); + + // Sample the uv value from the second plane. + auto* uv = b.Swizzle(vec2f, + b.Call(vec4f, core::BuiltinFn::kTextureSampleLevel, plane_1, + sampler, plane1_clamped, 0_f), + {0u, 1u}); + + // Convert the combined yuv value into rgb and set the alpha to 1.0. + b.ExitIf(if_planes_eq_1, + b.Multiply(b.Construct(vec4f, y, uv, 1_f), yuv_to_rgb_conversion), 1_f); + }); + + // Apply gamma correction if needed. + auto* final_result = b.InstructionResult(vec3f); + auto* if_gamma_correct = b.If(b.Equal(yuv_to_rgb_conversion_only, 0_u)); + if_gamma_correct->SetResult(final_result); + b.Append(if_gamma_correct->True(), [&] { + auto* gamma_decode_params = b.Access(GammaTransferParams(), params, 3_u); + auto* gamma_encode_params = b.Access(GammaTransferParams(), params, 4_u); + auto* gamut_conversion_matrix = b.Access(ty.mat3x3(), params, 5_u); + auto* decoded = b.Call(vec3f, GammaCorrection(), rgb_result, gamma_decode_params); + auto* converted = b.Multiply(gamut_conversion_matrix, decoded); + auto* encoded = b.Call(vec3f, GammaCorrection(), converted, gamma_encode_params); + b.ExitIf(if_gamma_correct, encoded); + }); + b.Append(if_gamma_correct->False(), [&] { // + b.ExitIf(if_gamma_correct, rgb_result); + }); + + b.Return(texture_sample_external, b.Construct(vec4f, final_result, alpha_result)); + }); + + return texture_sample_external; + } +}; + +} // namespace + +Result MultiplanarExternalTexture( + Module& ir, + const tint::transform::multiplanar::BindingsMap& multiplanar_map) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.MultiplanarExternalTexture", + kMultiplanarExternalTextureCapabilities)); + + return State{multiplanar_map, ir}.Process(); +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.h new file mode 100644 index 000000000..680f75756 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_external_texture.h @@ -0,0 +1,61 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_EXTERNAL_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_EXTERNAL_TEXTURE_H_ + +#include "src/tint/lang/core/ir/transform/multiplanar_options.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kMultiplanarExternalTextureCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// MultiplanarExternalTexture is a transform that splits texture_external bindings into two +/// separate texture_2d bindings for two possible planes, along with a uniform buffer of +/// parameters that describe how the texture should be sampled. +/// @param module the module to transform +/// @param options the external texture options +/// @returns success or failure +Result MultiplanarExternalTexture( + Module& module, + const tint::transform::multiplanar::BindingsMap& options); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_EXTERNAL_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_options.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_options.h new file mode 100644 index 000000000..51d8a8532 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/multiplanar_options.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_OPTIONS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_OPTIONS_H_ + +#include + +#include "src/tint/api/common/binding_point.h" + +namespace tint::transform::multiplanar { + +/// This struct identifies the binding groups and locations for new bindings to +/// use when transforming a texture_external instance. +struct BindingPoints { + /// The desired binding location of the texture_2d representing plane #1 when + /// a texture_external binding is expanded. + BindingPoint plane_1; + /// The desired binding location of the ExternalTextureParams uniform when a + /// texture_external binding is expanded. + BindingPoint params; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(BindingPoints, plane_1, params); +}; + +/// BindingsMap is a map where the key is the binding location of a +/// texture_external and the value is a struct containing the desired +/// locations for new bindings expanded from the texture_external instance. +using BindingsMap = std::unordered_map; + +} // namespace tint::transform::multiplanar + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_OPTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.cc new file mode 100644 index 000000000..f36a58ae7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.cc @@ -0,0 +1,162 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/prepare_immediate_data.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/utils/ice/ice.h" + +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +constexpr uint32_t kMaxImmediateBlockSize = 0x1000; + +/// PIMPL state for the transform. +struct State { + /// The transform config. + const PrepareImmediateDataConfig& config; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + Result Run() { + if (config.internal_immediate_data.empty()) { + return ImmediateDataLayout{}; + } + + ImmediateDataLayout layout; + Var* user_defined_immediates = nullptr; + Vector members; + + // Check for user-defined immediate data. + for (auto inst : *ir.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + auto* ptr = var->Result()->Type()->As(); + if (!ptr || ptr->AddressSpace() != core::AddressSpace::kImmediate) { + continue; + } + + if (user_defined_immediates) { + TINT_IR_ICE(ir) << "multiple user-defined immediate data variables"; + } + user_defined_immediates = var; + + // Assume that user-defined constants start at offset 0 until Dawn tells us otherwise. + members.Push(ty.Get(ir.symbols.New("user_immediate_data"), + ptr->StoreType(), + /* index */ 0u, + /* offset */ 0u, + /* align */ ptr->StoreType()->Align(), + /* size */ ptr->StoreType()->Size(), + /* attributes */ IOAttributes{})); + } + + // Create the structure and immediate data variable. + for (auto& internal : config.internal_immediate_data) { + auto offset = internal.first; + + if (!members.IsEmpty()) { + if (members.Back()->Offset() + members.Back()->Size() > offset) { + return Failure("immediate offset for '" + internal.second.name.Name() + + "' overlaps with previous member '" + + members.Back()->Name().Name() + "'"); + } + } + if (offset & (internal.second.type->Align() - 1)) { + return Failure("immediate offset for '" + internal.second.name.Name() + + "' must be aligned to " + + std::to_string(internal.second.type->Align()) + " bytes"); + } + if (offset + internal.second.type->Size() > kMaxImmediateBlockSize) { + return Failure("immediate '" + internal.second.name.Name() + + "' exceeds maximum immediate block size"); + } + + auto index = static_cast(members.Length()); + layout.offset_to_index.Add(offset, index); + members.Push(ty.Get(internal.second.name, + internal.second.type, + /* index */ index, + /* offset */ offset, + /* align */ internal.second.type->Align(), + /* size */ internal.second.type->Size(), + /* attributes */ IOAttributes{})); + } + + auto* immediate_constant_struct = + ty.Struct(ir.symbols.New("tint_immediate_data_struct"), std::move(members)); + immediate_constant_struct->SetStructFlag(type::kBlock); + layout.var = + b.Var("tint_immediate_data", core::AddressSpace::kImmediate, immediate_constant_struct); + ir.root_block->Append(layout.var); + + // Update uses of the user defined immediate data variable. + if (user_defined_immediates) { + user_defined_immediates->Result()->ReplaceAllUsesWith([&](Usage use) { + auto* access = b.Access(user_defined_immediates->Result()->Type(), layout.var, 0_u); + access->InsertBefore(use.instruction); + return access->Result(); + }); + user_defined_immediates->Destroy(); + } + + return layout; + } +}; + +} // namespace + +Result PrepareImmediateData(Module& ir, + const PrepareImmediateDataConfig& config) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.PrepareImmediateData", + core::ir::Capabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllowNonCoreTypes, + })); + + return State{config, ir}.Run(); +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.h new file mode 100644 index 000000000..6021d0cde --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/prepare_immediate_data.h @@ -0,0 +1,102 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_PREPARE_IMMEDIATE_DATA_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_PREPARE_IMMEDIATE_DATA_H_ + +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" +#include "src/tint/utils/symbol/symbol.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +class Var; +} // namespace tint::core::ir +namespace tint::core::type { +class Type; +} + +namespace tint::core::ir::transform { + +/// A descriptor for an internal immediate constant. +struct InternalImmediateData { + Symbol name; + const core::type::Type* type = nullptr; +}; + +/// A struct that describes the layout of the generated immediate data structure. +struct ImmediateDataLayout { + /// The immediate data variable. + core::ir::Var* var = nullptr; + + /// A map from member offset to member index. + Hashmap offset_to_index; + + /// @returns the member index of the constant at @p offset + uint32_t IndexOf(uint32_t offset) const { + auto itr = offset_to_index.Get(offset); + TINT_ASSERT(itr); + return *itr.value; + } +}; + +/// The internally created immediate data members. +struct PrepareImmediateDataConfig { + /// Add an internal immediate data to the map. + Result AddInternalImmediateData(uint32_t offset, + Symbol name, + const core::type::Type* type) { + auto res = internal_immediate_data.emplace(offset, InternalImmediateData{name, type}); + if (!res.second) { + return Failure("mutiple internal immediates created at offset " + + std::to_string(offset)); + } + return Success; + } + + /// The ordered map from offset to internally used constant descriptor. + std::map internal_immediate_data{}; + + /// Reflection for this class. + TINT_REFLECT(PrepareImmediateDataConfig, internal_immediate_data); +}; + +/// PrepareImmediateData is a transform that sets up the structure and variable used for immediate +/// data to combine both user-defined and internally used immediate data values. +/// @param module the module to transform +/// @param config the transform config +/// @returns the generated immediate constant layout or failure +Result PrepareImmediateData(Module& module, + const PrepareImmediateDataConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_PREPARE_IMMEDIATE_DATA_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.cc new file mode 100644 index 000000000..0178f0dcf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.cc @@ -0,0 +1,180 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/preserve_padding.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// Map from a type to a helper function that will store a decomposed value. + Hashmap helpers{}; + + /// Process the module. + void Process() { + // Find host-visible stores of types that contain padding bytes. + Vector worklist; + for (auto inst : ir.Instructions()) { + if (auto* store = inst->As()) { + auto* ptr = store->To()->Type()->As(); + if (ptr->AddressSpace() == core::AddressSpace::kStorage && + ContainsPadding(ptr->StoreType())) { + worklist.Push(store); + } + } + } + + // Replace the stores we found with calls to helper functions that decompose the accesses. + for (auto* store : worklist) { + auto* replacement = MakeStore(store->To(), store->From()); + store->ReplaceWith(replacement); + store->Destroy(); + } + } + + /// Check if a type contains padding bytes. + /// @param type the type to check + /// @returns true if the type contains padding bytes + bool ContainsPadding(const type::Type* type) { + return tint::Switch( + type, // + [&](const type::Array* arr) { + auto* elem_ty = arr->ElemType(); + if (arr->ImplicitStride() > elem_ty->Size()) { + return true; + } + return ContainsPadding(elem_ty); + }, + [&](const type::Matrix* mat) { + return mat->ColumnStride() > mat->ColumnType()->Size(); + }, + [&](const type::Struct* str) { + uint32_t current_offset = 0; + for (auto* member : str->Members()) { + if (member->Offset() > current_offset) { + return true; + } + if (ContainsPadding(member->Type())) { + return true; + } + current_offset += member->Type()->Size(); + } + return (current_offset < str->Size()); + }); + } + + /// Create an instruction that stores a (possibly padded) type to memory, decomposing the access + /// into separate components to preserve padding if necessary. + /// @param to the pointer to store to + /// @param value the value to store + /// @returns the instruction that performs the store + Instruction* MakeStore(Value* to, Value* value) { + auto* store_type = value->Type(); + + // If there are no padding bytes in this type, just use a regular store instruction. + if (!ContainsPadding(store_type)) { + return b.Store(to, value); + } + + // The type contains padding bytes, so call a helper function that decomposes the accesses. + auto* helper = helpers.GetOrAdd(store_type, [&] { + auto* func = b.Function("tint_store_and_preserve_padding", ty.void_()); + auto* target = b.FunctionParam("target", ty.ptr(storage, store_type)); + auto* value_param = b.FunctionParam("value_param", store_type); + func->SetParams({target, value_param}); + + b.Append(func->Block(), [&] { + tint::Switch( + store_type, // + [&](const type::Array* arr) { + b.LoopRange(0_u, u32(arr->ConstantCount().value()), 1_u, [&](Value* idx) { + auto* el_ptr = b.Access(ty.ptr(storage, arr->ElemType()), target, idx); + auto* el_value = b.Access(arr->ElemType(), value_param, idx); + MakeStore(el_ptr->Result(), el_value->Result()); + }); + }, + [&](const type::Matrix* mat) { + for (uint32_t i = 0; i < mat->Columns(); i++) { + auto* col_ptr = + b.Access(ty.ptr(storage, mat->ColumnType()), target, u32(i)); + auto* col_value = b.Access(mat->ColumnType(), value_param, u32(i)); + MakeStore(col_ptr->Result(), col_value->Result()); + } + }, + [&](const type::Struct* str) { + for (auto* member : str->Members()) { + auto* sub_ptr = b.Access(ty.ptr(storage, member->Type()), target, + u32(member->Index())); + auto* sub_value = + b.Access(member->Type(), value_param, u32(member->Index())); + MakeStore(sub_ptr->Result(), sub_value->Result()); + } + }); + + b.Return(func); + }); + + return func; + }); + + return b.Call(helper, to, value); + } +}; + +} // namespace + +Result PreservePadding(Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.PreservePadding", kPreservePaddingCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.h new file mode 100644 index 000000000..cc08dea59 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/preserve_padding.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_PRESERVE_PADDING_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_PRESERVE_PADDING_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kPreservePaddingCapabilities{ + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// PreservePadding is a transform that decomposes stores of whole structure and array types to +/// preserve padding bytes. +/// +/// @note assumes that DirectVariableAccess will be run afterwards for backends that need it. +/// @param module the module to transform +/// @returns success or failure +Result PreservePadding(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_PRESERVE_PADDING_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.cc new file mode 100644 index 000000000..dd04e96d2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.cc @@ -0,0 +1,127 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/prevent_infinite_loops.h" + +#include + +#include "src/tint/lang/core/ir/analysis/loop_analysis.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// Process the module. + void Process() { + for (auto func : ir.functions) { + // Look for loops in the function that we cannot detect as being finite, and inject a + // a new loop index that bounds the loop to 2^64 iterations. + analysis::LoopAnalysis analysis(*func); + Traverse(func->Block(), [&](Loop* loop) { + if (!analysis.GetInfo(*loop)->IsFinite()) { + InjectExitCondition(loop); + } + }); + } + } + + /// Inject an exit condition into @p loop. + /// @param loop the `loop` to inject the condition into + void InjectExitCondition(Loop* loop) { + // Initializer: + // var idx: vec2u = vec2(UINT32_MAX); + // + // Body: + // if all(idx == vec2(0)) { break; } + // + // Continuing: + // idx.x -= 1; + // idx.y -= u32(idx.x == UINT32_MAX); + + // Declare a new index variable at the top of the loop initializer. + auto* idx = b.Var("tint_loop_idx", b.Splat>(u32::Highest())); + if (loop->Initializer()->IsEmpty()) { + loop->Initializer()->Append(b.NextIteration(loop)); + } + loop->Initializer()->Prepend(idx); + + // Insert the new exit condition at the top of the loop body. + b.InsertBefore(loop->Body()->Front(), [&] { + auto* ifelse = b.If(b.Call( + BuiltinFn::kAll, b.Equal(b.Load(idx)->Result(), b.Splat>(0_u)))); + b.Append(ifelse->True(), [&] { + // If the loop produces result values, just use `undef` as this exit condition + // should never actually be hit. + Vector results; + results.Resize(loop->Results().Length(), nullptr); + b.ExitLoop(loop, std::move(results)); + }); + }); + + // Increment the index variable at the top of the continuing block. + if (loop->Continuing()->IsEmpty()) { + loop->Continuing()->Append(b.NextIteration(loop)); + } + b.InsertBefore(loop->Continuing()->Front(), [&] { + auto* low_inc = b.Subtract(b.LoadVectorElement(idx, 0_u), 1_u); + ir.SetName(low_inc->Result(), ir.symbols.New("tint_low_inc")); + b.StoreVectorElement(idx, 0_u, low_inc); + + auto* carry = b.Convert(b.Equal(low_inc, u32::Highest())); + ir.SetName(carry->Result(), ir.symbols.New("tint_carry")); + b.StoreVectorElement(idx, 1_u, b.Subtract(b.LoadVectorElement(idx, 1_u), carry)); + }); + } +}; + +} // namespace + +Result PreventInfiniteLoops(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.PreventInfiniteLoops", + kPreventInfiniteLoopsCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.h new file mode 100644 index 000000000..11a4cc9c0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/prevent_infinite_loops.h @@ -0,0 +1,57 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_PREVENT_INFINITE_LOOPS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_PREVENT_INFINITE_LOOPS_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kPreventInfiniteLoopsCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllow8BitIntegers, +}; + +/// PreventInfiniteLoops is a transform that injects an additional exit condition into loops that +/// may be infinite, to prevent downstream compilers from making bad assumptions due to the +/// undefined behavior of infinite loops. +/// +/// @param module the module to transform +/// @returns success or failure +Result PreventInfiniteLoops(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_PREVENT_INFINITE_LOOPS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc new file mode 100644 index 000000000..c828bcf29 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc @@ -0,0 +1,138 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/remove_continue_in_switch.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// A map from `switch` instruction to the flag used to indicate whether a `continue` was hit. + Hashmap continue_flag_for_switch{}; + + /// Process the module. + void Process() { + // Look for `continue` instructions. + for (auto* inst : ir.Instructions()) { + auto* cont = inst->As(); + if (!cont) { + continue; + } + + // Check if this `continue` is inside a `switch` that is inside the `loop`. + // Do this by walking up the stack of control flow instructions until we see a `loop`. + // If we hit a `switch` before we see the loop, we need to replace the `continue`. + auto* parent = cont->Block()->Parent(); + while (!parent->Is()) { + if (auto* swtch = parent->As()) { + ReplaceContinue(cont, swtch); + break; + } + parent = parent->Block()->Parent(); + } + } + } + + /// Replace a `continue` instruction. + /// @param cont the `continue` to replace + /// @param swtch the `switch` instruction that it is nested inside + void ReplaceContinue(Continue* cont, Switch* swtch) { + auto* flag = GetContinueFlag(swtch, cont->Loop()); + b.InsertBefore(cont, [&] { + b.Store(flag, true); + + // If the switch produces result values, just use `undef` as the switch result will not + // be used in this codepath. + Vector results; + results.Resize(swtch->Results().Length(), nullptr); + b.ExitSwitch(swtch, std::move(results)); + }); + cont->Destroy(); + } + + /// Get or create the flag used to indicate whether a `continue` was hit. + /// @param swtch the `switch` instruction to get the flag for + /// @param loop the `loop` that is the target of `continue` instruction in this switch + /// @returns the flag variable + Var* GetContinueFlag(Switch* swtch, Loop* loop) { + return continue_flag_for_switch.GetOrAdd(swtch, [&] { + // Declare the flag before the switch statement. + auto* flag = b.Var("tint_continue"); + flag->InsertBefore(swtch); + + // Check the flag after the `switch` instruction and `continue` if it was set. + b.InsertAfter(swtch, [&] { + auto* check = b.If(b.Load(flag)); + b.Append(check->True(), [&] { // + b.Continue(loop); + }); + }); + + return flag; + }); + } +}; + +} // namespace + +Result RemoveContinueInSwitch(Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.RemoveContinueInSwitch", + core::ir::Capabilities{ + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.h new file mode 100644 index 000000000..6a15b3390 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_continue_in_switch.h @@ -0,0 +1,52 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_CONTINUE_IN_SWITCH_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_CONTINUE_IN_SWITCH_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// RemoveContinueInSwitch is a transform that removes `continue` instructions that are nested +/// inside `switch` instructions, and instead sets a flag which is checked after the `switch`. +/// +/// This is needed because textual backends inline loop continuing blocks at the location of each +/// `continue`, which would lead to a `break` unintentionally breaking from the switch instead of +/// the loop. +/// @param module the module to transform +/// @returns success or failure +Result RemoveContinueInSwitch(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_CONTINUE_IN_SWITCH_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.cc new file mode 100644 index 000000000..a07190dee --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.cc @@ -0,0 +1,174 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/remove_terminator_args.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// A list of terminators that need to have their arguments cleared. + Vector terminators_to_clear{}; + + /// Process the module. + void Process() { + // Loop over every instruction looking for control instructions. + for (auto* inst : ir.Instructions()) { + tint::Switch( + inst, + [&](If* i) { // + RemoveExitArgs(i); + }, + [&](Loop* l) { // + RemoveExitArgs(l); + RemoveBlockParams(l->Body(), l->Initializer()->Front()); + RemoveBlockParams(l->Continuing(), l->Body()->Front()); + }, + [&](Switch* s) { // + RemoveExitArgs(s); + }); + + // Remove arguments from all terminators that we found. + for (auto* terminator : terminators_to_clear) { + if (auto* breakif = terminator->As()) { + breakif->SetNumNextIterValues(0); + // We retain the condition operand on break_if instructions. + breakif->SetOperands(Vector{breakif->Condition()}); + } else { + terminator->ClearOperands(); + } + } + terminators_to_clear.Clear(); + } + } + + /// Remove the arguments from all exit instructions inside a control instruction. + /// @param ci the control instruction + void RemoveExitArgs(ControlInstruction* ci) { + // Loop over all of the instruction results. + for (size_t i = 0; i < ci->Results().Length(); i++) { + auto* result = ci->Result(i); + + // Create a variable to hold the result, and insert it before the control instruction. + auto* var = b.Var(ty.ptr(result->Type())); + var->InsertBefore(ci); + + // Store to the variable before each exit instruction. + for (auto exit : ci->Exits()) { + Value* value = nullptr; + if (auto* breakif = exit.Value()->As()) { + value = breakif->ExitValues()[i]; + } else { + value = exit.Value()->Args()[i]; + } + if (value) { + auto* store = b.Store(var, value); + store->InsertBefore(exit.Value()); + } + } + + // Replace the original result with a load from the variable that we created above. + auto* load = b.LoadWithResult(result, var); + load->InsertAfter(ci); + } + + // Remove the arguments from the exits and the results from the control instruction. + for (auto exit : ci->Exits()) { + terminators_to_clear.Push(exit); + } + ci->ClearResults(); + } + + /// Remove block parameters and arguments from all branches to a block. + /// @param block the block + /// @param var_insertion_point the insertion point for variables used to replace parameters + void RemoveBlockParams(MultiInBlock* block, Instruction* var_insertion_point) { + for (size_t i = 0; i < block->Params().Length(); i++) { + auto* param = block->Params()[i]; + + // Create a variable to hold the parameter value, and insert it in the parent block. + auto* var = b.Var(ty.ptr(param->Type())); + var->InsertBefore(var_insertion_point); + + // Store to the variable before each branch. + for (auto* branch : block->InboundSiblingBranches()) { + Value* value = nullptr; + if (auto* breakif = branch->As()) { + value = breakif->NextIterValues()[i]; + } else { + value = branch->Args()[i]; + } + if (value) { + auto* store = b.Store(var, value); + store->InsertBefore(branch); + } + } + + // Replace the original result with a load from the variable that we created above. + auto* load = b.Load(var); + load->InsertBefore(block->Front()); + param->ReplaceAllUsesWith(load->Result()); + } + + // Remove the arguments from the branches and the parameters from the block. + for (auto exit : block->InboundSiblingBranches()) { + terminators_to_clear.Push(exit); + } + block->SetParams({}); + } +}; + +} // namespace + +Result RemoveTerminatorArgs(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.RemoveTerminatorArgs", + kRemoveTerminatorArgsCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.h new file mode 100644 index 000000000..ddac57a83 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_terminator_args.h @@ -0,0 +1,68 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_TERMINATOR_ARGS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_TERMINATOR_ARGS_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kRemoveTerminatorArgsCapabilities{ + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllow64BitIntegers, + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPointSizeBuiltin, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowAnyLetType, + core::ir::Capability::kAllowModuleScopeLets, + core::ir::Capability::kMslAllowEntryPointInterface, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// RemoveTerminatorArgs is a transform that removes all arguments from terminator instructions and +/// replaces them with stores to temporary variables instead. This is needed to prepare codegen for +/// textual languages. +/// @param module the module to transform +/// @returns success or failure +Result RemoveTerminatorArgs(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_TERMINATOR_ARGS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.cc new file mode 100644 index 000000000..7ee131916 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.cc @@ -0,0 +1,93 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// Process the module. + void Process() { + // Find all load_vector_element instructions that need to be replaced. + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* lve = inst->As()) { + auto* ptr = lve->From()->Type()->As(); + if (ptr->AddressSpace() == core::AddressSpace::kUniform) { + worklist.Push(lve); + } + } + } + + // Replace the instructions that we found. + for (auto* lve : worklist) { + b.InsertBefore(lve, [&] { + // Capture the `load` in a `let` so that it does not get inlined. + // This is necessary for the GLSL backend, where inlining the load expression will + // turn it into a reference that defers the load until the component is accessed. + auto* load = b.Load(lve->From()); + auto* let = b.Let(load); + auto* access = b.Access(lve->Result()->Type(), let, lve->Index()); + lve->Result()->ReplaceAllUsesWith(access->Result()); + }); + lve->Destroy(); + } + } +}; + +} // namespace + +Result RemoveUniformVectorComponentLoads(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.RemoveUniformVectorComponentLoads", + core::ir::Capabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.h new file mode 100644 index 000000000..e249d4a49 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.h @@ -0,0 +1,49 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_UNIFORM_VECTOR_COMPONENT_LOADS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_UNIFORM_VECTOR_COMPONENT_LOADS_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// RemoveUniformVectorComponentLoads is a transform that removes load_vector_element instructions +/// for uniform buffers. Instead, we load the whole vector and then extract the desired component. +/// This is to avoid a bug on Qualcomm devices (see crbug.com/452350626). +/// @param module the module to transform +/// @returns success or failure +Result RemoveUniformVectorComponentLoads(core::ir::Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_REMOVE_UNIFORM_VECTOR_COMPONENT_LOADS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.cc new file mode 100644 index 000000000..86dc36202 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.cc @@ -0,0 +1,311 @@ + +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/rename_conflicts.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/scalar.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/string.h" + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform, for a single function. +struct State { + /// Constructor + /// @param i the IR module + explicit State(core::ir::Module& i) : ir(i) {} + + /// Processes the module, renaming all declarations that would prevent an identifier resolving + /// to the correct declaration. + void Process() { + scopes.Push(Scope{}); + TINT_DEFER(scopes.Clear()); + + RegisterModuleScopeDecls(); + + // Process the types + for (auto* ty : ir.Types()) { + EnsureResolvable(ty); + } + + // Process the module-scope variable declarations + for (auto* inst : *ir.root_block) { + Process(inst); + } + + // Process the functions + for (core::ir::Function* fn : ir.functions) { + scopes.Push(Scope{}); + TINT_DEFER(scopes.Pop()); + for (auto* param : fn->Params()) { + EnsureResolvable(param->Type()); + if (auto symbol = ir.NameOf(param); symbol.IsValid()) { + Declare(param, symbol); + } + } + Process(fn->Block()); + } + } + + private: + /// Map of identifier to declaration. + /// The declarations may be one of an core::ir::Value or core::type::Struct. + using Scope = Hashmap; + + /// The IR module. + core::ir::Module& ir; + + /// Stack of scopes + Vector scopes{}; + + /// Registers all the module-scope declarations in the root-scope. + /// Duplicate declarations with the same name will renamed. + void RegisterModuleScopeDecls() { + // Declare all the user types + for (auto* ty : ir.Types()) { + if (auto* str = ty->As()) { + if (!IsBuiltinStruct(str)) { + Declare(const_cast(str), str->Name()); + } + } + } + + // Declare all the module-scope vars + for (auto* inst : *ir.root_block) { + for (auto* result : inst->Results()) { + if (auto symbol = ir.NameOf(result)) { + Declare(result, symbol); + } + } + } + + // Declare all the functions + for (core::ir::Function* fn : ir.functions) { + if (auto symbol = ir.NameOf(fn); symbol.IsValid()) { + Declare(fn, symbol); + } + } + } + + /// Processes the instructions of the block + void Process(core::ir::Block* block) { + for (auto* inst : *block) { + Process(inst); + } + } + + /// Processes an instruction, ensuring that all identifier references resolve to the correct + /// declaration. This may involve renaming of declarations in the outer scopes. + void Process(core::ir::Instruction* inst) { + // Check resolving of operands + for (auto* operand : inst->Operands()) { + if (operand) { + // If the operand is a constant, then ensure that type name can be resolved. + if (auto* c = operand->As()) { + EnsureResolvable(c->Type()); + } + } + } + + Switch( + inst, // + [&](core::ir::Loop* loop) { + // Initializer's scope encompasses the body and continuing + scopes.Push(Scope{}); + TINT_DEFER(scopes.Pop()); + Process(loop->Initializer()); + { + // Body's scope encompasses the continuing + scopes.Push(Scope{}); + TINT_DEFER(scopes.Pop()); + Process(loop->Body()); + { + scopes.Push(Scope{}); + TINT_DEFER(scopes.Pop()); + Process(loop->Continuing()); + } + } + }, + [&](core::ir::ControlInstruction* ctrl) { + // Traverse into the control instruction's blocks + ctrl->ForeachBlock([&](core::ir::Block* block) { + scopes.Push(Scope{}); + TINT_DEFER(scopes.Pop()); + Process(block); + }); + }, + [&](core::ir::Var*) { + // Ensure the var's type is resolvable + EnsureResolvable(inst->Result()->Type()); + }, + [&](core::ir::Let*) { + // Ensure the let's type is resolvable + EnsureResolvable(inst->Result()->Type()); + }, + [&](core::ir::Construct*) { + // Ensure the type of a type constructor is resolvable + EnsureResolvable(inst->Result()->Type()); + }, + [&](core::ir::Convert*) { + // Ensure the type of a type constructor is resolvable + EnsureResolvable(inst->Result()->Type()); + }, + [&](core::ir::CoreBuiltinCall* call) { + // Ensure builtin of a builtin call is resolvable + auto name = tint::ToString(call->Func()); + EnsureResolvesToBuiltin(name); + }); + + // Register new operands and check their types can resolve + for (auto* result : inst->Results()) { + if (auto symbol = ir.NameOf(result); symbol.IsValid()) { + Declare(result, symbol); + } + } + } + + /// Ensures that the type @p type can be resolved given its identifier(s) + void EnsureResolvable(const core::type::Type* type) { + while (type) { + type = tint::Switch( + type, // + [&](const core::type::Scalar* s) { + EnsureResolvesToBuiltin(s->FriendlyName()); + return nullptr; + }, + [&](const core::type::Vector* v) { + EnsureResolvesToBuiltin("vec" + tint::ToString(v->Width())); + return v->Type(); + }, + [&](const core::type::Matrix* m) { + EnsureResolvesToBuiltin("mat" + tint::ToString(m->Columns()) + "x" + + tint::ToString(m->Rows())); + return m->Type(); + }, + [&](const core::type::Array* a) -> const core::type::Type* { + EnsureResolvesToBuiltin("array"); + return a->ElemType(); + }, + [&](const core::type::Pointer* p) { + EnsureResolvesToBuiltin(tint::ToString(p->Access())); + EnsureResolvesToBuiltin(tint::ToString(p->AddressSpace())); + return p->StoreType(); + }, + [&](const core::type::Struct* s) { + auto name = s->Name().NameView(); + if (IsBuiltinStruct(s)) { + EnsureResolvesToBuiltin(name); + } + return nullptr; + }); + } + } + + /// Ensures that the identifier @p identifier resolves to a builtin symbol. + void EnsureResolvesToBuiltin(std::string_view identifier) { + for (auto& scope : tint::Reverse(scopes)) { + if (auto decl = scope.Get(identifier)) { + // Operand is shadowed + scope.Remove(identifier); + Rename(*decl, identifier); + } + } + } + + /// Registers the declaration @p thing in the current scope with the name @p name + /// If there is an existing declaration with the given name in any parent scope then @p thing + /// will be renamed. + void Declare(CastableBase* thing, Symbol name) { + // Check if the declaration would shadow another declaration in the current scope or any + // parent scope, and rename it if so. + for (auto& scope : tint::Reverse(scopes)) { + if (auto decl = scope.Get(name.NameView())) { + if (*decl.value != thing) { + name = Rename(thing, name.NameView()); + break; + } + } + } + + // Add the declaration to the current scope, and make sure that it was either successfully + // added or has already been added. + auto add = scopes.Back().Add(name.NameView(), thing); + TINT_IR_ASSERT(ir, add || add.value == thing); + } + + /// Rename changes the name of @p thing with the old name of @p old_name + /// @returns the new name + Symbol Rename(CastableBase* thing, std::string_view old_name) { + Symbol new_name = ir.symbols.New(old_name); + Switch( + thing, // + [&](core::ir::Value* value) { ir.SetName(value, new_name); }, + [&](core::type::Struct* str) { str->SetName(new_name); }, // + TINT_ICE_ON_NO_MATCH); + return new_name; + } + + /// @return true if @p s is a builtin (non-user declared) structure. + bool IsBuiltinStruct(const core::type::Struct* s) { + return s->Name().NameView().starts_with("__"); + } +}; + +} // namespace + +Result RenameConflicts(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.RenameConflicts", kRenameConflictsCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.h new file mode 100644 index 000000000..c74a4bc3f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/rename_conflicts.h @@ -0,0 +1,68 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_RENAME_CONFLICTS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_RENAME_CONFLICTS_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kRenameConflictsCapabilities{ + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllow64BitIntegers, + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPointSizeBuiltin, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowAnyLetType, + core::ir::Capability::kAllowModuleScopeLets, + core::ir::Capability::kMslAllowEntryPointInterface, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// RenameConflicts is a transform that renames declarations which prevent identifiers from +/// resolving to the correct declaration, and those with identical identifiers declared in the same +/// scope or a parent scope. +/// @param module the module to transform +/// @returns success or failure +Result RenameConflicts(core::ir::Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_RENAME_CONFLICTS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.cc new file mode 100644 index 000000000..8e116e581 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.cc @@ -0,0 +1,212 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/resource_table.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/resource_type.h" + +namespace tint::core::ir::transform { +namespace { + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +/// PIMPL state for the transform. +struct State { + /// The configuration. + const ResourceTableConfig& config; + + /// The IR module. + core::ir::Module& ir; + + /// The helper + ResourceTableHelper* helper; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + Hashmap var_for_type; + core::ir::Var* sb = nullptr; + b.Append(ir.root_block, [&] { + var_for_type = helper->GenerateVars(b, config.resource_table_binding, + config.default_binding_type_order); + sb = InjectStorageBuffer(config.storage_buffer_binding); + }); + + std::unordered_map resource_type_to_idx; + size_t def_size = config.default_binding_type_order.size(); + for (size_t i = 0; i < def_size; ++i) { + auto res_ty = static_cast(config.default_binding_type_order[i]); + resource_type_to_idx.insert({res_ty, uint32_t(i)}); + } + + std::vector to_delete; + for (auto* inst : ir.Instructions()) { + auto* call = inst->As(); + if (call == nullptr) { + continue; + } + if (call->Func() != core::BuiltinFn::kGetResource && + call->Func() != core::BuiltinFn::kHasResource) { + continue; + } + + b.InsertBefore(call, [&] { + switch (call->Func()) { + case core::BuiltinFn::kHasResource: { + auto* binding_ty = call->ExplicitTemplateParams()[0]; + auto* idx = call->Args()[0]; + if (idx->Type()->IsSignedIntegerScalar()) { + idx = b.Convert(ty.u32(), idx)->Result(); + } + GenHasResource(call->DetachResult(), binding_ty, idx, sb); + break; + } + case core::BuiltinFn::kGetResource: { + auto* binding_ty = call->ExplicitTemplateParams()[0]; + auto* idx = call->Args()[0]; + if (idx->Type()->IsSignedIntegerScalar()) { + idx = b.Convert(ty.u32(), idx)->Result(); + } + GenGetResource(call->DetachResult(), binding_ty, idx, sb, var_for_type, + resource_type_to_idx); + break; + } + default: + TINT_IR_UNREACHABLE(ir); + } + to_delete.push_back(call); + }); + } + + for (auto* inst : to_delete) { + inst->Destroy(); + } + } + + // Note, assumes it's called inside a builder append block. + void GenHasResource(core::ir::InstructionResult* result, + const core::type::Type* type, + core::ir::Value* idx, + core::ir::Var* storage_buffer) { + auto* length = b.Access(ty.ptr(), storage_buffer, 0_u); + auto* len_check = b.LessThan(idx, b.Load(length)); + + auto* has_check = b.If(len_check); + has_check->SetResult(result); + + b.Append(has_check->True(), [&] { + auto* type_val = b.Access(ty.ptr(), storage_buffer, 1_u, idx); + + auto* v = b.Load(type_val); + auto* eq = b.Equal(v, u32(static_cast(core::type::TypeToResourceType(type)))); + b.ExitIf(has_check, eq); + }); + + b.Append(has_check->False(), [&] { b.ExitIf(has_check, b.Constant(false)); }); + } + + // Note, assumes it's called inside a builder append block. + void GenGetResource(core::ir::InstructionResult* result, + const core::type::Type* type, + core::ir::Value* idx, + core::ir::Var* storage_buffer, + const Hashmap& alias_for_type, + const std::unordered_map& resource_type_to_idx) { + auto* has_result = b.InstructionResult(ty.bool_()); + GenHasResource(has_result, type, idx, storage_buffer); + + auto* get_check = b.If(has_result); + auto* res = b.InstructionResult(ty.u32()); + get_check->SetResult(res); + + auto alias = alias_for_type.Get(type); + TINT_IR_ASSERT(ir, alias); + + b.Append(get_check->True(), [&] { b.ExitIf(get_check, idx); }); + + b.Append(get_check->False(), [&] { + auto res_type = core::type::TypeToResourceType(type); + auto idx_iter = resource_type_to_idx.find(res_type); + TINT_IR_ASSERT(ir, idx_iter != resource_type_to_idx.end()); + + auto* len_access = b.Access(ty.ptr(), storage_buffer, 0_u); + auto* num_elements = b.Load(len_access); + + auto* r = b.Add(u32(idx_iter->second), num_elements); + + b.ExitIf(get_check, r); + }); + + // TODO(439627523): Fix pointer access + auto* ptr_ty = ty.ptr(handle, type, read); + auto* access = b.Access(ptr_ty, (*alias)->Result(), res); + b.LoadWithResult(result, access); + } + + core::ir::Var* InjectStorageBuffer(const BindingPoint& bp) { + auto* str = ty.Struct(ir.symbols.New("tint_resource_table_buffer"), + Vector{ + {ir.symbols.New("array_length"), ty.u32()}, + {ir.symbols.New("bindings"), ty.array()}, + }); + + auto* sb_ty = ty.ptr(storage, str, read); + auto* sb = b.Var(sb_ty); + sb->SetBindingPoint(bp.group, bp.binding); + + return sb; + } +}; + +} // namespace + +ResourceTableHelper::~ResourceTableHelper() = default; + +Result ResourceTable(core::ir::Module& ir, + const ResourceTableConfig& config, + ResourceTableHelper* helper) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.ResourceTable")); + + State{config, ir, helper}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.h new file mode 100644 index 000000000..712ac8cc5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table.h @@ -0,0 +1,73 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_TABLE_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_TABLE_H_ + +#include + +#include "src/tint/api/common/resource_table_config.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::transform { + +// Backend specific override methods for resource table +class ResourceTableHelper { + public: + virtual ~ResourceTableHelper(); + + // Returns a map of types to the var which is used to access the memory of that type + virtual Hashmap GenerateVars( + core::ir::Builder& b, + const BindingPoint& bp, + const std::vector& types) const = 0; +}; + +/// This transform updates the provided IR to support resource_table restrictions/requirements. +/// +/// We re-write the `getResource` and `hasResource` calls to use the provided storage buffer to +/// validate the requested types. +/// +/// @param module the module to transform +/// @param config the transform configuration +/// @param helper the resource binding helper +/// @returns success or failure +Result ResourceTable(core::ir::Module& module, + const ResourceTableConfig& config, + ResourceTableHelper* helper); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_TABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.cc new file mode 100644 index 000000000..f27dd483b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.cc @@ -0,0 +1,78 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/resource_table_helper.h" + +#include +#include +#include + +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/resource_type.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::ir::transform { + +std::optional GenerateResourceTableConfig(Module& mod) { + ResourceTableConfig cfg{ + .resource_table_binding = BindingPoint{.group = 42, .binding = 41}, + .storage_buffer_binding = BindingPoint{.group = 42, .binding = 42}, + .default_binding_type_order = {}, + }; + + std::vector default_binding_type_order; + + for (auto* inst : mod.Instructions()) { + auto* call = inst->As(); + if (!call) { + continue; + } + + if (call->Func() != core::BuiltinFn::kGetResource && + call->Func() != core::BuiltinFn::kHasResource) { + continue; + } + auto exp = call->ExplicitTemplateParams(); + TINT_IR_ASSERT(mod, exp.Length() == 1); + + default_binding_type_order.push_back(type::TypeToResourceType(exp[0])); + } + // If we found any resource uses, then we can just return an empty config. + if (default_binding_type_order.empty()) { + return {}; + } + + // Sort so we get stable generated results + std::sort(default_binding_type_order.begin(), default_binding_type_order.end()); + cfg.default_binding_type_order = std::move(default_binding_type_order); + + return cfg; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.h new file mode 100644 index 000000000..7a7ab2bd9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/resource_table_helper.h @@ -0,0 +1,42 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_TABLE_HELPER_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_TABLE_HELPER_H_ + +#include + +#include "src/tint/api/common/resource_table_config.h" +#include "src/tint/lang/core/ir/module.h" + +namespace tint::core::ir::transform { + +std::optional GenerateResourceTableConfig(tint::core::ir::Module& mod); + +} + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_TABLE_HELPER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.cc new file mode 100644 index 000000000..7c331c061 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.cc @@ -0,0 +1,578 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/robustness.h" + +#include +#include + +#include "src/tint/lang/core/ir/analysis/integer_range_analysis.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/texture.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The robustness config. + const RobustnessConfig& config; + + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// For integer range analysis when needed + std::optional integer_range_analysis = {}; + + /// Process the module. + void Process() { + // Find the access instructions that may need to be clamped. + Vector accesses; + Vector vector_loads; + Vector vector_stores; + Vector subgroup_matrix_calls; + Vector texture_calls; + + if (config.use_integer_range_analysis) { + integer_range_analysis.emplace(&ir); + } + + for (auto* inst : ir.Instructions()) { + tint::Switch( + inst, // + [&](ir::Access* access) { + // Check if accesses into this object should be clamped. + if (access->Object()->Type()->Is()) { + if (ShouldClamp(access->Object())) { + accesses.Push(access); + } + } else { + accesses.Push(access); + } + }, + [&](ir::LoadVectorElement* lve) { + // Check if loads from this value should be clamped. + if (ShouldClamp(lve->From())) { + vector_loads.Push(lve); + } + }, + [&](ir::StoreVectorElement* sve) { + // Check if stores to this value should be clamped. + if (ShouldClamp(sve->To())) { + vector_stores.Push(sve); + } + }, + [&](ir::CoreBuiltinCall* call) { + // Check if this is a texture builtin that needs to be clamped. + if (config.clamp_texture) { + if (call->Func() == core::BuiltinFn::kTextureDimensions || + call->Func() == core::BuiltinFn::kTextureLoad) { + texture_calls.Push(call); + } + } + // Check if this is a subgroup matrix builtin that needs to be clamped. + if (call->Func() == core::BuiltinFn::kSubgroupMatrixLoad || + call->Func() == core::BuiltinFn::kSubgroupMatrixStore) { + subgroup_matrix_calls.Push(call); + } + }); + } + + // Clamp access indices. + for (auto* access : accesses) { + b.InsertBefore(access, [&] { // + ClampAccessIndices(access); + }); + } + + // Clamp load-vector-element instructions. + for (auto* lve : vector_loads) { + auto* vec = lve->From()->Type()->UnwrapPtr()->As(); + b.InsertBefore(lve, [&] { // + ClampOperand(lve, LoadVectorElement::kIndexOperandOffset, + b.Constant(u32(vec->Width() - 1u))); + }); + } + + // Clamp store-vector-element instructions. + for (auto* sve : vector_stores) { + auto* vec = sve->To()->Type()->UnwrapPtr()->As(); + b.InsertBefore(sve, [&] { // + ClampOperand(sve, StoreVectorElement::kIndexOperandOffset, + b.Constant(u32(vec->Width() - 1u))); + }); + } + + // Clamp indices and coordinates for texture builtins calls. + for (auto* call : texture_calls) { + b.InsertBefore(call, [&] { // + ClampTextureCallArgs(call); + }); + } + + // Predicate subgroup matrix loads and stores based on their offset and stride. + for (auto* call : subgroup_matrix_calls) { + b.InsertBefore(call, [&] { // + PredicateSubgroupMatrixCall(call); + }); + } + } + + /// Check if clamping should be applied to a particular value. + /// @param value the value to check. The value's type must be type::Pointer. + /// @returns true if pointer accesses in @p param should be clamped + bool ShouldClamp(Value* value) { + auto* ptr = value->Type()->As(); + TINT_IR_ASSERT(ir, ptr); + switch (ptr->AddressSpace()) { + case AddressSpace::kFunction: + case AddressSpace::kPrivate: + case AddressSpace::kWorkgroup: + return true; + case AddressSpace::kImmediate: + return config.clamp_immediate_data; + case AddressSpace::kStorage: + return config.clamp_storage && !IsRootVarIgnored(value); + case AddressSpace::kUniform: + return config.clamp_uniform && !IsRootVarIgnored(value); + case AddressSpace::kUndefined: + case AddressSpace::kPixelLocal: + case AddressSpace::kHandle: + case AddressSpace::kIn: + case AddressSpace::kOut: + return false; + } + return false; + } + + /// Convert a value to a u32 if needed. + /// @param value the value to convert + /// @returns the converted value, or @p value if it is already a u32 + ir::Value* CastToU32(ir::Value* value) { + if (value->Type()->IsUnsignedIntegerScalarOrVector()) { + return value; + } + + const type::Type* type = ty.u32(); + if (auto* vec = value->Type()->As()) { + type = ty.vec(type, vec->Width()); + } + return b.Convert(type, value)->Result(); + } + + /// Clamp operand @p op_idx of @p inst to ensure it is within @p limit. + /// @param inst the instruction + /// @param op_idx the index of the operand that should be clamped + /// @param limit the limit to clamp to + void ClampOperand(ir::Instruction* inst, size_t op_idx, ir::Value* limit) { + auto* idx = inst->Operands()[op_idx]; + auto* const_idx = idx->As(); + auto* const_limit = limit->As(); + + ir::Value* clamped_idx = nullptr; + if (const_idx && const_limit) { + TINT_IR_ASSERT(ir, const_idx->Value()->ValueAs() <= + const_limit->Value()->ValueAs()); + clamped_idx = b.Constant(u32(const_idx->Value()->ValueAs())); + } else if (IndexMayOutOfBound(idx, limit)) { + // Clamp it to the dynamic limit. + clamped_idx = b.Min(CastToU32(idx), limit)->Result(); + } + + if (clamped_idx != nullptr) { + // Replace the index operand with the clamped version. + inst->SetOperand(op_idx, clamped_idx); + } + } + + /// Check if operand @p idx may be less than 0 or greater than @p limit with integer range + /// analysis algorithm. + /// @param idx the index to check + /// @param limit the upper limit @idx to compare with. + /// @returns true when @idx may be out of bound, false otherwise + bool IndexMayOutOfBound(ir::Value* idx, ir::Value* limit) { + // Return true when integer range analysis is disabled. + if (!integer_range_analysis.has_value()) { + return true; + } + + // Return true when `limit` is not a constant value. + auto* const_limit = limit->As(); + if (!const_limit) { + return true; + } + + // Return true when we cannot get a valid range for `idx`. + const auto& integer_range = integer_range_analysis->GetInfo(idx); + if (!integer_range.IsValid()) { + return true; + } + + TINT_IR_ASSERT(ir, const_limit->Value()->Type()->Is()); + uint32_t const_limit_value = const_limit->Value()->ValueAs(); + + using SignedIntegerRange = ir::analysis::IntegerRangeInfo::SignedIntegerRange; + using UnsignedIntegerRange = ir::analysis::IntegerRangeInfo::UnsignedIntegerRange; + + // Return true when `idx` may be negative or the upper bound of `idx` is greater than + // `limit`. + if (std::holds_alternative(integer_range.range)) { + UnsignedIntegerRange range = std::get(integer_range.range); + return range.max_bound > static_cast(const_limit_value); + } else { + SignedIntegerRange range = std::get(integer_range.range); + if (range.min_bound < 0) { + return true; + } + return range.max_bound > static_cast(const_limit_value); + } + } + + /// Clamp the indices of an access instruction to ensure they are within the limits of the types + /// that they are indexing into. + /// @param access the access instruction + void ClampAccessIndices(ir::Access* access) { + auto* type = access->Object()->Type()->UnwrapPtr(); + auto indices = access->Indices(); + for (size_t i = 0; i < indices.Length(); i++) { + auto* idx = indices[i]; + auto* const_idx = idx->As(); + + // Determine the limit of the type being indexed into. + auto limit = tint::Switch( + type, // + [&](const type::Vector* vec) -> ir::Value* { + return b.Constant(u32(vec->Width() - 1u)); + }, + [&](const type::Matrix* mat) -> ir::Value* { + return b.Constant(u32(mat->Columns() - 1u)); + }, + [&](const type::Array* arr) -> ir::Value* { + if (arr->ConstantCount()) { + return b.Constant(u32(arr->ConstantCount().value() - 1u)); + } + TINT_IR_ASSERT(ir, arr->Count()->Is()); + + // Skip clamping runtime-sized array indices if requested. + if (config.disable_runtime_sized_array_index_clamping) { + return nullptr; + } + + auto* object = access->Object(); + if (i > 0) { + // Generate a pointer to the runtime-sized array if it isn't the base of + // this access instruction. + auto* base_ptr = object->Type()->As(); + TINT_IR_ASSERT(ir, base_ptr != nullptr); + TINT_IR_ASSERT(ir, i == 1); + auto* arr_ptr = ty.ptr(base_ptr->AddressSpace(), arr, base_ptr->Access()); + object = b.Access(arr_ptr, object, indices[0])->Result(); + } + + // Use the `arrayLength` builtin to get the limit of a runtime-sized array. + auto* length = b.Call(ty.u32(), core::BuiltinFn::kArrayLength, object); + return b.Subtract(length, b.Constant(1_u))->Result(); + }); + + // If there's a dynamic limit that needs enforced, clamp the index operand. + if (limit) { + ClampOperand(access, ir::Access::kIndicesOperandOffset + i, limit); + } + + // Get the type that this index produces. + type = const_idx ? type->Element(const_idx->Value()->ValueAs()) + : type->Elements().type; + } + } + + /// Clamp the indices and coordinates of a texture builtin call instruction to ensure they are + /// within the limits of the texture that they are accessing. + /// @param call the texture builtin call instruction + void ClampTextureCallArgs(ir::CoreBuiltinCall* call) { + const auto& args = call->Args(); + auto* texture = args[0]->Type()->As(); + + // Helper for clamping the level argument. + // Keep hold of the clamped value to use for clamping the coordinates. + Value* clamped_level = nullptr; + auto clamp_level = [&](uint32_t idx) { + auto* num_levels = b.Call(ty.u32(), core::BuiltinFn::kTextureNumLevels, args[0]); + auto* limit = b.Subtract(num_levels, 1_u); + clamped_level = b.Min(CastToU32(args[idx]), limit)->Result(); + call->SetOperand(CoreBuiltinCall::kArgsOperandOffset + idx, clamped_level); + }; + + // Helper for clamping the coordinates. + auto clamp_coords = [&](uint32_t idx) { + auto* arg_ty = args[idx]->Type(); + const type::Type* type = ty.MatchWidth(ty.u32(), arg_ty); + auto* one = b.MatchWidth(1_u, arg_ty); + auto* dims = clamped_level ? b.Call(type, core::BuiltinFn::kTextureDimensions, args[0], + clamped_level) + : b.Call(type, core::BuiltinFn::kTextureDimensions, args[0]); + auto* limit = b.Subtract(dims, one); + call->SetOperand(CoreBuiltinCall::kArgsOperandOffset + idx, + b.Min(CastToU32(args[idx]), limit)->Result()); + }; + + // Helper for clamping the array index. + auto clamp_array_index = [&](uint32_t idx) { + auto* num_layers = b.Call(ty.u32(), core::BuiltinFn::kTextureNumLayers, args[0]); + auto* limit = b.Subtract(num_layers, 1_u); + call->SetOperand(CoreBuiltinCall::kArgsOperandOffset + idx, + b.Min(CastToU32(args[idx]), limit)->Result()); + }; + + // Select which arguments to clamp based on the function overload. + switch (call->Func()) { + case core::BuiltinFn::kTextureDimensions: { + if (args.Length() > 1) { + clamp_level(1u); + } + break; + } + case core::BuiltinFn::kTextureLoad: { + uint32_t next_arg = 2u; + if (type::IsTextureArray(texture->Dim())) { + clamp_array_index(next_arg++); + } + if (texture->IsAnyOf()) { + clamp_level(next_arg++); + } + clamp_coords(1u); // Must run after clamp_level + break; + } + case core::BuiltinFn::kTextureStore: { + clamp_coords(1u); + if (type::IsTextureArray(texture->Dim())) { + clamp_array_index(2u); + } + break; + } + default: + break; + } + } + + /// Clamp the indices and coordinates of a texture builtin call instruction to ensure they are + /// within the limits of the texture that they are accessing. + /// @param call the texture builtin call instruction + void PredicateSubgroupMatrixCall(ir::CoreBuiltinCall* call) { + const auto& args = call->Args(); + + // Extract the arguments from the call. + auto* arr = args[0]; + auto* offset = args[1]; + Value* col_major = nullptr; + Value* stride = nullptr; + uint32_t stride_index = 0; + const type::SubgroupMatrix* matrix_ty = nullptr; + if (call->Func() == BuiltinFn::kSubgroupMatrixLoad) { + col_major = args[2]; + stride = args[3]; + stride_index = 3; + matrix_ty = call->Result()->Type()->As(); + } else if (call->Func() == BuiltinFn::kSubgroupMatrixStore) { + matrix_ty = args[2]->Type()->As(); + col_major = args[3]; + stride = args[4]; + stride_index = 4; + } else { + TINT_IR_UNREACHABLE(ir); + } + + // Determine the minimum valid stride, and the value that we will multiply the stride by to + // determine the number of elements in memory that will be accessed. + uint32_t min_stride = 0; + uint32_t major_dim = 0; + if (col_major->As()->Value()->ValueAs()) { + min_stride = matrix_ty->Rows(); + major_dim = matrix_ty->Columns(); + } else { + min_stride = matrix_ty->Columns(); + major_dim = matrix_ty->Rows(); + } + + // Increase the stride so that it is at least `min_stride` if necessary. + if (auto* const_stride = stride->As()) { + if (const_stride->Value()->ValueAs() < min_stride) { + stride = b.Constant(u32(min_stride)); + } + } else { + stride = b.Max(stride, u32(min_stride))->Result(); + } + call->SetArg(stride_index, stride); + + // If we are not predicating, then clamping the stride is all we need to do. + if (!config.predicate_subgroup_matrix) { + return; + } + + // Some matrix components types are packed together into a single array element. + // Take that into account here by scaling the array length to number of components. + uint32_t components_per_element = 0; + if (matrix_ty->Type()->IsAnyOf()) { + components_per_element = 4; + } else { + TINT_IR_ASSERT( + ir, (matrix_ty->Type()->IsAnyOf())); + components_per_element = 1; + } + + // Get the length of the array (in terms of matrix elements). + auto* arr_ty = arr->Type()->UnwrapPtr()->As(); + TINT_IR_ASSERT(ir, arr_ty); + Value* array_length = nullptr; + if (arr_ty->ConstantCount()) { + array_length = + b.Constant(u32(arr_ty->ConstantCount().value() * components_per_element)); + } else { + TINT_IR_ASSERT(ir, arr_ty->Count()->Is()); + array_length = b.Call(ty.u32(), core::BuiltinFn::kArrayLength, arr)->Result(0); + if (components_per_element > 1) { + array_length = b.Multiply(array_length, u32(components_per_element))->Result(); + } + } + + // If the array length, offset, and stride are all constants, then we can determine if the + // call is in bounds now and skip any predication if so. + if (array_length->Is() && stride->Is() && offset->Is()) { + uint32_t const_length = array_length->As()->Value()->ValueAs(); + uint32_t const_stride = stride->As()->Value()->ValueAs(); + uint32_t const_offset = offset->As()->Value()->ValueAs(); + uint32_t const_end = const_offset + (const_stride * (major_dim - 1)) + min_stride; + if (const_end <= const_length) { + return; + } + } + + // Predicate the builtin call depending on whether it is in bounds. + auto insertion_point = call->next; + call->Remove(); + b.InsertBefore(insertion_point, [&] { + // The beginning of the last row/column is at `offset + (major_dim-1)*stride`. + // We then add another `min_stride` elements to get to the end of the accessed memory. + auto* last_slice = b.Add(offset, b.Multiply(stride, u32(major_dim - 1))); + auto* end = b.Add(last_slice, u32(min_stride)); + auto* in_bounds = b.LessThanEqual(end, array_length); + if (call->Func() == BuiltinFn::kSubgroupMatrixLoad) { + // Declare a variable to hold the result of the load, or a zero-initialized matrix. + auto* result = b.Var(ty.ptr(matrix_ty)); + auto* load_result = b.InstructionResult(matrix_ty); + call->Result()->ReplaceAllUsesWith(load_result); + + auto* if_ = b.If(in_bounds); + b.Append(if_->True(), [&] { // + if_->True()->Append(call); + b.Store(result, call->Result()); + b.ExitIf(if_); + }); + b.LoadWithResult(load_result, result); + } else if (call->Func() == BuiltinFn::kSubgroupMatrixStore) { + auto* if_ = b.If(in_bounds); + b.Append(if_->True(), [&] { // + if_->True()->Append(call); + b.ExitIf(if_); + }); + } else { + TINT_IR_UNREACHABLE(ir); + } + }); + } + + // Returns the root Var for `value` by walking up the chain of instructions, + // or nullptr if none is found. + Var* RootVarFor(Value* value) { + Var* result = nullptr; + while (value) { + TINT_IR_ASSERT(ir, value->Alive()); + value = tint::Switch( + value, // + [&](InstructionResult* res) { + // value was emitted by an instruction + auto* inst = res->Instruction(); + return tint::Switch( + inst, + [&](Access* access) { // + return access->Object(); + }, + [&](Let* let) { // + return let->Value(); + }, + [&](Var* var) { + result = var; + return nullptr; // Done + }, + TINT_ICE_ON_NO_MATCH); + }, + [&](FunctionParam*) { + // Cannot follow function params to vars + return nullptr; + }, // + TINT_ICE_ON_NO_MATCH); + } + return result; + } + + // Returns true if the binding for `value`'s root variable is in config.bindings_ignored. + bool IsRootVarIgnored(Value* value) { + if (auto* var = RootVarFor(value)) { + if (auto bp = var->BindingPoint()) { + if (config.bindings_ignored.find(*bp) != config.bindings_ignored.end()) { + return true; // Ignore this variable + } + } + } + return false; + } +}; + +} // namespace + +Result Robustness(Module& ir, const RobustnessConfig& config) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.Robustness", kRobustnessCapabilities)); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.h new file mode 100644 index 000000000..8530428e5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/robustness.h @@ -0,0 +1,96 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_ROBUSTNESS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_ROBUSTNESS_H_ + +#include +#include "src/tint/lang/core/ir/validator.h" + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kRobustnessCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllow8BitIntegers, +}; + +/// Configuration options that control when to clamp accesses. +struct RobustnessConfig { + /// Should texture accesses be clamped? + bool clamp_texture = true; + + /// Should accesses to pointers with the 'immediate' address space be clamped? + bool clamp_immediate_data = true; + /// Should accesses to pointers with the 'storage' address space be clamped? + bool clamp_storage = true; + /// Should accesses to pointers with the 'uniform' address space be clamped? + bool clamp_uniform = true; + + /// Should subgroup matrix builtins be predicated? + /// Note that the stride parameter will still be clamped if predication is disabled. + bool predicate_subgroup_matrix = true; + + /// Bindings that should always be ignored. + std::unordered_set bindings_ignored; + + /// Should the transform skip index clamping on runtime-sized arrays? + bool disable_runtime_sized_array_index_clamping = false; + + /// Should the integer range analysis be used before doing index clamping? + bool use_integer_range_analysis = false; + + /// Reflection for this class + TINT_REFLECT(RobustnessConfig, + clamp_texture, + clamp_immediate_data, + clamp_storage, + clamp_uniform, + predicate_subgroup_matrix, + bindings_ignored, + disable_runtime_sized_array_index_clamping, + use_integer_range_analysis); +}; + +/// Robustness is a transform that prevents out-of-bounds memory accesses. +/// @param module the module to transform +/// @param config the robustness configuration +/// @returns success or failure +Result Robustness(Module& module, const RobustnessConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_ROBUSTNESS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.cc new file mode 100644 index 000000000..c73f5e778 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.cc @@ -0,0 +1,266 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/shader_io.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/utils/containers/vector.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The function that creates a backend state object. + std::function make_backend_state; + + /// The IR module. + Module& ir; + /// The IR builder. + Builder b{ir}; + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The entry point currently being processed. + Function* ep = nullptr; + + /// The backend state object for the current entry point. + std::unique_ptr backend{}; + + /// Process the module. + void Process() { + // Collect all structures before the transform has run, so that we can strip their shader IO + // attributes later. + Vector structures_to_strip; + for (auto* type : ir.Types()) { + if (auto* str = type->As()) { + structures_to_strip.Push(str); + } + } + + // Process the entry points. + // Take a copy of the function list since the transform adds new functions to the module. + auto functions = ir.functions; + for (auto& func : functions) { + // Only process entry points. + if (!func->IsEntryPoint()) { + continue; + } + + ProcessEntryPoint(func, make_backend_state(ir, func)); + } + + // Remove IO attributes from all structure members that had them prior to this transform. + for (auto* str : structures_to_strip) { + for (auto* member : str->Members()) { + // TODO(crbug.com/tint/745): Remove the const_cast. + const_cast(member)->ResetAttributes(); + } + } + } + + /// Process an entry point. + /// @param f the original entry point function + /// @param bs the backend state object + void ProcessEntryPoint(Function* f, std::unique_ptr bs) { + TINT_SCOPED_ASSIGNMENT(ep, f); + backend = std::move(bs); + TINT_DEFER(backend = nullptr); + + // Process the parameters and return value to prepare for building a wrapper function. + GatherInputs(); // Calls backend->AddInput() for each input + GatherOutput(); // Calls backend->AddOutput() for each output + + // Add an output for the vertex point size if needed. + std::optional vertex_point_size_index; + if (ep->IsVertex() && backend->NeedsVertexPointSize()) { + vertex_point_size_index = + backend->AddOutput(ir.symbols.New("vertex_point_size"), ty.f32(), + core::IOAttributes{ + .builtin = core::BuiltinValue::kPointSize, + }); + } + + auto new_params = backend->FinalizeInputs(); + auto* new_ret_ty = backend->FinalizeOutputs(); + + // Skip entry points with no new inputs or outputs. + if (!backend->HasInputs() && !backend->HasOutputs()) { + return; + } + + // Rename the old function and remove its pipeline stage, workgroup size and subgroup size, + // as we will be wrapping it with a new entry point. + auto name = ir.NameOf(ep).Name(); + auto stage = ep->Stage(); + auto wgsize = ep->WorkgroupSize(); + auto sgsize = ep->SubgroupSize(); + ir.SetName(ep, name + "_inner"); + ep->SetStage(Function::PipelineStage::kUndefined); + ep->ClearWorkgroupSize(); + ep->ClearSubgroupSize(); + + // Create the entry point wrapper function. + auto* wrapper_ep = b.Function(name, new_ret_ty); + wrapper_ep->SetParams(std::move(new_params)); + wrapper_ep->SetStage(stage); + if (wgsize) { + wrapper_ep->SetWorkgroupSize((*wgsize)[0], (*wgsize)[1], (*wgsize)[2]); + } + if (sgsize) { + wrapper_ep->SetSubgroupSize(*sgsize); + } + auto wrapper = b.Append(wrapper_ep->Block()); + + // Call the original function, passing it the inputs and capturing its return value. + auto inner_call_args = BuildInnerCallArgs(wrapper); + auto* inner_result = wrapper.Call(ep->ReturnType(), ep, std::move(inner_call_args)); + SetOutputs(wrapper, inner_result->Result()); + if (vertex_point_size_index) { + backend->SetOutput(wrapper, vertex_point_size_index.value(), b.Constant(1_f)); + } + + backend->SetBackendOutputs(wrapper, inner_result->Result()); + + // Return the new result. + wrapper.Return(wrapper_ep, backend->MakeReturnValue(wrapper)); + } + + /// Gather the shader inputs. + void GatherInputs() { + for (auto* param : ep->Params()) { + if (auto* str = param->Type()->As()) { + for (auto* member : str->Members()) { + auto name = str->Name().Name() + "_" + member->Name().Name(); + auto attributes = member->Attributes(); + if (attributes.interpolation && !ep->IsFragment()) { + // Strip interpolation on non-fragment inputs + attributes.interpolation = {}; + } + backend->AddInput(ir.symbols.Register(name), member->Type(), + std::move(attributes)); + } + } else { + // Pull out the IO attributes and remove them from the parameter. + auto attributes = param->Attributes(); + if (attributes.interpolation && !ep->IsFragment()) { + // Strip interpolation on non-fragment inputs + attributes.interpolation = {}; + } + param->ResetAttributes(); + + auto name = ir.NameOf(param); + backend->AddInput(name, param->Type(), std::move(attributes)); + } + } + } + + /// Gather the shader outputs. + void GatherOutput() { + if (ep->ReturnType()->Is()) { + return; + } + + if (auto* str = ep->ReturnType()->As()) { + for (auto* member : str->Members()) { + auto name = str->Name().Name() + "_" + member->Name().Name(); + auto attributes = member->Attributes(); + if (attributes.interpolation && !ep->IsVertex()) { + // Strip interpolation on non-vertex outputs + attributes.interpolation = {}; + } + backend->AddOutput(ir.symbols.Register(name), member->Type(), + std::move(attributes)); + } + } else { + // Pull out the IO attributes and remove them from the original function. + auto attributes = ep->ReturnAttributes(); + if (attributes.interpolation && !ep->IsVertex()) { + // Strip interpolation on non-vertex outputs + attributes.interpolation = {}; + } + ep->SetReturnAttributes({}); + + backend->AddOutput(ir.symbols.New(), ep->ReturnType(), std::move(attributes)); + } + } + + /// Build the argument list to call the original entry point function. + /// @param builder the IR builder for new instructions + /// @returns the argument list + Vector BuildInnerCallArgs(Builder& builder) { + uint32_t input_idx = 0; + Vector args; + for (auto* param : ep->Params()) { + if (auto* str = param->Type()->As()) { + Vector construct_args; + for (uint32_t i = 0; i < str->Members().Length(); i++) { + construct_args.Push(backend->GetInput(builder, input_idx++)); + } + args.Push(builder.Construct(param->Type(), construct_args)->Result()); + } else { + args.Push(backend->GetInput(builder, input_idx++)); + } + } + + return args; + } + + /// Propagate outputs from the inner function call to their final destination. + /// @param builder the IR builder for new instructions + /// @param inner_result the return value from calling the original entry point function + void SetOutputs(Builder& builder, Value* inner_result) { + if (auto* str = inner_result->Type()->As()) { + for (auto* member : str->Members()) { + Value* from = + builder.Access(member->Type(), inner_result, u32(member->Index()))->Result(); + backend->SetOutput(builder, member->Index(), from); + } + } else if (!inner_result->Type()->Is()) { + backend->SetOutput(builder, 0u, inner_result); + } + } +}; + +} // namespace + +void RunShaderIOBase(Module& module, std::function make_backend_state) { + State{make_backend_state, module}.Process(); +} + +ShaderIOBackendState::~ShaderIOBackendState() = default; + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.h new file mode 100644 index 000000000..ce273073e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/shader_io.h @@ -0,0 +1,135 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_SHADER_IO_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_SHADER_IO_H_ + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/type/manager.h" + +namespace tint::core::ir::transform { + +/// Abstract base class for the state needed to handle IO for a particular backend target. +struct ShaderIOBackendState { + /// Constructor + /// @param mod the IR module + /// @param f the entry point function + ShaderIOBackendState(Module& mod, Function* f) : ir(mod), func(f) {} + + /// Destructor + virtual ~ShaderIOBackendState(); + + /// Add an input. + /// @param name the name of the input + /// @param type the type of the input + /// @param attributes the IO attributes + /// @returns the index of the input + uint32_t AddInput(Symbol name, const core::type::Type* type, core::IOAttributes attributes) { + inputs.Push({name, type, std::move(attributes)}); + return uint32_t(inputs.Length() - 1); + } + + /// Add an output. + /// @param name the name of the output + /// @param type the type of the output + /// @param attributes the IO attributes + /// @returns the index of the output + uint32_t AddOutput(Symbol name, const core::type::Type* type, core::IOAttributes attributes) { + outputs.Push({name, type, std::move(attributes)}); + return uint32_t(outputs.Length() - 1); + } + + /// @returns true if inputs were added + bool HasInputs() const { return !inputs.IsEmpty(); } + + // @returns true if outputs were added + bool HasOutputs() const { return !outputs.IsEmpty(); } + + /// Finalize the shader inputs and create any state needed for the new entry point function. + /// @returns the list of function parameters for the new entry point + virtual Vector FinalizeInputs() = 0; + + /// Finalize the shader outputs and create state needed for the new entry point function. + /// @returns the return type for the new entry point + virtual const type::Type* FinalizeOutputs() = 0; + + /// Get the value of the input at index @p idx + /// @param builder the IR builder for new instructions + /// @param idx the index of the input + /// @returns the value of the input + virtual Value* GetInput(Builder& builder, uint32_t idx) = 0; + + /// Set the value of the output at index @p idx + /// @param builder the IR builder for new instructions + /// @param idx the index of the output + /// @param value the value to set + virtual void SetOutput(Builder& builder, uint32_t idx, Value* value) = 0; + + /// Sets the backend specific outputs + virtual void SetBackendOutputs(Builder&, Value*) {} + + /// Create the return value for the entry point, based on the output values that have been set. + /// @param builder the IR builder for new instructions + /// @returns the return value for the new entry point + virtual Value* MakeReturnValue([[maybe_unused]] Builder& builder) { return nullptr; } + + /// @returns true if a vertex point size builtin should be added + virtual bool NeedsVertexPointSize() const { return false; } + + protected: + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The original entry point function. + Function* func = nullptr; + + /// The list of shader inputs. + Vector inputs; + + /// The list of shader outputs. + Vector outputs; +}; + +/// The signature for a function that creates a backend state object. +using MakeBackendStateFunc = std::unique_ptr(Module&, Function*); + +/// @param module the module to transform +/// @param make_backend_state a function that creates a backend state object +void RunShaderIOBase(Module& module, std::function make_backend_state); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_SHADER_IO_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.cc new file mode 100644 index 000000000..9d24cfc30 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.cc @@ -0,0 +1,170 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/signed_integer_polyfill.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/core_binary.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::core::ir::transform { +namespace { + +/// PIMPL state for the transform. +struct State { + core::ir::Module& ir; + SignedIntegerPolyfillConfig cfg; + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + Vector signed_int_negate_worklist; + Vector signed_integer_arithmetic_worklist; + Vector signed_integer_leftshift_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* unary = inst->As()) { + auto op = unary->Op(); + auto* type = unary->Val()->Type(); + if (cfg.signed_negation && op == core::UnaryOp::kNegation && + type->IsSignedIntegerScalarOrVector()) { + signed_int_negate_worklist.Push(unary); + } + } else if (auto* binary = inst->As()) { + auto op = binary->Op(); + auto* lhs_type = binary->LHS()->Type(); + if (cfg.signed_arithmetic && + (op == core::BinaryOp::kAdd || op == core::BinaryOp::kMultiply || + op == core::BinaryOp::kSubtract) && + lhs_type->IsSignedIntegerScalarOrVector()) { + signed_integer_arithmetic_worklist.Push(binary); + } else if (cfg.signed_shiftleft && op == core::BinaryOp::kShiftLeft && + lhs_type->IsSignedIntegerScalarOrVector()) { + signed_integer_leftshift_worklist.Push(binary); + } + } + } + + // Replace the instructions that we found. + for (auto* signed_int_negate : signed_int_negate_worklist) { + SignedIntegerNegation(signed_int_negate); + } + for (auto* signed_arith : signed_integer_arithmetic_worklist) { + SignedIntegerArithmetic(signed_arith); + } + for (auto* signed_shift_left : signed_integer_leftshift_worklist) { + SignedIntegerShiftLeft(signed_shift_left); + } + } + + /// Replace a signed integer negation to avoid undefined behavior. + /// @param unary the unary instruction + void SignedIntegerNegation(core::ir::Unary* unary) { + // Replace `-x` with `bitcast((~bitcast(x)) + 1)`. + auto* signed_type = unary->Result()->Type(); + auto* unsigned_type = ty.MatchWidth(ty.u32(), signed_type); + b.InsertBefore(unary, [&] { + auto* unsigned_value = b.Bitcast(unsigned_type, unary->Val()); + auto* complement = b.Complement(unsigned_value); + auto* plus_one = b.Add(complement, b.MatchWidth(u32(1), unsigned_type)); + auto* result = b.Bitcast(signed_type, plus_one); + unary->Result()->ReplaceAllUsesWith(result->Result()); + }); + unary->Destroy(); + } + + /// Replace a signed integer arithmetic instruction. + /// @param binary the signed integer arithmetic instruction + void SignedIntegerArithmetic(core::ir::CoreBinary* binary) { + // MSL (HLSL/SPIR-V) does not define the behavior of signed integer overflow, so bitcast the + // operands to unsigned integers, perform the operation, and then bitcast the result back to + // a signed integer. + auto* signed_result_ty = binary->Result()->Type(); + auto* unsigned_result_ty = ty.MatchWidth(ty.u32(), signed_result_ty); + auto* unsigned_lhs_ty = ty.MatchWidth(ty.u32(), binary->LHS()->Type()); + auto* unsigned_rhs_ty = ty.MatchWidth(ty.u32(), binary->RHS()->Type()); + b.InsertBefore(binary, [&] { + auto* uint_lhs = b.Bitcast(unsigned_lhs_ty, binary->LHS()); + auto* uint_rhs = b.Bitcast(unsigned_rhs_ty, binary->RHS()); + auto* uint_binary = b.Binary(binary->Op(), unsigned_result_ty, uint_lhs, uint_rhs); + auto* bitcast = b.Bitcast(signed_result_ty, uint_binary); + binary->Result()->ReplaceAllUsesWith(bitcast->Result()); + }); + binary->Destroy(); + } + + /// Replace a signed integer shift left instruction. + /// @param binary the signed integer shift left instruction + void SignedIntegerShiftLeft(core::ir::CoreBinary* binary) { + // Left-shifting a negative integer is undefined behavior in C++14 and therefore potentially + // in MSL (HLSL/SPRI-V) too, so we bitcast to an unsigned integer, perform the shift, and + // bitcast the result back to a signed integer. + auto* signed_ty = binary->Result()->Type(); + auto* unsigned_ty = ty.MatchWidth(ty.u32(), signed_ty); + b.InsertBefore(binary, [&] { + auto* unsigned_lhs = b.Bitcast(unsigned_ty, binary->LHS()); + auto* unsigned_binary = + b.Binary(binary->Op(), unsigned_ty, unsigned_lhs, binary->RHS()); + auto* bitcast = b.Bitcast(signed_ty, unsigned_binary); + binary->Result()->ReplaceAllUsesWith(bitcast->Result()); + }); + binary->Destroy(); + } +}; + +} // namespace + +Result SignedIntegerPolyfill(core::ir::Module& ir, + const SignedIntegerPolyfillConfig& cfg) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "ir.SignedIntegerPolyfill", + core::ir::Capabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllow64BitIntegers, + core::ir::Capability::kAllowPointSizeBuiltin, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowAnyLetType, + core::ir::Capability::kMslAllowEntryPointInterface, + core::ir::Capability::kAllowModuleScopeLets, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + })); + + State{ir, cfg}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.h new file mode 100644 index 000000000..2cd5f0fb1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/signed_integer_polyfill.h @@ -0,0 +1,65 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_SIGNED_INTEGER_POLYFILL_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_SIGNED_INTEGER_POLYFILL_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::transform { + +/// The set of polyfills that should be applied. +struct SignedIntegerPolyfillConfig { + /// Should signed negation be polyfilled to avoid integer overflow? + bool signed_negation = false; + + /// Should signed arithmetic be polyfilled to avoid integer overflow? + bool signed_arithmetic = false; + + /// Should signed shiftleft be polyfilled to avoid integer overflow? + bool signed_shiftleft = false; + + /// Reflection for this class + TINT_REFLECT(SignedIntegerPolyfillConfig, signed_negation, signed_arithmetic, signed_shiftleft); +}; + +/// SignedIntegerPolyfill is a transform that replaces signed integer instructions with polyfills. +/// @param module the module to transform +/// @returns success or failure +Result SignedIntegerPolyfill(core::ir::Module& module, + const SignedIntegerPolyfillConfig& cfg); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_SIGNED_INTEGER_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.cc new file mode 100644 index 000000000..0236d5827 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.cc @@ -0,0 +1,114 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/single_entry_point.h" + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/referenced_functions.h" +#include "src/tint/lang/core/ir/referenced_module_decls.h" +#include "src/tint/lang/core/ir/validator.h" + +namespace tint::core::ir::transform { + +namespace { + +Result Run(ir::Module& ir, std::string_view entry_point_name) { + if (entry_point_name.empty()) { + return Failure{"no entry point provided"}; + } + + // Find the entry point. + ir::Function* entry_point = nullptr; + for (auto& func : ir.functions) { + if (!func->IsEntryPoint()) { + continue; + } + if (ir.NameOf(func).NameView() == entry_point_name) { + if (entry_point) { + TINT_IR_ICE(ir) << "multiple entry points named '" << entry_point_name + << "' were found"; + } + entry_point = func; + } + } + if (!entry_point) { + StringStream err; + err << "entry point '" << entry_point_name << "' not found"; + return Failure{err.str()}; + } + + // Remove unused functions. + ReferencedFunctions referenced_function_cache(ir); + auto& referenced_functions = referenced_function_cache.TransitiveReferences(entry_point); + for (uint32_t i = 0; i < ir.functions.Length();) { + auto func = ir.functions[i]; + if (func == entry_point || referenced_functions.Contains(func)) { + i++; + continue; + } + + func->Destroy(); + ir.functions.Erase(i); + } + + // Remove unused module-scope variables. + ReferencedModuleDecls referenced_var_cache(ir); + auto& referenced_vars = referenced_var_cache.TransitiveReferences(entry_point); + auto* inst = ir.root_block->Back(); + + // The instructions are removed in reverse order. This is in order to handle overrides which + // have an initializer. If the initializer is made of multiple instructions we need to delete + // the later one first to remove the usage from the earlier instruction. + while (inst) { + auto prev = inst->prev; + if (!referenced_vars.Contains(inst)) { + // There shouldn't be any remaining references to the variable. + if (inst->Result()->NumUsages() != 0) { + TINT_IR_ICE(ir) + << " Unexpected usages remain when applying single entry point IR for '" + << entry_point_name << "' "; + } + inst->Destroy(); + } + inst = prev; + } + + return Success; +} + +} // namespace + +Result SingleEntryPoint(Module& ir, std::string_view entry_point_name) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.SingleEntryPoint", kSingleEntryPointCapabilities)); + + return Run(ir, entry_point_name); +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.h new file mode 100644 index 000000000..3c1497767 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/single_entry_point.h @@ -0,0 +1,57 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_SINGLE_ENTRY_POINT_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_SINGLE_ENTRY_POINT_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kSingleEntryPointCapabilities{ + Capability::kAllowMultipleEntryPoints, + Capability::kAllowOverrides, + Capability::kAllow8BitIntegers, +}; + +/// Strip a module down to a single entry point, removing any unused functions and module-scope +/// declarations. +/// @param module the module to transform +/// @param entry_point_name the entry point name +/// @returns success or failure +Result SingleEntryPoint(Module& module, std::string_view entry_point_name); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_SINGLE_ENTRY_POINT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/std140.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/std140.cc new file mode 100644 index 000000000..552ac252f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/std140.cc @@ -0,0 +1,458 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/std140.h" + +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/function_param.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/memory_view.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/text/string_stream.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// Map from original type to a new type with decomposed matrices. + Hashmap rewritten_types{}; + + /// Map from struct member to its new index. + Hashmap member_index_map{}; + + /// Map from a type to a helper function that will convert its rewritten form back to it. + Hashmap convert_helpers{}; + + /// Process the module. + void Process() { + if (ir.root_block->IsEmpty()) { + return; + } + + // Find uniform buffers that contain matrices that need to be decomposed. + Vector, 8> buffer_variables; + for (auto inst : *ir.root_block) { + if (auto* var = inst->As()) { + auto* ptr = var->Result()->Type()->As(); + if (!ptr || ptr->AddressSpace() != core::AddressSpace::kUniform) { + continue; + } + auto* store_type = RewriteType(ptr->StoreType()); + if (store_type != ptr->StoreType()) { + buffer_variables.Push(std::make_pair(var, store_type)); + } + } + } + + // Now process the buffer variables, replacing them with new variables that have decomposed + // matrices and updating all usages of the variables. + for (auto var_and_ty : buffer_variables) { + // Create a new variable with the modified store type. + auto* old_var = var_and_ty.first; + auto* new_var = b.Var(ty.ptr(uniform, var_and_ty.second)); + const auto& bp = old_var->BindingPoint(); + new_var->SetBindingPoint(bp->group, bp->binding); + if (auto name = ir.NameOf(old_var)) { + ir.SetName(new_var->Result(), name); + } + + // Transform instructions that accessed the variable to use the decomposed var. + old_var->Result()->ForEachUseSorted( + [&](Usage use) { Replace(use.instruction, new_var->Result()); }); + + // Replace the original variable with the new variable. + old_var->ReplaceWith(new_var); + old_var->Destroy(); + } + } + + /// @param type the type to check + /// @returns the matrix if @p type is a matrix that needs to be decomposed + static const core::type::Matrix* NeedsDecomposing(const core::type::Type* type) { + if (auto* mat = type->As(); mat && NeedsDecomposing(mat)) { + return mat; + } + return nullptr; + } + + /// @param mat the matrix type to check + /// @returns true if @p mat needs to be decomposed + static bool NeedsDecomposing(const core::type::Matrix* mat) { + // Std140 layout rules only require us to do this transform for matrices whose column + // strides are not a multiple of 16 bytes. + // + // Due to a bug on Qualcomm devices, we also do this when the *size* of the column vector is + // not a multiple of 16 bytes (e.g. matCx3 types). See crbug.com/tint/2074. + return (mat->ColumnType()->Size() & 0xF) != 0; + } + + /// Rewrite a type if necessary, decomposing contained matrices. + /// @param type the type to rewrite + /// @returns the new type + const core::type::Type* RewriteType(const core::type::Type* type) { + return rewritten_types.GetOrAdd(type, [&] { + return tint::Switch( + type, + [&](const core::type::Array* arr) { + // Create a new array with element type potentially rewritten. + return ty.array(RewriteType(arr->ElemType()), arr->ConstantCount().value()); + }, + [&](const core::type::Struct* str) -> const core::type::Type* { + bool needs_rewrite = false; + uint32_t member_index = 0; + Vector new_members; + for (auto* member : str->Members()) { + if (auto* mat = NeedsDecomposing(member->Type())) { + // Decompose these matrices into a separate member for each column. + member_index_map.Add(member, member_index); + auto* col = mat->ColumnType(); + uint32_t offset = member->Offset(); + for (uint32_t i = 0; i < mat->Columns(); i++) { + StringStream ss; + ss << member->Name().Name() << "_col" << std::to_string(i); + new_members.Push(ty.Get( + sym.New(ss.str()), col, member_index, offset, col->Align(), + col->Size(), core::IOAttributes{})); + offset += col->Align(); + member_index++; + } + needs_rewrite = true; + } else { + // For all other types, recursively rewrite them as necessary. + auto* new_member_ty = RewriteType(member->Type()); + new_members.Push(ty.Get( + member->Name(), new_member_ty, member_index, member->Offset(), + member->Align(), member->Size(), core::IOAttributes{})); + member_index_map.Add(member, member_index); + member_index++; + if (new_member_ty != member->Type()) { + needs_rewrite = true; + } + } + } + + // If no members needed to be rewritten, just return the original struct. + if (!needs_rewrite) { + return str; + } + + // Create a new struct with the rewritten members. + auto* new_str = + ty.Get(sym.New(str->Name().Name() + "_std140"), + std::move(new_members), str->Size()); + for (auto flag : str->StructFlags()) { + new_str->SetStructFlag(flag); + } + return new_str; + }, + [&](const core::type::Matrix* mat) -> const core::type::Type* { + if (!NeedsDecomposing(mat)) { + return mat; + } + StringStream name; + name << "mat" << mat->Columns() << "x" << mat->Rows() << "_" + << mat->ColumnType()->Type()->FriendlyName() << "_std140"; + Vector members; + // Decompose these matrices into a separate member for each column. + auto* col = mat->ColumnType(); + uint32_t offset = 0; + for (uint32_t i = 0; i < mat->Columns(); i++) { + StringStream ss; + ss << "col" << std::to_string(i); + members.Push(ty.Get( + sym.New(ss.str()), col, i, offset, col->Align(), col->Size(), + core::IOAttributes{})); + offset += col->Align(); + } + + // Create a new struct with the rewritten members. + return ty.Get(sym.New(name.str()), std::move(members), + col->Align() * mat->Columns()); + }, + [&](Default) { + // This type cannot contain a matrix, so no changes needed. + return type; + }); + }); + } + + /// Reconstructs a column-decomposed matrix. + /// @param mat the matrix type + /// @param root the root value being accessed into + /// @param indices the access indices that index the first column of the matrix. + /// @returns the loaded matrix + Value* RebuildMatrix(const core::type::Matrix* mat, Value* root, VectorRef indices) { + // Recombine each column vector from the struct and reconstruct the original matrix type. + bool is_ptr = root->Type()->Is(); + auto first_column = indices.Back()->As()->Value()->ValueAs(); + Vector column_indices(std::move(indices)); + Vector args; + for (uint32_t i = 0; i < mat->Columns(); i++) { + column_indices.Back() = b.Constant(u32(first_column + i)); + if (is_ptr) { + auto* access = b.Access(ty.ptr(uniform, mat->ColumnType()), root, column_indices); + args.Push(b.Load(access)->Result()); + } else { + auto* access = b.Access(mat->ColumnType(), root, column_indices); + args.Push(access->Result()); + } + } + return b.Construct(mat, std::move(args))->Result(); + } + + /// Convert a value that may contain decomposed matrices to a value with the original type. + /// @param source the value to convert + /// @param orig_ty the original type to convert type + /// @returns the converted value + Value* Convert(Value* source, const core::type::Type* orig_ty) { + if (source->Type() == orig_ty) { + // The type was not rewritten, so just return the source value. + return source; + } + return tint::Switch( + orig_ty, // + [&](const core::type::Struct* str) -> Value* { + // Create a helper function that converts the struct to the original type. + auto* helper = convert_helpers.GetOrAdd(str, [&] { + auto* input_str = source->Type()->As(); + auto* func = b.Function("tint_convert_" + str->FriendlyName(), str); + auto* input = b.FunctionParam("tint_input", input_str); + func->SetParams({input}); + b.Append(func->Block(), [&] { + uint32_t index = 0; + Vector args; + for (auto* member : str->Members()) { + if (auto* mat = NeedsDecomposing(member->Type())) { + args.Push( + RebuildMatrix(mat, input, Vector{b.Constant(u32(index))})); + index += mat->Columns(); + } else { + // Extract and convert the member. + auto* type = input_str->Element(index); + auto* extract = b.Access(type, input, u32(index)); + args.Push(Convert(extract->Result(), member->Type())); + index++; + } + } + + // Construct and return the original struct. + b.Return(func, b.Construct(str, std::move(args))); + }); + return func; + }); + + // Call the helper function to convert the struct. + return b.Call(str, helper, source)->Result(); + }, + [&](const core::type::Array* arr) -> Value* { + // Create a loop that copies and converts each element of the array. + auto* el_ty = source->Type()->Elements().type; + auto* new_arr = b.Var(ty.ptr(function, arr)); + b.LoopRange(0_u, u32(arr->ConstantCount().value()), 1_u, [&](Value* idx) { + // Convert arr[idx] and store to new_arr[idx]; + auto* to = b.Access(ty.ptr(function, arr->ElemType()), new_arr, idx); + auto* from = b.Access(el_ty, source, idx)->Result(); + b.Store(to, Convert(from, arr->ElemType())); + }); + return b.Load(new_arr)->Result(); + }, + [&](const core::type::Matrix* mat) -> Value* { + if (!NeedsDecomposing(mat)) { + return source; + } + return RebuildMatrix(mat, source, Vector{b.Constant(u32(0))}); + }, + [&](Default) { return source; }); + } + + /// Replace a use of a value that contains or was derived from a decomposed matrix. + /// @param inst the instruction to replace + /// @param replacement the replacement value + void Replace(Instruction* inst, Value* replacement) { + b.InsertBefore(inst, [&] { + tint::Switch( + inst, // + [&](Access* access) { + auto* object_ty = access->Object()->Type()->As(); + if (!object_ty || object_ty->AddressSpace() != core::AddressSpace::kUniform) { + // Access to non-uniform memory views does not require transformation. + return; + } + + if (!replacement->Type()->Is()) { + // The replacement is a value, in which case the decomposed matrix has + // already been reconstructed. In this situation the access only needs its + // return type updating, and downstream instructions need updating. + access->SetOperand(Access::kObjectOperandOffset, replacement); + auto* result = access->Result(); + result->SetType(result->Type()->UnwrapPtrOrRef()); + result->ForEachUseSorted( + [&](Usage use) { Replace(use.instruction, result); }); + return; + } + + // Modify the access indices to take decomposed matrices into account. + auto* current_type = object_ty->StoreType(); + Vector indices; + + if (NeedsDecomposing(current_type)) { + // Decomposed matrices are indexed using their first column vector + indices.Push(b.Constant(0_u)); + } + + for (size_t i = 0, n = access->Indices().Length(); i < n; i++) { + auto* idx = access->Indices()[i]; + + if (auto* mat = NeedsDecomposing(current_type)) { + // Access chain passes through decomposed matrix. + if (auto* const_idx = idx->As()) { + // Column vector index is a constant. + // Instead of loading the whole matrix, fold the access of the + // matrix and the constant column index into an single access of + // column vector member. + auto* base_idx = indices.Back()->As(); + indices.Back() = + b.Constant(u32(base_idx->Value()->ValueAs() + + const_idx->Value()->ValueAs())); + current_type = mat->ColumnType(); + i++; // We've already consumed the column access + } else { + // Column vector index is dynamic. + // Reconstruct the whole matrix and index that. + replacement = RebuildMatrix(mat, replacement, std::move(indices)); + indices.Clear(); + indices.Push(idx); + current_type = mat->ColumnType(); + } + } else if (auto* str = current_type->As()) { + // Remap member index + uint32_t old_index = idx->As()->Value()->ValueAs(); + uint32_t new_index = *member_index_map.Get(str->Members()[old_index]); + current_type = str->Element(old_index); + indices.Push(b.Constant(u32(new_index))); + } else { + indices.Push(idx); + current_type = current_type->Elements().type; + if (NeedsDecomposing(current_type)) { + // Decomposed matrices are indexed using their first column vector + indices.Push(b.Constant(0_u)); + } + } + } + + if (auto* mat = NeedsDecomposing(current_type)) { + replacement = RebuildMatrix(mat, replacement, std::move(indices)); + indices.Clear(); + } + + if (!indices.IsEmpty()) { + // Emit the access with the modified indices. + if (replacement->Type()->Is()) { + current_type = ty.ptr(uniform, RewriteType(current_type)); + } + auto* new_access = b.Access(current_type, replacement, std::move(indices)); + replacement = new_access->Result(); + } + + // Replace every instruction that uses the original access instruction. + access->Result()->ForEachUseSorted( + [&](Usage use) { Replace(use.instruction, replacement); }); + access->Destroy(); + }, + [&](Load* load) { + if (!replacement->Type()->Is()) { + // We have already loaded to a value type, so this load just folds away. + load->Result()->ReplaceAllUsesWith(replacement); + } else { + // Load the decomposed value and then convert it to the original type. + auto* decomposed = b.Load(replacement); + auto* converted = Convert(decomposed->Result(), load->Result()->Type()); + load->Result()->ReplaceAllUsesWith(converted); + } + load->Destroy(); + }, + [&](LoadVectorElement* load) { + if (!replacement->Type()->Is()) { + // We have loaded a decomposed matrix and reconstructed it, so this is now + // extracting from a value type. + b.AccessWithResult(load->DetachResult(), replacement, load->Index()); + load->Destroy(); + } else { + // There was no decomposed matrix on the path to this instruction so just + // update the source operand. + load->SetOperand(LoadVectorElement::kFromOperandOffset, replacement); + } + }, + [&](Let* let) { + // Let instructions just fold away. + let->Result()->ForEachUseSorted( + [&](Usage use) { Replace(use.instruction, replacement); }); + let->Destroy(); + }); + }); + } +}; + +} // namespace + +Result Std140(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.Std140", kStd140Capabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/std140.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/std140.h new file mode 100644 index 000000000..40636788d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/std140.h @@ -0,0 +1,61 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_STD140_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_STD140_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kStd140Capabilities{ + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// Std140 is a transform that rewrites matrix types in the uniform address space to conform to +/// GLSL's std140 layout rules. +/// @note requires the DirectVariableAccess transform to have been run first to remove uniform +/// pointer parameters. +/// @param module the module to transform +/// @returns success or failure +Result Std140(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_STD140_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.cc new file mode 100644 index 000000000..a6464bb05 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.cc @@ -0,0 +1,386 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/substitute_overrides.h" + +#include +#include +#include + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/const_param_validator.h" +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/evaluator.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/terminator.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/type/array_count.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/utils/numeric.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The configuration + const SubstituteOverridesConfig& cfg; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + diag::Result Process() { + Vector to_remove; + Vector values_to_propagate; + Vector vars_with_value_array_count; + Vector override_complex_init; + + // Note, we don't `Destroy` the overrides when we substitute them. We need them to stay + // alive because the `workgroup_size` and `array` usages aren't in the `Usages` list so + // haven't been replaced yet. + for (auto* inst : *ir.root_block) { + if (auto* var = inst->As()) { + if (auto* ary = var->Result()->Type()->UnwrapPtr()->As()) { + if (ary->Count()->Is()) { + vars_with_value_array_count.Push(var); + } + } + } else { + // Gather all the non-var instructions which we'll remove + to_remove.Push(inst); + } + + auto* override = inst->As(); + if (!override) { + continue; + } + + // Check if the user provided an override for the given ID. In the case of Dawn, all + // overrides end up having an ID, so they will all be able to be queried here. If the + // code came through the SPIR-V reader, and overrides are being applied on the top of + // that IR tree, an OverrideId may not be set, but that also means in SPIR-V the + // override could not be set anyway, so it can't have an override value applied. + if (override->OverrideId().has_value()) { + auto iter = cfg.map.find(override->OverrideId().value()); + if (iter != cfg.map.end()) { + bool substitution_representation_valid = tint::Switch( + override->Result()->Type(), // + [&](const core::type::Bool*) { return true; }, + [&](const core::type::I32*) { + return dawn::IsDoubleValueRepresentable(iter->second); + }, + [&](const core::type::U32*) { + return dawn::IsDoubleValueRepresentable(iter->second); + }, + [&](const core::type::F32*) { + return dawn::IsDoubleValueRepresentable(iter->second); + }, + [&](const core::type::F16*) { + return dawn::IsDoubleValueRepresentableAsF16(iter->second); + }, + TINT_ICE_ON_NO_MATCH); + + if (!substitution_representation_valid) { + diag::Diagnostic error{}; + error.severity = diag::Severity::Error; + error.source = ir.SourceOf(override); + error << "Pipeline overridable constant " << iter->first.value + << " with value (" << iter->second + << ") is not representable in type (" + << override->Result()->Type()->FriendlyName() << ")"; + return diag::Failure(error); + } + + auto* replacement = CreateConstant(override->Result()->Type(), iter->second); + override->SetInitializer(replacement); + } + } + + if (override->Initializer() == nullptr) { + diag::Diagnostic error{}; + error.severity = diag::Severity::Error; + error.source = ir.SourceOf(override); + error << "Initializer not provided for override, and override not overridden."; + return diag::Failure(error); + } + + if (auto* replacement = override->Initializer()->As()) { + override->Result()->ReplaceAllUsesWith(replacement); + values_to_propagate.Push(replacement); + } else { + // This override might depend on ConstExperIf block compile time evaluation. + override_complex_init.Push(override); + } + } + + // When `overrides` are evaluated, only the `override` is checked, and any instructions back + // up the block. This means, if we have a `constexpr-if` we may hit an override in the part + // of the `constexpr-if` which should be ignored (because we had a `false && a_override / 0` + // or something similar). If we evaluate `a_override` before we evaluate the `constexpr-if` + // that represents the `&&` then we'll produce an incorrect compile error. Instead evaluate + // the `constexpr-if` constructs early to remove them all and remove any blocks which should + // not be evaluated. + TINT_CHECK_RESULT(EvalConstExprIf()); + + // Workgroup size and subgroup size MUST be evaluated prior to 'propagate' because workgroup + // size and subgroup size parameters are not proper usages. + for (auto func : ir.functions) { + if (!func->IsCompute()) { + continue; + } + + auto wgs = func->WorkgroupSize(); + TINT_IR_ASSERT(ir, wgs.has_value()); + + std::array new_wg{}; + for (size_t i = 0; i < 3; ++i) { + TINT_CHECK_RESULT_UNWRAP(new_value, CalculateOverride(wgs.value()[i])); + new_wg[i] = new_value; + } + func->SetWorkgroupSize(new_wg); + + auto sgs = func->SubgroupSize(); + if (sgs.has_value()) { + TINT_CHECK_RESULT_UNWRAP(new_sg, CalculateOverride(sgs.value())); + func->SetSubgroupSize(new_sg); + } + } + + // Replace array types MUST be evaluate prior to 'propagate' because array count values are + // not proper usages. + for (auto var : vars_with_value_array_count) { + auto* old_ptr = var->Result()->Type()->As(); + TINT_IR_ASSERT(ir, old_ptr); + + auto* old_ty = old_ptr->UnwrapPtr()->As(); + auto* cnt = old_ty->Count()->As(); + TINT_IR_ASSERT(ir, cnt); + + TINT_CHECK_RESULT_UNWRAP(new_value, CalculateOverride(cnt->value)); + + // Pipeline creation error for zero or negative sized array. This is important as we do + // not check constant evaluation access against zero size. + int64_t cnt_size_check = new_value->Value()->ValueAs(); + if (cnt_size_check < 1) { + diag::Diagnostic error{}; + error.severity = diag::Severity::Error; + error.source = ir.SourceOf(cnt->value); + error << "array count (" << cnt_size_check << ") must be greater than 0"; + return diag::Failure(error); + } + + uint32_t num_elements = new_value->Value()->ValueAs(); + auto* new_cnt = ty.Get(num_elements); + auto* new_ty = ty.Get(old_ty->ElemType(), new_cnt, + num_elements * old_ty->ImplicitStride()); + + auto* new_ptr = ty.ptr(old_ptr->AddressSpace(), new_ty, old_ptr->Access()); + var->Result()->SetType(new_ptr); + + // The `Var` type needs to propagate to certain usages. + Vector to_replace; + to_replace.Push(var); + + while (!to_replace.IsEmpty()) { + auto* inst = to_replace.Pop(); + for (auto usage : inst->Result()->UsagesUnsorted()) { + // This is an edge case where we have to specifically verify bounds access for + // these new arrays for all usages. + if (NeedsEval(usage->instruction)) { + TINT_CHECK_RESULT(eval::Eval(b, usage->instruction)); + } + if (!usage->instruction->Is()) { + continue; + } + + usage->instruction->Result()->SetType(new_ptr); + to_replace.Push(usage->instruction); + } + } + } + + for (auto* override : override_complex_init) { + TINT_CHECK_RESULT_UNWRAP(res_const, CalculateOverride(override->Result())); + override->Result()->ReplaceAllUsesWith(res_const); + values_to_propagate.Push(res_const); + } + + // Propagate any replaced override instructions up their instruction chains + TINT_CHECK_RESULT(Propagate(values_to_propagate)); + + // Remove any non-var instruction in the root block + for (auto* inst : to_remove) { + // Some instructions can be destroyed by 'Propagate' or 'EvalConstExprIf'. This is + // normal. + if (inst->Alive()) { + inst->Destroy(); + } + } + + return Success; + } + + diag::Result EvalConstExprIf() { + Vector ordered_constexpr_if; + core::ir::Traverse(ir.root_block, [&ordered_constexpr_if](ConstExprIf* inst) { + ordered_constexpr_if.Push(inst); + }); + + for (auto func : ir.functions) { + core::ir::Traverse(func->Block(), [&ordered_constexpr_if](ConstExprIf* inst) { + ordered_constexpr_if.Push(inst); + }); + } + + for (auto* constexpr_if : ordered_constexpr_if) { + // This very code can end up destroying other ConstExprIf instructions. + if (!constexpr_if->Alive()) { + continue; + } + + TINT_CHECK_RESULT_UNWRAP(res, eval::Eval(b, constexpr_if->Condition())); + TINT_IR_ASSERT(ir, res); + + auto* inline_block = + res->Value()->ValueAs() ? constexpr_if->True() : constexpr_if->False(); + TINT_IR_ASSERT(ir, inline_block->Terminator()); + for (;;) { + auto block_inst = *inline_block->begin(); + if (block_inst->Is()) { + break; + } + block_inst->Remove(); + block_inst->InsertBefore(constexpr_if); + } + // There will only be one arg since the return (of ConstExprIf) is a single + // boolean. + constexpr_if->Result()->ReplaceAllUsesWith(inline_block->Terminator()->Args()[0]); + constexpr_if->Destroy(); + } + + return Success; + } + + diag::Result CalculateOverride(core::ir::Value* val) { + TINT_CHECK_RESULT_UNWRAP(r, eval::Eval(b, val)); + // Must be able to evaluate the constant. + TINT_IR_ASSERT(ir, r); + return r; + } + + diag::Result Propagate(Vector& values_to_propagate) { + while (!values_to_propagate.IsEmpty()) { + auto* value = values_to_propagate.Pop(); + for (auto usage : value->UsagesSorted()) { + // If the instruction has no results, then it was destroyed already and we can just + // skip it. + if (!usage.instruction->Result(0)) { + continue; + } + + if (!NeedsEval(usage.instruction)) { + continue; + } + + // The replacement can be a `nullptr` if we try to evaluate something like a `dpdx` + // builtin which doesn't have a `@const` annotation. + TINT_CHECK_RESULT_UNWRAP(replacement, eval::Eval(b, usage.instruction)); + if (!replacement) { + continue; + } + + usage.instruction->Result()->ReplaceAllUsesWith(replacement); + values_to_propagate.Push(replacement); + usage.instruction->Destroy(); + } + } + + return Success; + } + + bool NeedsEval(core::ir::Instruction* inst) { + return tint::Switch( // + inst, // + [&](core::ir::Bitcast*) { return true; }, // + [&](core::ir::Access*) { return true; }, // + [&](core::ir::Construct*) { return true; }, // + [&](core::ir::Convert*) { return true; }, // + [&](core::ir::CoreBinary*) { return true; }, // + [&](core::ir::CoreBuiltinCall*) { return true; }, // + [&](core::ir::CoreUnary*) { return true; }, // + [&](core::ir::Swizzle*) { return true; }, // + [&](core::ir::Override*) { return true; }, // + [&](Default) { return false; }); + } + + Constant* CreateConstant(const core::type::Type* type, double val) { + return tint::Switch( + type, + [&](const core::type::Bool*) { return b.Constant(!std::equal_to()(val, 0.0)); }, + [&](const core::type::I32*) { return b.Constant(i32(val)); }, + [&](const core::type::U32*) { return b.Constant(u32(val)); }, + [&](const core::type::F32*) { return b.Constant(f32(val)); }, + [&](const core::type::F16*) { return b.Constant(f16(val)); }, // + TINT_ICE_ON_NO_MATCH); + } +}; + +} // namespace + +Result SubstituteOverrides(Module& ir, const SubstituteOverridesConfig& cfg) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.SubstituteOverrides", kSubstituteOverridesCapabilities)); + { + auto result = State{ir, cfg}.Process(); + if (result != Success) { + return Failure{result.Failure().reason.Str()}; + } + } + + // TODO(crbug.com/382300469): This function should take in a constant module but it does not due + // to missing constant functions. + return tint::core::ir::ValidateConstParam(ir); +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.h new file mode 100644 index 000000000..dc13e6103 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/substitute_overrides.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_SUBSTITUTE_OVERRIDES_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_SUBSTITUTE_OVERRIDES_H_ + +#include + +#include "src/tint/api/common/substitute_overrides_config.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kSubstituteOverridesCapabilities{ + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// Substitute overrides to their constant values. +/// @param module the module to transform +/// @returns success or failure +Result SubstituteOverrides(Module& module, const SubstituteOverridesConfig& cfg); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_SUBSTITUTE_OVERRIDES_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.cc new file mode 100644 index 000000000..bfa3881a3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.cc @@ -0,0 +1,240 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/value_to_let.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The configuration + const ValueToLetConfig& cfg; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + // A set of possibly-inlinable values returned by a instructions that has not yet been + // marked-for or ruled-out-for inlining. + Hashset pending_resolution{}; + // The accesses of the values in pending_resolution. + Instruction::Access pending_access = Instruction::Access::kLoad; + + /// Process the module. + void Process() { + // Process each block. + for (auto* block : ir.blocks.Objects()) { + Process(block); + } + } + + private: + void Process(ir::Block* block) { + // Replace all pointer lets with the value they point too. + ReplacePointerLetsWithValues(); + + for (ir::Instruction* inst = block->Front(); inst; inst = inst->next) { + // This transform assumes that all multi-result instructions have been replaced + TINT_IR_ASSERT(ir, inst->Results().Length() < 2); + + // The memory accesses of this instruction + auto accesses = inst->GetSideEffects(); + + // A pointer access chain will be inlined by the backends. For backends which don't + // provide pointer lets we need to force any arguments into lets such the occur in the + // correct order. Without this it's possible to shift function calls around if they're + // only used in the access. + // + // e.g. + // ``` + // var arr : array; + // let p = val[f() + 1]; + // g(); + // let x = p; + // ``` + // + // If the access at `p` is inlined to `x` then the function `f()` will be called after + // `g()` instead of before as is required. So, we pessimize and for all access operands + // to lets to maintain ordering. + // + // This flush only needs to take place if the access chain contains operands which are + // pending resolution. If nothing is pending, we don't need to flush at all. + if (cfg.replace_pointer_lets && IsPointerAccess(inst)) { + for (auto* operand : inst->Operands()) { + if (auto* result = operand->As()) { + if (pending_resolution.Contains(result)) { + PutPendingInLets(); + break; + } + } + } + } + + for (auto* operand : inst->Operands()) { + // If the operand is in pending_resolution, then we know it has a single use and + // because it hasn't been removed with put_pending_in_lets(), we know its safe to + // inline without breaking access ordering. By inlining the operand, we are pulling + // the operand's instruction into the same statement as this instruction, so this + // instruction adopts the access of the operand. + if (auto* result = As(operand)) { + if (pending_resolution.Remove(result)) { + // Var and Let are always statements, and so can never be inlined. As such, + // they do not need to propagate the pending resolution through them. + if (!inst->IsAnyOf()) { + accesses.Add(pending_access); + } + } + } + } + + if (accesses.Contains( + Instruction::Access::kStore)) { // Note: Also handles load + store + PutPendingInLets(); + pending_access = Instruction::Access::kStore; + inst = MaybePutInLet(inst, accesses); + } else if (accesses.Contains(Instruction::Access::kLoad)) { + if (pending_access != Instruction::Access::kLoad) { + PutPendingInLets(); + pending_access = Instruction::Access::kLoad; + } + inst = MaybePutInLet(inst, accesses); + } + } + } + + void PutPendingInLets() { + for (auto& pending : pending_resolution) { + PutInLet(pending); + } + pending_resolution.Clear(); + } + + core::ir::Instruction* MaybePutInLet(core::ir::Instruction* inst, + Instruction::Accesses& accesses) { + if (auto* result = inst->Result(0)) { + auto& usages = result->UsagesUnsorted(); + switch (result->NumUsages()) { + case 0: // No usage + if (accesses.Contains(Instruction::Access::kStore)) { + // This instruction needs to be emitted but has no uses, so we need to + // make sure that it will be used in a statement. Function call + // instructions with no uses will be emitted as call statements, so we + // just need to put other instructions in `let`s to force them to be + // emitted. + if (!inst->IsAnyOf() || + inst->IsAnyOf()) { + inst = PutInLet(result); + } + } + break; + case 1: { // Single usage + auto usage = (*usages.begin())->instruction; + if (usage->Block() == inst->Block()) { + // Usage in same block. Assign to pending_resolution, as we don't + // know whether its safe to inline yet. + pending_resolution.Add(result); + } else { + // Usage from another block. Cannot inline. + inst = PutInLet(result); + } + break; + } + default: // Value has multiple usages. Cannot inline. + inst = PutInLet(result); + break; + } + } + return inst; + } + + bool IsPointerAccess(core::ir::Instruction* inst) { + return inst->Is() && inst->Result()->Type()->Is(); + } + + /// PutInLet places the value into a new 'let' instruction, immediately after the value's + /// instruction + /// @param value the value to place into the 'let' + /// @return the created 'let' instruction. + ir::Instruction* PutInLet(ir::InstructionResult* value) { + auto* inst = value->Instruction(); + + if (cfg.replace_pointer_lets && IsPointerAccess(inst)) { + return inst; + } + + auto* let = b.Let(value->Type()); + value->ReplaceAllUsesWith(let->Result()); + let->SetValue(value); + let->InsertAfter(inst); + if (auto name = b.ir.NameOf(value); name.IsValid()) { + b.ir.SetName(let->Result(), name); + b.ir.ClearName(value); + } + return let; + } + + void ReplacePointerLetsWithValues() { + if (!cfg.replace_pointer_lets) { + return; + } + + for (auto* inst : ir.Instructions()) { + if (auto* l = inst->As()) { + if (!l->Result()->Type()->Is()) { + continue; + } + l->Result()->ReplaceAllUsesWith(l->Value()); + l->Destroy(); + } + } + } +}; + +} // namespace + +Result ValueToLet(Module& ir, const ValueToLetConfig& cfg) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.ValueToLet", kValueToLetCapabilities)); + + State{ir, cfg}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.h new file mode 100644 index 000000000..f815e06a2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/value_to_let.h @@ -0,0 +1,83 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_VALUE_TO_LET_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_VALUE_TO_LET_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kValueToLetCapabilities{ + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllow64BitIntegers, + + core::ir::Capability::kAllowPointSizeBuiltin, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowAnyLetType, + core::ir::Capability::kMslAllowEntryPointInterface, + core::ir::Capability::kAllowModuleScopeLets, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// Configuration for ValueToLet transform. +struct ValueToLetConfig { + /// Replace pointer lets with their value + bool replace_pointer_lets = false; + + /// Reflection for this class + TINT_REFLECT(ValueToLetConfig, replace_pointer_lets); +}; + +/// ValueToLet is a transform that moves "non-inlinable" instruction values to let instructions. +/// An expression is considered "non-inlinable" if any of the following are true: +/// * The value has multiple uses. +/// * The value's instruction is a load that when inlined would cross a store instruction. +/// * The value's instruction is a store instruction that when inlined would cross a load or store +/// instruction. +/// * The value is used in a block different to the value's instruction. +/// +/// @param module the module to transform +/// @param cfg the configuration +/// @returns error on failure +Result ValueToLet(Module& module, const ValueToLetConfig& cfg); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_VALUE_TO_LET_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc new file mode 100644 index 000000000..32c6f19c6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc @@ -0,0 +1,105 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + // Find and replace matrix constructors that take scalar operands. + for (auto inst : ir.Instructions()) { + if (auto* construct = inst->As()) { + if (construct->Result()->Type()->As()) { + if (construct->Operands().Length() > 0 && + construct->Operands()[0]->Type()->Is()) { + b.InsertBefore(construct, [&] { // + ReplaceConstructor(construct); + }); + } + } + } + } + } + + /// Replace a matrix construct instruction. + /// @param construct the instruction to replace + void ReplaceConstructor(Construct* construct) { + auto* mat = construct->Result()->Type()->As(); + auto* col = mat->ColumnType(); + const auto& scalars = construct->Operands(); + + // Collect consecutive scalars into column vectors. + Vector columns; + for (uint32_t c = 0; c < mat->Columns(); c++) { + Vector values; + for (uint32_t r = 0; r < col->Width(); r++) { + values.Push(scalars[c * col->Width() + r]); + } + columns.Push(b.Construct(col, std::move(values))->Result()); + } + + // Construct the matrix from the column vectors and replace the original instruction. + b.ConstructWithResult(construct->DetachResult(), std::move(columns)); + construct->Destroy(); + } +}; + +} // namespace + +Result VectorizeScalarMatrixConstructors(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.VectorizeScalarMatrixConstructors", + kVectorizeScalarMatrixConstructorsCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h new file mode 100644 index 000000000..30f25558a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h @@ -0,0 +1,60 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_VECTORIZE_SCALAR_MATRIX_CONSTRUCTORS_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_VECTORIZE_SCALAR_MATRIX_CONSTRUCTORS_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kVectorizeScalarMatrixConstructorsCapabilities{ + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowHandleVarsWithoutBindings, + core::ir::Capability::kAllowClipDistancesOnF32ScalarAndVector, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// VectorizeScalarMatrixConstructors is a transform that replaces construct instructions that +/// produce matrices from scalar operands to construct individual columns first. +/// +/// @param module the module to transform +/// @returns success or failure +Result VectorizeScalarMatrixConstructors(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_VECTORIZE_SCALAR_MATRIX_CONSTRUCTORS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.cc new file mode 100644 index 000000000..0445785ca --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.cc @@ -0,0 +1,697 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/vertex_pulling.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/manager.h" + +namespace tint::core::ir::transform { +namespace { + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +/// @returns the vector width of @p format +uint32_t FormatWidth(VertexFormat format) { + switch (format) { + case VertexFormat::kUint8: + case VertexFormat::kSint8: + case VertexFormat::kUnorm8: + case VertexFormat::kSnorm8: + case VertexFormat::kUint16: + case VertexFormat::kSint16: + case VertexFormat::kUnorm16: + case VertexFormat::kSnorm16: + case VertexFormat::kFloat16: + case VertexFormat::kFloat32: + case VertexFormat::kUint32: + case VertexFormat::kSint32: + return 1; + case VertexFormat::kUint8x2: + case VertexFormat::kSint8x2: + case VertexFormat::kUnorm8x2: + case VertexFormat::kSnorm8x2: + case VertexFormat::kUint16x2: + case VertexFormat::kSint16x2: + case VertexFormat::kUnorm16x2: + case VertexFormat::kSnorm16x2: + case VertexFormat::kFloat16x2: + case VertexFormat::kFloat32x2: + case VertexFormat::kUint32x2: + case VertexFormat::kSint32x2: + return 2; + case VertexFormat::kFloat32x3: + case VertexFormat::kUint32x3: + case VertexFormat::kSint32x3: + return 3; + case VertexFormat::kUint8x4: + case VertexFormat::kSint8x4: + case VertexFormat::kUnorm8x4: + case VertexFormat::kSnorm8x4: + case VertexFormat::kUint16x4: + case VertexFormat::kSint16x4: + case VertexFormat::kUnorm16x4: + case VertexFormat::kSnorm16x4: + case VertexFormat::kFloat16x4: + case VertexFormat::kFloat32x4: + case VertexFormat::kUint32x4: + case VertexFormat::kSint32x4: + case VertexFormat::kUnorm10_10_10_2: + case VertexFormat::kUnorm8x4BGRA: + return 4; + } + TINT_UNREACHABLE(); +} + +/// PIMPL state for the transform. +struct State { + /// The vertex pulling configuration. + const VertexPullingConfig& config; + + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// A map from location to a descriptor that holds the format, buffer, the offset of the + /// vertex data from the start of the buffer, and the offset of the attribute from the start of + /// the element. + struct LocationInfo { + VertexFormat format; + core::ir::Value* buffer = nullptr; + // Word offset within the buffer to the start of the data for this invocation. + core::ir::Value* base_offset = nullptr; + // Byte offset within the data for this invocation to the start of the attribute data. + uint32_t attr_byte_offset; + }; + Hashmap locations_{}; + + /// The vertex index function parameter. + core::ir::FunctionParam* vertex_index_ = nullptr; + /// The instance index function parameter. + core::ir::FunctionParam* instance_index_ = nullptr; + + /// Process the module. + void Process() { + // Find the vertex shader entry point. There should be at most one. + core::ir::Function* ep = nullptr; + for (auto& func : ir.functions) { + if (func->IsVertex()) { + TINT_IR_ASSERT(ir, !ep); + ep = func; + } + } + if (!ep) { + return; + } + + Vector new_params; + b.InsertBefore(ep->Block()->Front(), [&] { // + // Create the storage buffers and record vertex attribute information. + CreateBuffers(); + + // Pull vertex attributes out of the entry point parameters and replace them. + for (auto* param : ep->Params()) { + if (auto* str = param->Type()->As()) { + ProcessStructParameter(param, str); + param->Destroy(); + } else if (auto loc = param->Attributes().location) { + // Load the vertex attribute and replace uses of the parameter with it. + auto* input = Load(*loc, param->Type()); + param->ReplaceAllUsesWith(input); + param->Destroy(); + } else { + // Other parameters should be builtins, which can only be the vertex and + // instance indices. Replace any user-declared indices with the ones that we + // created when setting up the buffers. + auto builtin = param->Builtin(); + TINT_IR_ASSERT(ir, builtin); + switch (*builtin) { + case core::BuiltinValue::kVertexIndex: + if (vertex_index_) { + param->ReplaceAllUsesWith(vertex_index_); + param->Destroy(); + } else { + new_params.Push(param); + } + break; + case core::BuiltinValue::kInstanceIndex: + if (instance_index_) { + param->ReplaceAllUsesWith(instance_index_); + param->Destroy(); + } else { + new_params.Push(param); + } + break; + default: + TINT_IR_UNREACHABLE(ir); + } + } + } + }); + + // Update the entry point with the new parameter list. + if (vertex_index_) { + new_params.Push(vertex_index_); + } + if (instance_index_) { + new_params.Push(instance_index_); + } + ep->SetParams(std::move(new_params)); + } + + /// @returns the vertex index parameter, creating one if needed + core::ir::FunctionParam* GetVertexIndex() { + if (!vertex_index_) { + vertex_index_ = b.FunctionParam("tint_vertex_index"); + vertex_index_->SetBuiltin(core::BuiltinValue::kVertexIndex); + } + return vertex_index_; + } + + /// @returns the instance index parameter, creating one if needed + core::ir::FunctionParam* GetInstanceIndex() { + if (!instance_index_) { + instance_index_ = b.FunctionParam("tint_instance_index"); + instance_index_->SetBuiltin(core::BuiltinValue::kInstanceIndex); + } + return instance_index_; + } + + /// Create storage buffers and record vertex attribute information. + /// Record instructions that need vertex and instance indices. + void CreateBuffers() { + for (uint32_t i = 0; i < config.vertex_state.size(); i++) { + // Create the storage buffer. + auto& buffer = config.vertex_state[i]; + auto buffer_name = "tint_vertex_buffer_" + std::to_string(i); + core::ir::Var* var = nullptr; + b.Append(ir.root_block, [&] { + var = b.Var(buffer_name, ty.ptr, read>()); + var->SetBindingPoint(config.pulling_group, i); + }); + + // Determine the base offset of the vertex data in the storage buffer. + core::ir::Value* index = nullptr; + if (buffer.step_mode == VertexStepMode::kVertex) { + index = GetVertexIndex(); + } else if (buffer.step_mode == VertexStepMode::kInstance) { + index = GetInstanceIndex(); + } + if (buffer.array_stride != 4) { + // Multiply the index by the stride in words. + TINT_IR_ASSERT(ir, (buffer.array_stride & 3u) == 0u); + index = b.Multiply(index, u32(buffer.array_stride / 4))->Result(); + ir.SetName(index, buffer_name + "_base"); + } + + // Register the format, buffer, and offset for each location slot. + for (auto& attr : buffer.attributes) { + locations_.Add(attr.shader_location, LocationInfo{ + .format = attr.format, + .buffer = var->Result(), + .base_offset = index, + .attr_byte_offset = attr.offset, + }); + } + } + } + + /// Pull vertex attributes out of structure parameter. + /// Replace the parameter with a new structure created from the attributes. + /// @param param the parameter + /// @param str the structure type + void ProcessStructParameter(core::ir::FunctionParam* param, const core::type::Struct* str) { + Vector construct_args; + for (auto* member : str->Members()) { + if (auto loc = member->Attributes().location) { + construct_args.Push(Load(*loc, member->Type())); + } else { + // Other parameters should be builtins, which can only be the vertex and instance + // indices. Use the separate parameters that we created for these indices. Because + // there are no duplicates, this doesn't conflict with the param handling above. + TINT_IR_ASSERT(ir, member->Attributes().builtin); + switch (*member->Attributes().builtin) { + case core::BuiltinValue::kVertexIndex: + construct_args.Push(GetVertexIndex()); + break; + case core::BuiltinValue::kInstanceIndex: + construct_args.Push(GetInstanceIndex()); + break; + default: + TINT_IR_UNREACHABLE(ir); + } + } + } + param->ReplaceAllUsesWith(b.Construct(str, std::move(construct_args))->Result()); + } + + /// Load a vertex attribute. + /// @param location the location index of the attribute + /// @param shader_type the type of the attribute declared in the shader + /// @returns the loaded attribute value + core::ir::Value* Load(uint32_t location, const core::type::Type* shader_type) { + auto info = locations_.Get(location); + TINT_IR_ASSERT(ir, info); + + // Load the attribute data from the buffer. + auto* value = LoadFromBuffer(*info, shader_type->DeepestElement()); + + // The shader type may have a different component width to the vertex attribute, so we may + // need to add or remove components. + auto src_width = FormatWidth(info->format); + auto dst_width = 1u; + if (auto* vec = shader_type->As()) { + dst_width = vec->Width(); + } + if (dst_width < src_width) { + // The type declared in the shader is narrower than the vertex attribute format, so + // truncate the value with a swizzle. + switch (dst_width) { + case 1: + value = b.Swizzle(shader_type, value, Vector{0u})->Result(); + break; + case 2: + value = b.Swizzle(shader_type, value, Vector{0u, 1u})->Result(); + break; + case 3: + value = b.Swizzle(shader_type, value, Vector{0u, 1u, 2u})->Result(); + break; + default: + TINT_IR_UNREACHABLE(ir) << dst_width; + } + } else if (dst_width > src_width) { + // The type declared in the shader is wider than the vertex attribute format, so append + // values to pad it out. Append a `1` value for the fourth element of a vector, + // otherwise append zero. + auto* elem_ty = shader_type->DeepestElement(); + auto one = [&] { + return tint::Switch( + elem_ty, // + [&](const core::type::I32*) { return b.Constant(1_i); }, // + [&](const core::type::U32*) { return b.Constant(1_u); }, // + [&](const core::type::F32*) { return b.Constant(1_f); }, // + [&](const core::type::F16*) { return b.Constant(1_h); }, // + TINT_ICE_ON_NO_MATCH); + }; + Vector values{value}; + for (uint32_t i = src_width; i < dst_width; i++) { + values.Push(i == 3 ? one() : b.Zero(elem_ty)); + } + value = b.Construct(shader_type, std::move(values))->Result(); + } + + return value; + } + + /// Load attribute data from a buffer. + /// @param info the location descriptor + /// @param shader_element_type the element type of the attribute declared in the shader + /// @returns the loaded attribute data + core::ir::Value* LoadFromBuffer(const LocationInfo& info, + const core::type::Type* shader_element_type) { + // Helper for loading a single word from the buffer at an offset. + auto load_u32 = [&](uint32_t offset) { + auto offset_value = info.base_offset; + offset += (info.attr_byte_offset / 4u); + if (offset > 0) { + offset_value = b.Add(offset_value, u32(offset))->Result(); + } + auto* word = + b.Load(b.Access>(info.buffer, offset_value))->Result(); + // If the offset is not 4-byte aligned, shift the word so that the requested data starts + // at the first byte. The shift amount is the offset of the byte within a word + // multiplied by 8 to get the bit offset. + if (info.attr_byte_offset & 3) { + word = b.ShiftRight(word, u32((info.attr_byte_offset & 3) * 8))->Result(); + } + return word; + }; + // Helpers for loading non-u32 data from the buffer. + auto load_i32 = [&](uint32_t offset) { return b.Bitcast(load_u32(offset))->Result(); }; + auto load_f32 = [&](uint32_t offset) { return b.Bitcast(load_u32(offset))->Result(); }; + auto load_ivec = [&](uint32_t offset, uint32_t bits, const core::type::Vector* vec) { + // For a vec2, we read the `xxxx'yyyy` u32 word. We then splat to a vec2 and left + // shift so we have `(xxxx'yyyy, yyyy'xxxx)`. Finally, we right shift to produce + // `(0000'xxxx, 0000'yyyy)` + auto* uvec = ty.MatchWidth(ty.u32(), vec); + // yyyyxxxx + auto* word = load_u32(offset); + if (vec->Type()->Is()) { + word = b.Bitcast(word)->Result(); + } + // yyyyxxxx, yyyyxxxx + auto* splat = b.Construct(vec, word); + // xxxxyyyy, yyyyxxxx + core::ir::Instruction* shift_left = nullptr; + switch (vec->Width()) { + case 2: + if (bits == 8) { + shift_left = b.ShiftLeft(splat, b.Composite(uvec, 24_u, 16_u)); + } else if (bits == 16) { + shift_left = b.ShiftLeft(splat, b.Composite(uvec, 16_u, 0_u)); + } else { + TINT_IR_UNREACHABLE(ir); + } + break; + case 4: + TINT_IR_ASSERT(ir, bits == 8); + shift_left = b.ShiftLeft(splat, b.Composite(uvec, 24_u, 16_u, 8_u, 0_u)); + break; + default: + TINT_IR_UNREACHABLE(ir); + } + // 0000xxxx, 0000yyyy + return b.ShiftRight(shift_left, b.Splat(uvec, u32(32 - bits)))->Result(); + }; + // Helper to convert a value to f16 if required by the shader, otherwise returns the f32. + auto float_value = [&](core::ir::Value* value) -> core::ir::Value* { + // If the shader expects an f16 value, convert the value. + if (shader_element_type->Is()) { + return b.Convert(ty.MatchWidth(ty.f16(), value->Type()), value)->Result(); + } + return value; + }; + + switch (info.format) { + // Formats that are always u32 in the shader (or vectors of u32). + // Shift/mask values to expand to 32-bits. + case VertexFormat::kUint8: + return b.And(load_u32(0), 0xFF_u)->Result(); + case VertexFormat::kUint8x2: + return load_ivec(0, 8, ty.vec2u()); + case VertexFormat::kUint8x4: + return load_ivec(0, 8, ty.vec4u()); + case VertexFormat::kUint16: + return b.And(load_u32(0), 0xFFFF_u)->Result(); + case VertexFormat::kUint16x2: + return load_ivec(0, 16, ty.vec2u()); + case VertexFormat::kUint16x4: { + auto* xy = load_ivec(0, 16, ty.vec2u()); + auto* zw = load_ivec(1, 16, ty.vec2u()); + return b.Construct>(xy, zw)->Result(); + } + case VertexFormat::kUint32: + return load_u32(0); + case VertexFormat::kUint32x2: { + auto* x = load_u32(0); + auto* y = load_u32(1); + return b.Construct>(x, y)->Result(); + } + case VertexFormat::kUint32x3: { + auto* x = load_u32(0); + auto* y = load_u32(1); + auto* z = load_u32(2); + return b.Construct>(x, y, z)->Result(); + } + case VertexFormat::kUint32x4: { + auto* x = load_u32(0); + auto* y = load_u32(1); + auto* z = load_u32(2); + auto* w = load_u32(3); + return b.Construct>(x, y, z, w)->Result(); + } + + // Formats that are always i32 in the shader (or vectors of i32). + // Shift values to expand to 32-bits. + case VertexFormat::kSint8: { + // ******xx + auto* word = b.Bitcast(load_u32(0)); + // 000000xx + return b.ShiftRight(b.ShiftLeft(word, 24_u), 24_u)->Result(); + } + case VertexFormat::kSint8x2: + return load_ivec(0, 8, ty.vec2i()); + case VertexFormat::kSint8x4: + return load_ivec(0, 8, ty.vec4i()); + case VertexFormat::kSint16: { + // ****xxxx + auto* word = b.Bitcast(load_u32(0)); + // 0000xxxx + return b.ShiftRight(b.ShiftLeft(word, 16_u), 16_u)->Result(); + } + case VertexFormat::kSint16x2: + return load_ivec(0, 16, ty.vec2i()); + case VertexFormat::kSint16x4: { + auto* xy = load_ivec(0, 16, ty.vec2i()); + auto* zw = load_ivec(1, 16, ty.vec2i()); + return b.Construct>(xy, zw)->Result(); + } + case VertexFormat::kSint32: + return load_i32(0); + case VertexFormat::kSint32x2: { + auto* x = load_i32(0); + auto* y = load_i32(1); + return b.Construct>(x, y)->Result(); + } + case VertexFormat::kSint32x3: { + auto* x = load_i32(0); + auto* y = load_i32(1); + auto* z = load_i32(2); + return b.Construct>(x, y, z)->Result(); + } + case VertexFormat::kSint32x4: { + auto* x = load_i32(0); + auto* y = load_i32(1); + auto* z = load_i32(2); + auto* w = load_i32(3); + return b.Construct>(x, y, z, w)->Result(); + } + + // Unsigned normalized formats. + // Use unpack builtins to convert to f32. + case VertexFormat::kUnorm8: { + // ******xx + auto* word = load_u32(0); + // 000000xx, ********, ********, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Unorm, word); + // 000000xx + return float_value(b.Access(unpack, 0_u)->Result()); + } + case VertexFormat::kUnorm8x2: { + // ****yyxx + auto* word = load_u32(0); + // 000000xx, 000000yy, ********, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Unorm, word); + // 000000xx, 000000yy + return float_value(b.Swizzle>(unpack, Vector{0u, 1u})->Result()); + } + case VertexFormat::kUnorm8x4: { + // wwzzyyxx + auto* word = load_u32(0); + // 000000xx, 000000yy, 000000zz, 000000ww + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Unorm, word); + return float_value(unpack->Result()); + } + case VertexFormat::kUnorm8x4BGRA: { + // wwzzyyxx + auto* word = load_u32(0); + // 000000xx, 000000yy, 000000zz, 000000ww + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Unorm, word); + // 000000zz, 000000yy, 000000xx, 000000ww + return float_value(b.Swizzle>(unpack, Vector{2u, 1u, 0u, 3u})->Result()); + } + case VertexFormat::kUnorm16: { + // ****xxxx + auto* word = load_u32(0); + // 0000xxxx, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack2X16Unorm, word); + // 0000xxxx + return float_value(b.Access(unpack, 0_u)->Result()); + } + case VertexFormat::kUnorm16x2: { + // yyyyxxxx + auto* word = load_u32(0); + // 0000xxxx, 0000yyyy + auto* unpack = b.Call>(core::BuiltinFn::kUnpack2X16Unorm, word); + return float_value(unpack->Result()); + } + case VertexFormat::kUnorm16x4: { + // yyyyxxxx, wwwwzzzz + auto* word0 = load_u32(0); + auto* word1 = load_u32(1); + // 0000xxxx, 0000yyyy, 0000zzzz, 0000wwww + auto* unpack0 = b.Call>(core::BuiltinFn::kUnpack2X16Unorm, word0); + auto* unpack1 = b.Call>(core::BuiltinFn::kUnpack2X16Unorm, word1); + return float_value(b.Construct>(unpack0, unpack1)->Result()); + } + + // Signed normalized formats. + // Use unpack builtins to expand to f32. + case VertexFormat::kSnorm8: { + // ******xx + auto* word = load_u32(0); + // 000000xx, ********, ********, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Snorm, word); + // 000000xx + return float_value(b.Access(unpack, 0_u)->Result()); + } + case VertexFormat::kSnorm8x2: { + // ****yyxx + auto* word = load_u32(0); + // 000000xx, 000000yy, ********, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Snorm, word); + // 000000xx, 000000yy + return float_value(b.Swizzle>(unpack, Vector{0u, 1u})->Result()); + } + case VertexFormat::kSnorm8x4: { + // wwzzyyxx + auto* word = load_u32(0); + // 000000xx, 000000yy, 000000zz, 000000ww + auto* unpack = b.Call>(core::BuiltinFn::kUnpack4X8Snorm, word); + return float_value(unpack->Result()); + } + case VertexFormat::kSnorm16: { + // ****xxxx + auto* word = load_u32(0); + // 0000xxxx, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack2X16Snorm, word); + // 0000xxxx + return float_value(b.Access(unpack, 0_u)->Result()); + } + case VertexFormat::kSnorm16x2: { + // yyyyxxxx + auto* word = load_u32(0); + // 0000xxxx, 0000yyyy + auto* unpack = b.Call>(core::BuiltinFn::kUnpack2X16Snorm, word); + return float_value(unpack->Result()); + } + case VertexFormat::kSnorm16x4: { + // yyyyxxxx, wwwwzzzz + auto* word0 = load_u32(0); + auto* word1 = load_u32(1); + // 0000xxxx, 0000yyyy, 0000zzzz, 0000wwww + auto* unpack0 = b.Call>(core::BuiltinFn::kUnpack2X16Snorm, word0); + auto* unpack1 = b.Call>(core::BuiltinFn::kUnpack2X16Snorm, word1); + return float_value(b.Construct>(unpack0, unpack1)->Result()); + } + + // F16 formats that can either be f16 or f32 in the shader. + // If f16 is expected just bitcast, otherwise use unpack builtins to convert to f32. + case VertexFormat::kFloat16: { + // ****xxxx + auto* word = load_u32(0); + if (shader_element_type->Is()) { + // xxxx, **** + auto* bitcast = b.Bitcast>(word); + // xxxx + return b.Access(bitcast, 0_u)->Result(); + } else { + // 0000xxxx, ******** + auto* unpack = b.Call>(core::BuiltinFn::kUnpack2X16Float, word); + // 0000xxxx + return b.Access(unpack, 0_u)->Result(); + } + } + case VertexFormat::kFloat16x2: { + // yyyyxxxx + auto* word = load_u32(0); + if (shader_element_type->Is()) { + // xxxx, yyyy + return b.Bitcast>(word)->Result(); + } else { + // 0000xxxx, 0000yyyy + auto* unpack = b.Call>(core::BuiltinFn::kUnpack2X16Float, word); + return unpack->Result(); + } + } + case VertexFormat::kFloat16x4: { + // yyyyxxxx, wwwwzzzz + auto* word0 = load_u32(0); + auto* word1 = load_u32(1); + if (shader_element_type->Is()) { + // xxxx, yyyy, zzzz, wwww + auto* bitcast0 = b.Bitcast>(word0); + auto* bitcast1 = b.Bitcast>(word1); + return b.Construct>(bitcast0, bitcast1)->Result(); + } else { + // 0000xxxx, 0000yyyy, 0000zzzz, 0000wwww + auto* unpack0 = b.Call>(core::BuiltinFn::kUnpack2X16Float, word0); + auto* unpack1 = b.Call>(core::BuiltinFn::kUnpack2X16Float, word1); + return b.Construct>(unpack0, unpack1)->Result(); + } + } + + // F32 formats that can either be f16 or f32 in the shader. + // Load the f32 data and downconvert to f16 if needed. + case VertexFormat::kFloat32: + return float_value(load_f32(0)); + case VertexFormat::kFloat32x2: { + auto* x = load_f32(0); + auto* y = load_f32(1); + return float_value(b.Construct>(x, y)->Result()); + } + case VertexFormat::kFloat32x3: { + auto* x = load_f32(0); + auto* y = load_f32(1); + auto* z = load_f32(2); + return float_value(b.Construct>(x, y, z)->Result()); + } + case VertexFormat::kFloat32x4: { + auto* x = load_f32(0); + auto* y = load_f32(1); + auto* z = load_f32(2); + auto* w = load_f32(3); + return float_value(b.Construct>(x, y, z, w)->Result()); + } + + // Miscellaneous other formats that need custom handling. + case VertexFormat::kUnorm10_10_10_2: { + auto* u32s = b.Construct>(load_u32(0)); + // shr = u32s >> vec4u(0, 10, 20, 30); + auto* shr = b.ShiftRight(u32s, b.Composite>(0_u, 10_u, 20_u, 30_u)); + // mask = shr & vec4u(0x3FF, 0x3FF, 0x3FF, 0x3); + auto* mask = b.And(shr, b.Composite>(0x3FF_u, 0x3FF_u, 0x3FF_u, 0x3_u)); + // vec4f(mask) / vec4f(1023, 1023, 1023, 3); + auto* div = b.Composite>(1023_f, 1023_f, 1023_f, 3_f); + return float_value(b.Divide(b.Convert>(mask), div)->Result()); + } + } + TINT_IR_UNREACHABLE(ir); + } +}; + +} // namespace + +Result VertexPulling(core::ir::Module& ir, const VertexPullingConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "core.VertexPulling", kVertexPullingCapabilities)); + + State{config, ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.h new file mode 100644 index 000000000..9d5adca86 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/vertex_pulling.h @@ -0,0 +1,64 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_VERTEX_PULLING_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_VERTEX_PULLING_H_ + +#include "src/tint/api/common/vertex_pulling_config.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kVertexPullingCapabilities{}; + +/// This transform replaces vertex shader inputs with storage buffers, so that we can apply +/// robustness to the vertex input accesses. +/// +/// We bind the storage buffers as arrays of u32, so any read to byte position `p` will actually +/// need to read position `p / 4`, since `sizeof(u32) == 4`. +/// +/// The config specifies the input format for each attribute. This isn't related to the type of the +/// input in the shader. For example, `VertexFormat::kVec2F16` tells us that the buffer will +/// contain `f16` elements, to be read as `vec2`. In the shader, a user would declare a `vec2` +/// input to be able to use them. The conversion between `f16` and `f32` is handled by this +/// transform. +/// +/// @param module the module to transform +/// @param config the vertex pulling configuration +/// @returns success or failure +Result VertexPulling(core::ir::Module& module, const VertexPullingConfig& config); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_VERTEX_PULLING_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc b/3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc new file mode 100644 index 000000000..83e3b043d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc @@ -0,0 +1,317 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/referenced_module_vars.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/containers/reverse.h" + +#if TINT_BUILD_IS_MSVC +#if _MSC_VER > 1930 && _MSC_VER < 1939 +// MSVC raises an internal compiler error in Vector::Sort(), when optimizations are enabled. +// Later versions are fixed. +TINT_BEGIN_DISABLE_OPTIMIZATIONS(); +#endif +#endif + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::core::ir::transform { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + Module& ir; + + /// The IR builder. + Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The mapping from functions to their transitively referenced workgroup variables. + ReferencedModuleVars referenced_module_vars_{ + ir, [](const Var* var) { + auto* view = var->Result()->Type()->As(); + return view && view->AddressSpace() == AddressSpace::kWorkgroup; + }}; + + /// ArrayIndex represents a required array index for an access instruction. + struct ArrayIndex { + /// The size of the array that will be indexed. + uint32_t count = 0u; + }; + + /// Index represents an index for an access instruction, which is either a constant value or + /// an array index that will be dynamically calculated from an array size. + using Index = std::variant; + + /// Store describes a store to a sub-element of a workgroup variable. + struct Store { + /// The workgroup variable. + Var* var = nullptr; + /// The store type of the element. + const type::Type* store_type = nullptr; + /// The list of index operands to get to the element. + Vector indices; + }; + + /// StoreList is a list of `Store` descriptors. + using StoreList = Vector; + + /// StoreMap is a map from iteration count to a list of `Store` descriptors. + using StoreMap = Hashmap; + + /// Process the module. + void Process() { + if (ir.root_block->IsEmpty()) { + return; + } + // Process each entry point function. + for (auto& func : ir.functions) { + if (func->Stage() == Function::PipelineStage::kCompute) { + ProcessEntryPoint(func); + } + } + } + + /// Process an entry point function to zero-initialize the workgroup variables that it uses. + /// @param func the entry point function + void ProcessEntryPoint(Function* func) { + // Get list of transitively referenced workgroup variables. + const auto& vars = referenced_module_vars_.TransitiveReferences(func); + if (vars.IsEmpty()) { + return; + } + + // Build list of store descriptors for all workgroup variables. + StoreMap stores; + for (auto* var : vars) { + PrepareStores(var, var->Result()->Type()->UnwrapPtr(), 1, {}, stores); + } + + // Sort the iteration counts to get deterministic output in tests. + auto sorted_iteration_counts = stores.Keys(); + sorted_iteration_counts.Sort(); + + // Capture the first instruction of the function. + // All new instructions will be inserted before this. + auto* function_start = func->Block()->Front(); + + // Get the local invocation index and the linearized workgroup size. + auto* local_index = GetLocalInvocationIndex(func); + + auto wgsizes = func->WorkgroupSizeAsConst(); + TINT_IR_ASSERT(ir, wgsizes); + auto wgsize = wgsizes.value()[0] * wgsizes.value()[1] * wgsizes.value()[2]; + + // Insert instructions to zero-initialize every variable. + b.InsertBefore(function_start, [&] { + for (auto count : sorted_iteration_counts) { + auto element_stores = stores.Get(count); + TINT_IR_ASSERT(ir, count); + // No loop is required if we have at least as many invocations than counts. + if (count <= wgsize) { + // Make the first |count| invocations in the group perform the arrayed stores. + auto* ifelse = b.If(b.LessThan(local_index, u32(count))); + b.Append(ifelse->True(), [&] { + for (auto& store : *element_stores) { + GenerateStore(store, count, local_index); + } + b.ExitIf(ifelse); + }); + } else { + // Use a loop for arrayed stores that exceed the wgsize + b.LoopRange(local_index, u32(count), u32(wgsize), [&](Value* index) { + for (auto& store : *element_stores) { + GenerateStore(store, count, index); + } + }); + } + } + b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier); + }); + } + + /// Recursively generate store descriptors for a workgroup variable. + /// Determines the combined array iteration count of each inner element. + /// @param var the workgroup variable + /// @param type the current element type + /// @param iteration_count the iteration count of this inner element of the variable + /// @param indices the access indices needed to get to this element + /// @param stores the map of stores to populate + void PrepareStores(Var* var, + const type::Type* type, + uint32_t iteration_count, + Vector indices, + StoreMap& stores) { + // If this type can be trivially zeroed, store to the whole element. + if (CanTriviallyZero(type)) { + stores.GetOrAddZero(iteration_count).Push(Store{var, type, indices}); + return; + } + + tint::Switch( + type, + [&](const type::Array* arr) { + // Add an array index to the list and recurse into the element type. + TINT_IR_ASSERT(ir, arr->ConstantCount()); + auto count = arr->ConstantCount().value(); + auto new_indices = indices; + if (count > 1) { + new_indices.Push(ArrayIndex{count}); + } else { + new_indices.Push(0u); + } + PrepareStores(var, arr->ElemType(), iteration_count * count, new_indices, stores); + }, + [&](const type::Atomic*) { + stores.GetOrAddZero(iteration_count).Push(Store{var, type, indices}); + }, + [&](const type::Struct* str) { + for (auto* member : str->Members()) { + // Add the member index to the index list and recurse into its type. + auto new_indices = indices; + new_indices.Push(member->Index()); + PrepareStores(var, member->Type(), iteration_count, new_indices, stores); + } + }, // + TINT_ICE_ON_NO_MATCH); + } + + /// Get or inject an entry point builtin for the local invocation index. + /// @param func the entry point function + /// @returns the local invocation index builtin + Value* GetLocalInvocationIndex(Function* func) { + // Look for an existing local_invocation_index builtin parameter. + for (auto* param : func->Params()) { + if (auto* str = param->Type()->As()) { + // Check each member for the local invocation index builtin attribute. + for (auto* member : str->Members()) { + if (member->Attributes().builtin == BuiltinValue::kLocalInvocationIndex) { + auto* access = b.Access(ty.u32(), param, u32(member->Index())); + access->InsertBefore(func->Block()->Front()); + return access->Result(); + } + } + } else { + // Check if the parameter is the local invocation index. + if (param->Builtin() == BuiltinValue::kLocalInvocationIndex) { + return param; + } + } + } + + // No local invocation index was found, so add one to the parameter list and use that. + auto* param = b.FunctionParam("tint_local_index", ty.u32()); + func->AppendParam(param); + param->SetBuiltin(BuiltinValue::kLocalInvocationIndex); + return param; + } + + /// Generate the store instruction for a given store descriptor. + /// @param store the store descriptor + /// @param total_count the total number of elements that will be zeroed + /// @param linear_index the linear index of the single element that will be zeroed + void GenerateStore(const Store& store, uint32_t total_count, Value* linear_index) { + auto* to = store.var->Result(); + if (!store.indices.IsEmpty()) { + // Build the access indices to get to the target element. + // We walk backwards along the index list so that adjacent invocation store to + // adjacent array elements. + uint32_t count = 1; + Vector indices; + for (auto idx : Reverse(store.indices)) { + if (std::holds_alternative(idx)) { + // Array indices are computed from the linear index based on the size of the + // array and the size of the sub-arrays that have already been indexed. + auto array_index = std::get(idx); + Value* index = linear_index; + if (count > 1) { + index = b.Divide(index, u32(count))->Result(); + } + if (total_count > count * array_index.count) { + index = b.Modulo(index, u32(array_index.count))->Result(); + } + indices.Push(index); + count *= array_index.count; + } else { + // Constant indices are added to the list unmodified. + indices.Push(b.Constant(u32(std::get(idx)))); + } + } + indices.Reverse(); + to = b.Access(ty.ptr(workgroup, store.store_type), to, indices)->Result(); + } + + // Generate the store instruction. + if (auto* atomic = store.store_type->As()) { + auto* zero = b.Constant(ir.constant_values.Zero(atomic->Type())); + b.Call(ty.void_(), core::BuiltinFn::kAtomicStore, to, zero); + } else { + auto* zero = b.Constant(ir.constant_values.Zero(store.store_type)); + b.Store(to, zero); + } + } + + /// Check if a type can be efficiently zeroed with a single store. Returns `false` if there are + /// any nested arrays or atomics. + /// @param type the type to inspect + /// @returns true if a variable with store type @p ty can be efficiently zeroed + bool CanTriviallyZero(const core::type::Type* type) { + if (type->IsAnyOf()) { + return false; + } + if (auto* str = type->As()) { + for (auto* member : str->Members()) { + if (!CanTriviallyZero(member->Type())) { + return false; + } + } + } + return true; + } +}; + +} // namespace + +Result ZeroInitWorkgroupMemory(Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "core.ZeroInitWorkgroupMemory", + kZeroInitWorkgroupMemoryCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::core::ir::transform diff --git a/3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h b/3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h new file mode 100644 index 000000000..895235c91 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h @@ -0,0 +1,56 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_ZERO_INIT_WORKGROUP_MEMORY_H_ +#define SRC_TINT_LANG_CORE_IR_TRANSFORM_ZERO_INIT_WORKGROUP_MEMORY_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::core::ir::transform { + +/// The capabilities that the transform can support. +const Capabilities kZeroInitWorkgroupMemoryCapabilities{ + Capability::kAllowDuplicateBindings, + Capability::kAllowNonCoreTypes, + Capability::kAllow8BitIntegers, +}; + +/// ZeroInitWorkgroupMemory is a transform that injects code at the top of each entry point to +/// zero-initialize workgroup memory used by that entry point. +/// @param module the module to transform +/// @returns success or failure +Result ZeroInitWorkgroupMemory(Module& module); + +} // namespace tint::core::ir::transform + +#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_ZERO_INIT_WORKGROUP_MEMORY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/traverse.h b/3rdparty/dawn/src/tint/lang/core/ir/traverse.h new file mode 100644 index 000000000..86122d323 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/traverse.h @@ -0,0 +1,78 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TRAVERSE_H_ +#define SRC_TINT_LANG_CORE_IR_TRAVERSE_H_ + +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint::core::ir { + +/// Traverse calls @p callback with each instruction in @p block and all child blocks of @p block +/// that matches the callback parameter type. +/// @param block the block to traverse +/// @param callback a function with the signature `void(T*)` +template +void Traverse(Block* block, CALLBACK&& callback) { + using T = std::remove_pointer_t>; + + Vector queue; + if (!block->IsEmpty()) { + queue.Push(block->Front()); + } + while (!queue.IsEmpty()) { + for (auto* inst = queue.Pop(); inst != nullptr; inst = inst->next) { + if (auto* as_t = inst->As()) { + callback(as_t); + } + if (auto* ctrl = inst->As()) { + if (Instruction* next = inst->next) { + queue.Push(next); // Resume iteration of this block + } + + Vector children; + ctrl->ForeachBlock([&](ir::Block* b) { + if (!b->IsEmpty()) { + children.Push(b->Front()); + } + }); + for (auto* child : Reverse(children)) { + queue.Push(child); + } + break; + } + } + } +} + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_TRAVERSE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/type/array_count.cc b/3rdparty/dawn/src/tint/lang/core/ir/type/array_count.cc new file mode 100644 index 000000000..d82925b83 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/type/array_count.cc @@ -0,0 +1,54 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/type/array_count.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::type::ValueArrayCount); + +namespace tint::core::ir::type { + +ValueArrayCount::ValueArrayCount(Value* val) + : Base(static_cast(tint::TypeCode::Of().bits)), value(val) {} + +ValueArrayCount::~ValueArrayCount() = default; + +bool ValueArrayCount::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return value == v->value; + } + return false; +} + +std::string ValueArrayCount::FriendlyName() const { + return ""; +} + +core::type::ArrayCount* ValueArrayCount::Clone(core::type::CloneContext&) const { + TINT_UNREACHABLE() << "Value array count clone not available"; +} + +} // namespace tint::core::ir::type diff --git a/3rdparty/dawn/src/tint/lang/core/ir/type/array_count.h b/3rdparty/dawn/src/tint/lang/core/ir/type/array_count.h new file mode 100644 index 000000000..4f2a650a4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/type/array_count.h @@ -0,0 +1,67 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_TYPE_ARRAY_COUNT_H_ +#define SRC_TINT_LANG_CORE_IR_TYPE_ARRAY_COUNT_H_ + +#include + +#include "src/tint/lang/core/type/array_count.h" + +// Predeclarations +namespace tint::core::ir { +class Value; +} + +namespace tint::core::ir::type { + +/// The variant of an ArrayCount when the count is an ir `Value`. +class ValueArrayCount final : public Castable { + public: + /// Constructor + /// @param val the value + explicit ValueArrayCount(Value* val); + ~ValueArrayCount() override; + + /// @param other the other node + /// @returns true if this array count is equal @p other + bool Equals(const core::type::UniqueNode& other) const override; + + /// @returns the friendly name for this array count + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + core::type::ArrayCount* Clone(core::type::CloneContext& ctx) const override; + + /// The value + Value* value; +}; + +} // namespace tint::core::ir::type + +#endif // SRC_TINT_LANG_CORE_IR_TYPE_ARRAY_COUNT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/unary.cc b/3rdparty/dawn/src/tint/lang/core/ir/unary.cc new file mode 100644 index 000000000..e3a7bb0b0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/unary.cc @@ -0,0 +1,46 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/unary.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Unary); + +namespace tint::core::ir { + +Unary::Unary(Id id) : Base(id) {} + +Unary::Unary(Id id, InstructionResult* result, UnaryOp op, Value* val) : Base(id), op_(op) { + AddOperand(Unary::kValueOperandOffset, val); + AddResult(result); +} + +Unary::~Unary() = default; + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/unary.h b/3rdparty/dawn/src/tint/lang/core/ir/unary.h new file mode 100644 index 000000000..f48e0f6db --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/unary.h @@ -0,0 +1,92 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_UNARY_H_ +#define SRC_TINT_LANG_CORE_IR_UNARY_H_ + +#include + +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/lang/core/unary_op.h" + +// Forward declarations +namespace tint::core::intrinsic { +struct TableData; +} + +namespace tint::core::ir { + +/// The abstract base class for dialect-specific unary-op instructions in the IR. +class Unary : public Castable> { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// The fixed number of results returned by unary instructions + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands expected for unary instructions + static constexpr size_t kNumOperands = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Unary(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param op the unary operator + /// @param val the input value for the instruction + Unary(Id id, InstructionResult* result, UnaryOp op, Value* val); + + ~Unary() override; + + /// @returns the value for the instruction + Value* Val() { return Operand(kValueOperandOffset); } + + /// @returns the value for the instruction + const Value* Val() const { return Operand(kValueOperandOffset); } + + /// @returns the unary operator + UnaryOp Op() const { return op_; } + + /// @param op the new unary operator + void SetOp(UnaryOp op) { op_ = op; } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "unary"; } + + /// @returns the table data to validate this builtin + virtual const core::intrinsic::TableData& TableData() const = 0; + + private: + UnaryOp op_ = UnaryOp::kComplement; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_UNARY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/unreachable.cc b/3rdparty/dawn/src/tint/lang/core/ir/unreachable.cc new file mode 100644 index 000000000..1fafa6ca8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/unreachable.cc @@ -0,0 +1,45 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/unreachable.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Unreachable); + +namespace tint::core::ir { + +Unreachable::Unreachable(Instruction::Id id) : Base(id) {} + +Unreachable::~Unreachable() = default; + +Unreachable* Unreachable::Clone(CloneContext& ctx) { + return ctx.ir.CreateInstruction(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/unreachable.h b/3rdparty/dawn/src/tint/lang/core/ir/unreachable.h new file mode 100644 index 000000000..4ae40409d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/unreachable.h @@ -0,0 +1,60 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_UNREACHABLE_H_ +#define SRC_TINT_LANG_CORE_IR_UNREACHABLE_H_ + +#include + +#include "src/tint/lang/core/ir/terminator.h" + +namespace tint::core::ir { + +/// An unreachable instruction in the IR. +class Unreachable final : public Castable { + public: + /// The fixed number of results returned by unreachable instructions + static constexpr size_t kNumResults = 0; + + /// The fixed number of operands accepted by unreachable instructions + static constexpr size_t kNumOperands = 0; + + /// @param id the instruction id + explicit Unreachable(Instruction::Id id); + + ~Unreachable() override; + + /// @copydoc Instruction::Clone() + Unreachable* Clone(CloneContext& ctx) override; + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "unreachable"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_UNREACHABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/unused.cc b/3rdparty/dawn/src/tint/lang/core/ir/unused.cc new file mode 100644 index 000000000..5f6d20be4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/unused.cc @@ -0,0 +1,45 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/unused.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Unused); + +namespace tint::core::ir { + +Unused::Unused() : Base(nullptr) {} + +Unused::~Unused() = default; + +Unused* Unused::Clone(CloneContext& ctx) { + return ctx.ir.CreateValue(); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/unused.h b/3rdparty/dawn/src/tint/lang/core/ir/unused.h new file mode 100644 index 000000000..8b33549b4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/unused.h @@ -0,0 +1,47 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_UNUSED_H_ +#define SRC_TINT_LANG_CORE_IR_UNUSED_H_ + +#include "src/tint/lang/core/ir/value.h" + +namespace tint::core::ir { + +/// Unused value in the IR. +class Unused : public Castable { + public: + Unused(); + ~Unused() override; + + /// @copydoc Value::Clone() + Unused* Clone(CloneContext& ctx) override; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_UNUSED_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/user_call.cc b/3rdparty/dawn/src/tint/lang/core/ir/user_call.cc new file mode 100644 index 000000000..25e1420a6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/user_call.cc @@ -0,0 +1,67 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/user_call.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::UserCall); + +namespace tint::core::ir { + +UserCall::UserCall(Id id) : Base(id) { + flags_.Add(Flag::kSequenced); +} + +UserCall::UserCall(Id id, InstructionResult* result, Function* func, VectorRef arguments) + : Base(id) { + flags_.Add(Flag::kSequenced); + AddOperand(UserCall::kFunctionOperandOffset, func); + AddOperands(UserCall::kArgsOperandOffset, std::move(arguments)); + AddResult(result); +} + +UserCall::~UserCall() = default; + +UserCall* UserCall::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* target = ctx.Remap(Target()); + auto args = ctx.Remap(Args()); + return ctx.ir.CreateInstruction(new_result, target, args); +} + +void UserCall::SetArgs(VectorRef arguments) { + auto* fn = Target(); + ClearOperands(); + AddOperand(UserCall::kFunctionOperandOffset, fn); + AddOperands(UserCall::kArgsOperandOffset, std::move(arguments)); +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/user_call.h b/3rdparty/dawn/src/tint/lang/core/ir/user_call.h new file mode 100644 index 000000000..4f21e3550 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/user_call.h @@ -0,0 +1,95 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_USER_CALL_H_ +#define SRC_TINT_LANG_CORE_IR_USER_CALL_H_ + +#include + +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A user call instruction in the IR. +class UserCall final : public Castable { + 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; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The minimum number of operands expected for this instruction + static constexpr size_t kMinOperands = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit UserCall(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param func the function being called + /// @param args the function arguments + UserCall(Id id, InstructionResult* result, Function* func, VectorRef args); + + ~UserCall() override; + + /// @copydoc Instruction::Clone() + UserCall* Clone(CloneContext& ctx) override; + + /// @returns the offset of the arguments in Operands() + size_t ArgsOperandOffset() const override { return kArgsOperandOffset; } + + /// Replaces the call arguments to @p arguments + /// @param arguments the new call arguments + void SetArgs(VectorRef arguments); + + /// @returns the called function + Function* Target() { return tint::As(Operand(kFunctionOperandOffset)); } + + /// @returns the called function + const Function* Target() const { + return tint::As(Operand(kFunctionOperandOffset)); + } + + /// Sets called function + /// @param target the new target of the call + void SetTarget(Function* target) { SetOperand(kFunctionOperandOffset, target); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "call"; } +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_USER_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/validator.cc b/3rdparty/dawn/src/tint/lang/core/ir/validator.cc new file mode 100644 index 000000000..66b17d9fd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/validator.cc @@ -0,0 +1,5244 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/validator.h" + +#include +#include +#include +#include +#include +#include + +#include "src/tint/lang/core/intrinsic/table.h" +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/block_param.h" +#include "src/tint/lang/core/ir/break_if.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/constexpr_if.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/continue.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/disassembler.h" +#include "src/tint/lang/core/ir/discard.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/function_param.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/instruction_result.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/load_vector_element.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/member_builtin_call.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/phony.h" +#include "src/tint/lang/core/ir/referenced_functions.h" +#include "src/tint/lang/core/ir/referenced_module_vars.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/store_vector_element.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/terminate_invocation.h" +#include "src/tint/lang/core/ir/type/array_count.h" +#include "src/tint/lang/core/ir/unary.h" +#include "src/tint/lang/core/ir/unreachable.h" +#include "src/tint/lang/core/ir/unused.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/function.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/memory_view.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u64.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/containers/predicates.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/internal_limits.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/result.h" +#include "src/tint/utils/rtti/castable.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +/// If set to 1 then the Tint will dump the IR when validating. +#define TINT_DUMP_IR_WHEN_VALIDATING 0 +#if TINT_DUMP_IR_WHEN_VALIDATING +#include +#include "src/tint/utils/text/styled_text_printer.h" +#endif + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::core::ir { + +struct ValidatedType { + const core::type::Type* ty; + Capabilities caps; +}; + +namespace { + +using SupportedStages = tint::EnumSet; + +/// @returns a human-readable string of all the entries in a EnumSet +template +std::string ToString(const EnumSet& values) { + std::stringstream result; + result << "[ "; + bool first = true; + for (auto v : values) { + if (!first) { + result << ", "; + } + first = false; + result << ToString(v); + } + result << " ]"; + return result.str(); +} + +/// @returns the parent block of @p block +const Block* ParentBlockOf(const Block* block) { + if (auto* parent = block->Parent()) { + return parent->Block(); + } + return nullptr; +} + +/// @returns true if @p block directly or transitively holds the instruction @p inst +bool TransitivelyHolds(const Block* block, const Instruction* inst) { + for (auto* b = inst->Block(); b; b = ParentBlockOf(b)) { + if (b == block) { + return true; + } + } + return false; +} + +/// @returns true if @p ty meets the basic function parameter rules (i.e. one of constructible, +/// pointer, handle). +/// +/// Note: Does not handle corner cases like if certain capabilities are +/// enabled. +bool IsValidFunctionParamType(const core::type::Type* ty) { + if (ty->IsConstructible() || ty->IsHandle()) { + return true; + } + + if (auto* ptr = ty->As()) { + return ptr->AddressSpace() != core::AddressSpace::kHandle; + } + return false; +} + +/// @returns true if @p ty is a non-struct and decorated with @builtin(position), or if it is a +/// struct and one of its members is decorated, otherwise false. +/// @param attr attributes attached to data +/// @param ty type of the data being tested +bool IsPositionPresent(const IOAttributes& attr, const core::type::Type* ty) { + if (auto* ty_struct = ty->As()) { + for (const auto* mem : ty_struct->Members()) { + if (mem->Attributes().builtin == BuiltinValue::kPosition) { + return true; + } + } + return false; + } + + return attr.builtin == BuiltinValue::kPosition; +} + +/// Helper that walks the members of a struct, called from WalkTypeAndMembers and its helpers +/// @param ctx a context object to pass to the impl function +/// @param str the struct to walk the members of +/// @param impl an impl function to be run, see WalkTypeAndMembers for details +template +void WalkStructMembers(CTX& ctx, const core::type::Struct* str, IMPL&& impl) { + for (auto* member : str->Members()) { + WalkTypeAndMembers(ctx, member->Type(), member->Attributes(), impl); + } +} + +/// Helper that walks an array's element type, called from WalkTypeAndMembers and its helpers +/// @param ctx a context object to pass to the impl function +/// @param arr the array to walk the element type of +/// @param impl an impl function to be run, see WalkTypeAndMembers for details +template +void WalkArrayElements(CTX& ctx, const core::type::Array* arr, IMPL&& impl) { + tint::Switch( + arr->ElemType(), [&](const core::type::Struct* s) { WalkStructMembers(ctx, s, impl); }, + [&](const core::type::Array* a) { WalkArrayElements(ctx, a, impl); }); +} + +/// Helper for walking a type that maybe a struct, calling an impl function for the type and each of +/// its members. +/// @param ctx a context object to pass to the implementation function +/// @param type the type to walk +/// @param attr the attributes for @p type +/// @param impl a function with the signature `void(const core::type::Type*, const IOAttributes&, +/// CTX&)` that is called for each type. +template +void WalkTypeAndMembers(CTX& ctx, + const core::type::Type* type, + const IOAttributes& attr, + IMPL&& impl) { + impl(ctx, type, attr); + tint::Switch( + type, [&](const core::type::Struct* s) { WalkStructMembers(ctx, s, impl); }, + [&](const core::type::Array* a) { WalkArrayElements(ctx, a, impl); }); +} + +/// The IO direction of an operation. +enum class IODirection : uint8_t { kInput, kOutput, kResource }; + +/// @returns a human-readable string for an IODirection +std::string_view ToString(IODirection value) { + switch (value) { + case IODirection::kInput: + return "input"; + case IODirection::kOutput: + return "output"; + case IODirection::kResource: + return "resource"; + } + TINT_ICE() << "Unknown enum passed to ToString(IODirection)"; +} + +IODirection IODirectionFor(AddressSpace address_space) { + switch (address_space) { + case AddressSpace::kIn: + return IODirection::kInput; + case AddressSpace::kOut: + return IODirection::kOutput; + case AddressSpace::kHandle: + return IODirection::kResource; + default: + TINT_ICE() << "Unexpected address_space '" << ToString(address_space) + << "' passed to IODirectionFrom()"; + } +} + +/// The kind of shader IO being validated. +enum class ShaderIOKind : uint8_t { + kInputParam, + kResultValue, + kModuleScopeVar, +}; + +/// @returns text describing the shader IO kind for error logging +std::string ToString(ShaderIOKind value) { + switch (value) { + case ShaderIOKind::kInputParam: + return "input param"; + case ShaderIOKind::kResultValue: + return "return value"; + case ShaderIOKind::kModuleScopeVar: + return "module scope variable"; + } + TINT_ICE() << "Unknown enum passed to ToString(ShaderIOKind)"; +} + +/// How an attribute is being used, a tuple of the shader stage and IO direction +enum class IOAttributeUsage : uint8_t { + kComputeInputUsage, + kComputeOutputUsage, + kComputeResourceUsage, + kFragmentInputUsage, + kFragmentOutputUsage, + kFragmentResourceUsage, + kVertexInputUsage, + kVertexOutputUsage, + kVertexResourceUsage, + kUndefinedUsage, +}; + +/// @returns a human-readable string for an IOAttributeUsage +std::string ToString(IOAttributeUsage value) { + switch (value) { + case IOAttributeUsage::kComputeInputUsage: + return "compute shader input"; + case IOAttributeUsage::kComputeOutputUsage: + return "compute shader output"; + case IOAttributeUsage::kComputeResourceUsage: + return "compute shader resource"; + case IOAttributeUsage::kFragmentInputUsage: + return "fragment shader input"; + case IOAttributeUsage::kFragmentOutputUsage: + return "fragment shader output"; + case IOAttributeUsage::kFragmentResourceUsage: + return "fragment shader resource"; + case IOAttributeUsage::kVertexInputUsage: + return "vertex shader input"; + case IOAttributeUsage::kVertexOutputUsage: + return "vertex shader output"; + case IOAttributeUsage::kVertexResourceUsage: + return "vertex shader resourcee"; + case IOAttributeUsage::kUndefinedUsage: + return "non-entry point usage"; + } + TINT_ICE() << "Unknown enum passed to ToString(IOAttribute)"; +} + +/// @returns the IOAttributeUsage for a given Function::PipelineStage + IODirection tuple +IOAttributeUsage IOAttributeUsageFor(Function::PipelineStage stage, IODirection direction) { + switch (stage) { + case Function::PipelineStage::kCompute: + switch (direction) { + case IODirection::kInput: + return IOAttributeUsage::kComputeInputUsage; + case IODirection::kOutput: + return IOAttributeUsage::kComputeOutputUsage; + case IODirection::kResource: + return IOAttributeUsage::kComputeResourceUsage; + } + case Function::PipelineStage::kFragment: + switch (direction) { + case IODirection::kInput: + return IOAttributeUsage::kFragmentInputUsage; + case IODirection::kOutput: + return IOAttributeUsage::kFragmentOutputUsage; + case IODirection::kResource: + return IOAttributeUsage::kFragmentResourceUsage; + } + case Function::PipelineStage::kVertex: + switch (direction) { + case IODirection::kInput: + return IOAttributeUsage::kVertexInputUsage; + case IODirection::kOutput: + return IOAttributeUsage::kVertexOutputUsage; + case IODirection::kResource: + return IOAttributeUsage::kVertexResourceUsage; + } + case Function::PipelineStage::kUndefined: + return IOAttributeUsage::kUndefinedUsage; + } + TINT_ICE() << "Unknown IOAttribute usage " << ToString(direction) << " for a " + << ToString(stage) << " entry point"; +} + +/// @returns the Function::PipelineStage for an IOAttributeUsage +[[maybe_unused]] Function::PipelineStage PipelineStageFor(IOAttributeUsage usage) { + switch (usage) { + case IOAttributeUsage::kComputeInputUsage: + case IOAttributeUsage::kComputeOutputUsage: + case IOAttributeUsage::kComputeResourceUsage: + return Function::PipelineStage::kCompute; + case IOAttributeUsage::kFragmentInputUsage: + case IOAttributeUsage::kFragmentOutputUsage: + case IOAttributeUsage::kFragmentResourceUsage: + return Function::PipelineStage::kFragment; + case IOAttributeUsage::kVertexInputUsage: + case IOAttributeUsage::kVertexOutputUsage: + case IOAttributeUsage::kVertexResourceUsage: + return Function::PipelineStage::kVertex; + case IOAttributeUsage::kUndefinedUsage: + return Function::PipelineStage::kUndefined; + } + TINT_ICE() << "Unknown IOAttribute usage " << ToString(usage); +} + +/// @returns the IODirection for an IOAttributeUsage +[[maybe_unused]] IODirection IODirectionFor(IOAttributeUsage usage) { + switch (usage) { + case IOAttributeUsage::kComputeInputUsage: + case IOAttributeUsage::kFragmentInputUsage: + case IOAttributeUsage::kVertexInputUsage: + return IODirection::kInput; + case IOAttributeUsage::kComputeOutputUsage: + case IOAttributeUsage::kFragmentOutputUsage: + case IOAttributeUsage::kVertexOutputUsage: + return IODirection::kOutput; + case IOAttributeUsage::kComputeResourceUsage: + case IOAttributeUsage::kFragmentResourceUsage: + case IOAttributeUsage::kVertexResourceUsage: + case IOAttributeUsage::kUndefinedUsage: + return IODirection::kResource; // Technically it could also be a kInput or kOutput, but + // no validation depends on differentiate between these + // cases currently. + } + TINT_ICE() << "Unknown IOAttribute usage " << ToString(usage); +} + +/// A BuiltInChecker is the interface used to check that a usage of a builtin attribute meets the +/// basic spec rules, i.e. correct shader stage, data type, and IO direction. +/// It does not test more sophisticated rules like location and builtins being mutually exclusive or +/// that the correct capabilities are enabled. +struct BuiltInChecker { + /// What combination of stage and IO direction is this builtin legal for + EnumSet valid_usages; + + /// What values for depth_mode are valid for this builtin. + /// Currently, kUndefined is the only valid option for non-frag_depth + EnumSet valid_depth_modes = + EnumSet{BuiltinDepthMode::kUndefined}; + + /// Implements logic for checking if the given type is valid or not. Is not a data entry (i.e. a + /// type or set of types), because types are part of the IR module and created at runtime. + using TypeCheckFn = bool(const core::type::Type* type, const Capabilities& cap); + + /// @see #TypeCheckFn + TypeCheckFn* const type_check; + + /// Message for logging if the type check fails. Cannot be easily generated at runtime, because + /// the type check is a function, not just a data entry. + const char* type_error; +}; + +constexpr BuiltInChecker kPointSizeChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexOutputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be a f32", +}; + +/// returns true if the number of elements in @p ty is valid for use in clip_distances without +/// Capability::kAllowClipDistancesOnF32. +constexpr auto ClipDistancesElementsCheck = [](const core::type::Type* ty) -> bool { + const auto elems = ty->Elements(); + return elems.type && elems.type->Is() && elems.count <= 8; +}; + +constexpr BuiltInChecker kClipDistancesChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexOutputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is() && ClipDistancesElementsCheck(ty); + }, + .type_error = "must be an array, where N <= 8", +}; + +constexpr BuiltInChecker kClipDistancesAllowF32ScalarAndVectorChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexOutputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ((ty->Is() || ty->Is()) && + ClipDistancesElementsCheck(ty)) || + ty->Is(); + }, + .type_error = "must be a f32 or either a vecN or an array, where N <= 8", +}; + +constexpr BuiltInChecker kCullDistanceChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexOutputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is() && ty->DeepestElement()->Is(); + }, + .type_error = "must be an array of f32", +}; + +constexpr BuiltInChecker kFragDepthChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentOutputUsage}, + .valid_depth_modes = + EnumSet{BuiltinDepthMode::kUndefined, BuiltinDepthMode::kAny, + BuiltinDepthMode::kGreater, BuiltinDepthMode::kLess}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be a f32", +}; + +constexpr BuiltInChecker kFrontFacingChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be a bool", +}; + +constexpr BuiltInChecker kGlobalInvocationIdChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsUnsignedIntegerVector() && ty->Elements().count == 3; + }, + .type_error = "must be an vec3", +}; + +constexpr BuiltInChecker kInstanceIndexChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kLocalInvocationIdChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsUnsignedIntegerVector() && ty->Elements().count == 3; + }, + .type_error = "must be an vec3", +}; + +constexpr BuiltInChecker kLocalInvocationIndexChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kNumSubgroupsChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kNumWorkgroupsChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsUnsignedIntegerVector() && ty->Elements().count == 3; + }, + .type_error = "must be an vec3", +}; + +constexpr BuiltInChecker kPositionChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexOutputUsage, + IOAttributeUsage::kFragmentInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsFloatVector() && ty->Elements().count == 4; + }, + .type_error = "must be an vec4", +}; + +constexpr BuiltInChecker kSampleIndexChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kSampleMaskChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage, + IOAttributeUsage::kFragmentOutputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kSubgroupIdChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kSubgroupInvocationIdChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage, + IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kSubgroupSizeChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage, + IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kVertexIndexChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kVertexInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kWorkgroupIdChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kComputeInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsUnsignedIntegerVector() && ty->Elements().count == 3; + }, + .type_error = "must be an vec3", +}; + +constexpr BuiltInChecker kPrimitiveIndexChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->Is(); + }, + .type_error = "must be an u32", +}; + +constexpr BuiltInChecker kBarycentricCoordChecker{ + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage}, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsFloatVector() && ty->Elements().count == 3; + }, + .type_error = "must be an vec3", +}; + +/// @returns an appropriate BuiltInCheck for @p builtin, ICEs when one isn't defined +const BuiltInChecker& BuiltinCheckerFor(BuiltinValue builtin, const Capabilities& capabilities) { + switch (builtin) { + case BuiltinValue::kPointSize: + return kPointSizeChecker; + case BuiltinValue::kClipDistances: + if (capabilities.Contains(Capability::kAllowClipDistancesOnF32ScalarAndVector)) { + return kClipDistancesAllowF32ScalarAndVectorChecker; + } + return kClipDistancesChecker; + case BuiltinValue::kCullDistance: + return kCullDistanceChecker; + case BuiltinValue::kFragDepth: + return kFragDepthChecker; + case BuiltinValue::kFrontFacing: + return kFrontFacingChecker; + case BuiltinValue::kGlobalInvocationId: + return kGlobalInvocationIdChecker; + case BuiltinValue::kInstanceIndex: + return kInstanceIndexChecker; + case BuiltinValue::kLocalInvocationId: + return kLocalInvocationIdChecker; + case BuiltinValue::kLocalInvocationIndex: + return kLocalInvocationIndexChecker; + case BuiltinValue::kNumSubgroups: + return kNumSubgroupsChecker; + case BuiltinValue::kNumWorkgroups: + return kNumWorkgroupsChecker; + case BuiltinValue::kPosition: + return kPositionChecker; + case BuiltinValue::kSampleIndex: + return kSampleIndexChecker; + case BuiltinValue::kSampleMask: + return kSampleMaskChecker; + case BuiltinValue::kSubgroupId: + return kSubgroupIdChecker; + case BuiltinValue::kSubgroupInvocationId: + return kSubgroupInvocationIdChecker; + case BuiltinValue::kSubgroupSize: + return kSubgroupSizeChecker; + case BuiltinValue::kVertexIndex: + return kVertexIndexChecker; + case BuiltinValue::kWorkgroupId: + return kWorkgroupIdChecker; + case BuiltinValue::kPrimitiveIndex: + return kPrimitiveIndexChecker; + case BuiltinValue::kBarycentricCoord: + return kBarycentricCoordChecker; + default: + TINT_ICE() << builtin << " is does not have a checker defined for it"; + } +} + +/// IOAttributeChecker is the interface used to check that a usage of an IO attribute +/// meets the spec rules for a given context. +struct IOAttributeChecker { + /// What kinda of IO attribute is being checked + IOAttributeKind kind; + + /// What combination of stage and IO direction is this attribute legal for. + EnumSet valid_usages; + + /// What type of shader IO values is this attribute legal for. + EnumSet valid_io_kinds; + + /// Implements the validation logic for a specific attribute. + using CheckFn = Result(const core::type::Type* ty, + const IOAttributes& attr, + const Capabilities& cap, + IOAttributeUsage usage); + + /// The validation function. + CheckFn* const check; + + /// Implements logic for checking if the given type is valid or not. Is not a data entry (i.e. a + /// type or set of types), because types are part of the IR module and created at runtime. + using TypeCheckFn = bool(const core::type::Type* type, const Capabilities& cap); + + /// @see #TypeCheckFn + TypeCheckFn* const type_check; + + /// Message for logging if the type check fails. Cannot be easily generated at runtime, because + /// the type check is a function, not just a data entry. + const char* type_error; +}; + +constexpr IOAttributeChecker kInvariantChecker{ + .kind = IOAttributeKind::kInvariant, + .valid_usages = EnumSet{IOAttributeUsage::kVertexOutputUsage, + IOAttributeUsage::kFragmentInputUsage}, + .valid_io_kinds = EnumSet{ShaderIOKind::kInputParam, ShaderIOKind::kResultValue, + ShaderIOKind::kModuleScopeVar}, + .check = [](const core::type::Type*, + const IOAttributes& attr, + const Capabilities&, + IOAttributeUsage) -> Result { + if (attr.builtin != BuiltinValue::kPosition) { + return {"invariant can only decorate a value if it is also decorated with position"}; + } + return Success; + }, + .type_check = kPositionChecker.type_check, + .type_error = kPositionChecker.type_error, +}; + +constexpr IOAttributeChecker kBuiltinChecker{ + .kind = IOAttributeKind::kBuiltin, + .valid_usages = + EnumSet{ + IOAttributeUsage::kComputeInputUsage, + IOAttributeUsage::kComputeOutputUsage, + IOAttributeUsage::kFragmentInputUsage, + IOAttributeUsage::kFragmentOutputUsage, + IOAttributeUsage::kVertexInputUsage, + IOAttributeUsage::kVertexOutputUsage, + }, + .valid_io_kinds = EnumSet{ShaderIOKind::kInputParam, ShaderIOKind::kResultValue, + ShaderIOKind::kModuleScopeVar}, + .check = [](const core::type::Type* ty, + const IOAttributes& attr, + const Capabilities& cap, + IOAttributeUsage usage) -> Result { + if (!attr.builtin.has_value()) { + return Success; + } + + const auto builtin = attr.builtin.value(); + const auto& checker = BuiltinCheckerFor(builtin, cap); + if (usage != IOAttributeUsage::kUndefinedUsage && !checker.valid_usages.Contains(usage)) { + std::stringstream msg; + msg << ToString(builtin) << " cannot be used on a " << ToString(usage) << ". "; + if (checker.valid_usages.Size() == 1) { + const auto v = *checker.valid_usages.begin(); + msg << "It can only be used on a " << ToString(v) << "."; + } else { + msg << "It can only be used on one of " << ToString(checker.valid_usages); + } + return msg.str(); + } + + if (!checker.type_check(ty, cap)) { + std::stringstream msg; + msg << ToString(builtin) << " " << checker.type_error; + return msg.str(); + } + + const auto depth_mode = attr.depth_mode.value_or(BuiltinDepthMode::kUndefined); + if (!checker.valid_depth_modes.Contains(depth_mode)) { + std::stringstream msg; + msg << ToString(builtin) << " cannot have a depth mode of " << ToString(depth_mode) + << ". "; + if (checker.valid_depth_modes.Size() == 1) { + const auto v = *checker.valid_depth_modes.begin(); + msg << "It can only be " << ToString(v) << "."; + } else { + msg << "It must be one of " << ToString(checker.valid_depth_modes); + } + return msg.str(); + } + + if (builtin == BuiltinValue::kPointSize && + !cap.Contains(Capability::kAllowPointSizeBuiltin)) { + return std::string{"use of point_size builtin requires kAllowPointSizeBuiltin"}; + } + + return Success; + }, + .type_check = [](const core::type::Type*, const Capabilities&) -> bool { return true; }, + .type_error = nullptr, +}; + +constexpr IOAttributeChecker kColorChecker{ + .kind = IOAttributeKind::kColor, + .valid_usages = EnumSet{IOAttributeUsage::kFragmentInputUsage}, + .valid_io_kinds = + EnumSet{ShaderIOKind::kInputParam, ShaderIOKind::kModuleScopeVar}, + .check = [](const core::type::Type*, const IOAttributes&, const Capabilities&, IOAttributeUsage) + -> Result { return Success; }, + .type_check = [](const core::type::Type* ty, const Capabilities&) -> bool { + return ty->IsNumericScalarOrVector(); + }, + .type_error = "must be a scalar or vector", +}; + +constexpr IOAttributeChecker kInputAttachmentIndexChecker{ + .kind = IOAttributeKind::kInputAttachmentIndex, + .valid_usages = EnumSet{IOAttributeUsage::kFragmentResourceUsage}, + .valid_io_kinds = EnumSet{ShaderIOKind::kModuleScopeVar}, + .check = [](const core::type::Type*, const IOAttributes&, const Capabilities&, IOAttributeUsage) + -> Result { return Success; }, + .type_check = [](const core::type::Type* ty, const Capabilities& cap) -> bool { + return cap.Contains(Capability::kAllowAnyInputAttachmentIndexType) || + ty->Is(); + }, + .type_error = "must be an input_attachment", +}; + +constexpr IOAttributeChecker kDepthModeChecker{ + .kind = IOAttributeKind::kDepthMode, + .valid_usages = kBuiltinChecker.valid_usages, + .valid_io_kinds = kBuiltinChecker.valid_io_kinds, + // kBuiltInChecker does the checking of the depth_mode value for the specific builtin. + .check = [](const core::type::Type*, + const IOAttributes& attr, + const Capabilities&, + IOAttributeUsage) -> Result { + if (!attr.builtin.has_value()) { + return {"cannot have a depth_mode without a builtin"}; + } + return Success; + }, + .type_check = [](const core::type::Type*, const Capabilities&) -> bool { return true; }, + .type_error = nullptr, +}; + +// kBlendSrcChecker, kLocationChecker, kInterpolationChecker, and kBindingPointChecker are +// intentionally not implemented + +/// @returns all the appropriate IOAttributeCheckers for @p attr +Vector IOAttributeCheckersFor(const IOAttributes& attr, + bool skip_builtin) { + Vector checkers{}; + if (attr.invariant) { + checkers.Push(&kInvariantChecker); + } + if (!skip_builtin && attr.builtin.has_value()) { + checkers.Push(&kBuiltinChecker); + } + if (attr.color.has_value()) { + checkers.Push(&kColorChecker); + } + if (attr.input_attachment_index.has_value()) { + checkers.Push(&kInputAttachmentIndexChecker); + } + if (attr.depth_mode.has_value()) { + checkers.Push(&kDepthModeChecker); + } + + // attr.blend_src, attr.location, attr.interpolation, and attr.binding_point are intentionally + // skipped, because their rules are not amenable to implementation via IOAttributeChecker. + return checkers; +} + +/// Annotations that can be associated with a value that are used for shader IO, +/// e.g. binding_points, @location, being in workgroup address space, etc. +/// These are a subset of IOAttributes. +enum class IOAnnotation : uint8_t { + /// @group + @binding + kBindingPoint, + /// @location + kLocation, + /// @builtin(...) + kBuiltin, + /// Pointer to Workgroup address space + kWorkgroup, + /// @color + kColor, +}; + +/// @returns text describing the annotation for error logging +std::string ToString(IOAnnotation value) { + switch (value) { + case IOAnnotation::kBindingPoint: + return "@group + @binding"; + case IOAnnotation::kLocation: + return "@location"; + case IOAnnotation::kBuiltin: + return "built-in"; + case IOAnnotation::kWorkgroup: + return ""; + case IOAnnotation::kColor: + return "@color"; + } + TINT_ICE() << "Unknown enum passed to ToString(IOAnnotation)"; +} + +/// Adds appropriate entries to annotations, based on what values are present in attributes +/// @param annotations the set to updated +/// @param attr the attributes to be examined +/// @returns Success if none of the values being added where already present, otherwise returns the +/// first non-unique value as a Failure +Result AddIOAnnotationsFromIOAttributes( + EnumSet& annotations, + const IOAttributes& attr) { + if (attr.location.has_value()) { + if (annotations.Contains(IOAnnotation::kLocation)) { + return IOAnnotation::kLocation; + } + annotations.Add(IOAnnotation::kLocation); + } + + if (attr.builtin.has_value()) { + if (annotations.Contains(IOAnnotation::kBuiltin)) { + return IOAnnotation::kBuiltin; + } + annotations.Add(IOAnnotation::kBuiltin); + } + + if (attr.color.has_value()) { + if (annotations.Contains(IOAnnotation::kColor)) { + return IOAnnotation::kColor; + } + annotations.Add(IOAnnotation::kColor); + } + + return Success; +} + +/// State for validating blend_src attributes shared across multiple passes within the same entry +/// point. +struct BlendSrcContext { + Function::PipelineStage stage; + Hashmap locations; + Hashset blend_srcs; + const core::type::Type* blend_src_type = nullptr; + IODirection dir; +}; + +/// State for validating IO attributes that needs to shared across impl invocations within the same +/// entry point. +struct IOAttributeContext { + Hashmap input_builtins; + Hashmap output_builtins; +}; + +/// The core IR validator. +class Validator { + public: + /// Create a core validator + /// @param mod the module to be validated + /// @param capabilities the optional capabilities that are allowed + explicit Validator(const Module& mod, Capabilities capabilities); + + /// Destructor + ~Validator(); + + /// Runs the validator over the module provided during construction + /// @returns success or failure + Result Run(); + + private: + /// Runs validation to confirm the structural soundness of the module. + /// Also runs any validation that is not dependent on the entire module being + /// sound and sets up data structures for later checks. + void RunStructuralSoundnessChecks(); + + /// Checks that there is no direct or indirect recursion. + /// Depends on CheckStructuralSoundness() having previously been run. + void CheckForRecursion(); + + /// Checks that there are no orphaned instructions + /// Depends on CheckStructuralSoundness() having previously been run + void CheckForOrphanedInstructions(); + + /// Checks that entry points do not use instructions that are not supported by their stage. + /// Depends on CheckStructuralSoundness() having previously been run + void CheckStageRestrictedInstructions(); + + /// @returns the IR disassembly, performing a disassemble if this is the first call. + ir::Disassembler& Disassemble(); + + /// Adds an error for the @p inst and highlights the instruction in the disassembly + /// @param inst the instruction + /// @returns the diagnostic + diag::Diagnostic& AddError(const Instruction* inst); + + /// Adds an error for the @p inst operand at @p idx and highlights the operand in the + /// disassembly + /// @param inst the instruction + /// @param idx the operand index + /// @returns the diagnostic + diag::Diagnostic& AddError(const Instruction* inst, size_t idx); + + /// Adds an error for the @p inst result at @p idx and highlgihts the result in the disassembly + /// @param inst the instruction + /// @param idx the result index + /// @returns the diagnostic + diag::Diagnostic& AddResultError(const Instruction* inst, size_t idx); + + /// Adds an error for the @p block and highlights the block header in the disassembly + /// @param blk the block + /// @returns the diagnostic + diag::Diagnostic& AddError(const Block* blk); + + /// Adds an error for the @p param and highlights the parameter in the disassembly + /// @param param the parameter + /// @returns the diagnostic + diag::Diagnostic& AddError(const BlockParam* param); + + /// Adds an error for the @p func and highlights the function in the disassembly + /// @param func the function + /// @returns the diagnostic + diag::Diagnostic& AddError(const Function* func); + + /// Adds an error for the @p param and highlights the parameter in the disassembly + /// @param param the parameter + /// @returns the diagnostic + diag::Diagnostic& AddError(const FunctionParam* param); + + /// Adds an error for the castable base @p base and highlights it in the disassembly + /// @param base the declaration to add an error for + /// @returns the diagnostic + diag::Diagnostic& AddError(const CastableBase* base); + + /// Adds an error the @p block and highlights the block header in the disassembly + /// @param src the source lines to highlight + /// @returns the diagnostic + diag::Diagnostic& AddError(Source src); + + /// Adds a note to @p inst and highlights the instruction in the disassembly + /// @param inst the instruction + diag::Diagnostic& AddNote(const Instruction* inst); + + /// Adds a note to @p func and highlights the function in the disassembly + /// @param func the function + diag::Diagnostic& AddNote(const Function* func); + + /// Adds a note to @p inst for operand @p idx and highlights the operand in the disassembly + /// @param inst the instruction + /// @param idx the operand index + diag::Diagnostic& AddOperandNote(const Instruction* inst, size_t idx); + + /// Adds a note to @p inst for result @p idx and highlights the result in the disassembly + /// @param inst the instruction + /// @param idx the result index + diag::Diagnostic& AddResultNote(const Instruction* inst, size_t idx); + + /// Adds a note to @p blk and highlights the block in the disassembly + /// @param blk the block + diag::Diagnostic& AddNote(const Block* blk); + + /// Adds a note to the diagnostics + /// @param src the source lines to highlight + diag::Diagnostic& AddNote(Source src = {}); + + /// Adds a note to the diagnostics highlighting where the value instruction or block is + /// declared, if it has a source location. + /// @param decl the value instruction or block + void AddDeclarationNote(const CastableBase* decl); + + /// Adds a note to the diagnostics highlighting where the block is declared, if it has a source + /// location. + /// @param block the block + void AddDeclarationNote(const Block* block); + + /// Adds a note to the diagnostics highlighting where the block parameter is declared, if it + /// has a source location. + /// @param param the block parameter + void AddDeclarationNote(const BlockParam* param); + + /// Adds a note to the diagnostics highlighting where the function is declared, if it has a + /// source location. + /// @param fn the function + void AddDeclarationNote(const Function* fn); + + /// Adds a note to the diagnostics highlighting where the function parameter is declared, if it + /// has a source location. + /// @param param the function parameter + void AddDeclarationNote(const FunctionParam* param); + + /// Adds a note to the diagnostics highlighting where the instruction is declared, if it has a + /// source location. + /// @param inst the inst + void AddDeclarationNote(const Instruction* inst); + + /// Adds a note to the diagnostics highlighting where instruction result was declared, if it has + /// a source location. + /// @param res the res + void AddDeclarationNote(const InstructionResult* res); + + /// @param decl the type, value, instruction or block to get the name for + /// @returns the styled name for the given value, instruction or block + StyledText NameOf(const CastableBase* decl); + + // @param ty the type to get the name for + /// @returns the styled name for the given type + StyledText NameOf(const core::type::Type* ty); + + /// @param v the value to get the name for + /// @returns the styled name for the given value + StyledText NameOf(const Value* v); + + /// @param inst the instruction to get the name for + /// @returns the styled name for the given instruction + StyledText NameOf(const Instruction* inst); + + /// @param block the block to get the name for + /// @returns the styled name for the given block + StyledText NameOf(const Block* block); + + /// Checks the given result is not null and its type is not null + /// @param inst the instruction + /// @param idx the result index + /// @returns true if the result is not null + bool CheckResult(const Instruction* inst, size_t idx); + + /// Checks the results (and their types) for @p inst are not null. If count is specified then + /// number of results is checked to be exact. + /// @param inst the instruction + /// @param count the number of results to check + /// @returns true if the results count is as expected and none are null + bool CheckResults(const ir::Instruction* inst, std::optional count); + + /// Checks the given operand is not null and its type is not null + /// @param inst the instruction + /// @param idx the operand index + /// @returns true if the operand is not null + bool CheckOperand(const Instruction* inst, size_t idx); + + /// Checks the number of operands provided to @p inst and that none of them are null. Also + /// checks that the types for the operands are not null + /// @param inst the instruction + /// @param min_count the minimum number of operands to expect + /// @param max_count the maximum number of operands to expect, if not set, than only the minimum + /// number is checked. + /// @returns true if the number of operands is in the expected range and none are null + bool CheckOperands(const ir::Instruction* inst, + size_t min_count, + std::optional max_count); + + /// Checks the operands (and their types) for @p inst are not null. If count is specified then + /// number of operands is checked to be exact. + /// @param inst the instruction + /// @param count the number of operands to check + /// @returns true if the operands count is as expected and none are null + bool CheckOperands(const ir::Instruction* inst, std::optional count); + + /// Checks the number of results for @p inst are exactly equal to @p num_results and the number + /// of operands is correctly. Both results and operands are confirmed to be non-null. + /// @param inst the instruction + /// @param num_results expected number of results for the instruction + /// @param min_operands the minimum number of operands to expect + /// @param max_operands the maximum number of operands to expect, if not set, than only the + /// minimum number is checked. + /// @returns true if the result and operand counts are as expected and none are null + bool CheckResultsAndOperandRange(const ir::Instruction* inst, + size_t num_results, + size_t min_operands, + std::optional max_operands); + + /// Checks the number of results and operands for @p inst are exactly equal to num_results + /// and num_operands, respectively, and that none of them are null. + /// @param inst the instruction + /// @param num_results expected number of results for the instruction + /// @param num_operands expected number of operands for the instruction + /// @returns true if the result and operand counts are as expected and none are null + bool CheckResultsAndOperands(const ir::Instruction* inst, + size_t num_results, + size_t num_operands); + + /// Checks that @p type is allowed by the spec, and does not use any types that are prohibited + /// by the target capabilities. + /// @param type the type + /// @param diag a function that creates an error diagnostic for the source of the type + /// @param ignore_caps a set of capabilities to ignore for this check + void CheckType(const core::type::Type* type, + std::function diag, + Capabilities ignore_caps = {}); + + /// Validates the root block + /// @param blk the block + void CheckRootBlock(const Block* blk); + + /// Validates the given instruction is only used in the root block. + /// @param inst the instruction + void CheckOnlyUsedInRootBlock(const Instruction* inst); + + /// Validates the given function + /// @param func the function to validate + void CheckFunction(const Function* func); + + /// Validates the workgroup_size attribute for a given function + /// @param func the function to validate + void CheckWorkgroupSize(const Function* func); + + /// Validates the subgroup_size attribute for a given function + /// @param func the function to validate + void CheckSubgroupSize(const Function* func); + + /// Validates the specific function as a vertex entry point + /// @param ep the function to validate + void CheckPositionPresentForVertexOutput(const Function* ep); + + /// Validates the spec rules for IO attribute usage for a function. + /// @param func the function to validate + void ValidateIOAttributes(const Function* func); + + /// Implementation for validating the spec rules for IO attribute usage. + /// @param ctx context object shared between the multiple invocations of this per entry point + /// @param msg_anchor the object to anchor the error message to + /// @param ty the data type being decorated by the attributes + /// @param attr the attributes to test + /// @param stage the shader stage the builtin is being used + /// @param dir is value being used as an input or an output + /// @param io_kind is the type of shader IO object the attribute is attached to + void ValidateIOAttributesImpl(IOAttributeContext& ctx, + const CastableBase* msg_anchor, + const core::type::Type* ty, + const IOAttributes& attr, + Function::PipelineStage stage, + IODirection dir, + ShaderIOKind io_kind); + + /// Validates that a type is a bool only if it is decorated with @builtin(front_facing). + /// @param msg_anchor where to attach errors to + /// @param attr the IO attributes + /// @param ty the type + /// @param err error message to log when check fails + void CheckFrontFacingIfBool(const CastableBase* msg_anchor, + const IOAttributes& attr, + const core::type::Type* ty, + const std::string& err); + + /// Validates that a type is not a bool. + /// @param msg_anchor where to attach errors to + /// @param ty the type + /// @param err error message to log when check fails + void CheckNotBool(const CastableBase* msg_anchor, + const core::type::Type* ty, + const std::string& err); + + /// Validates the given instruction + /// @param inst the instruction to validate + void CheckInstruction(const Instruction* inst); + + /// Validates the given override + /// @param o the override to validate + void CheckOverride(const Override* o); + + /// Validates the given var + /// @param var the var to validate + void CheckVar(const Var* var); + + /// Validates annotations related to shader IO + /// @param msg_anchor where to attach errors to + /// @param ty type of the value under test + /// @param binding_point the binding information associated with the value + /// @param attr IO attributes associated with the values + /// @param kind the kind Shader IO being performed + void ValidateShaderIOAnnotations(const CastableBase* msg_anchor, + const core::type::Type* ty, + const std::optional& binding_point, + const IOAttributes& attr, + ShaderIOKind kind); + + /// Validates the blend_src attribute for a given type, responsible for traversal of inner types + /// and checking rules that span across a multiple attribute instances. + /// @param ctx the blend_src context. + /// @param target the object that has the struct ty. + /// @param ty the ty to validate. + /// @param attr the IO attributes for the object. + void CheckBlendSrc(BlendSrcContext& ctx, + const CastableBase* target, + const core::type::Type* ty, + const IOAttributes& attr); + + /// Validates the details of a single attribute instance. + /// @param ctx the blend_src context. + /// @param target the object that has the struct type. + /// @param ty the type to validate. + /// @param attr the IO attributes for the object. + void CheckBlendSrcImpl(BlendSrcContext& ctx, + const CastableBase* target, + const core::type::Type* ty, + const IOAttributes& attr); + + /// Validates location attributes on entry point IO. + /// @param locations the map of locations used so far for the current IO direction. + /// @param target the object that has the location attribute. + /// @param attr the IO attributes for the object. + /// @param stage the pipeline stage of the entry point. + /// @param type the type of the IO object. + /// @param dir the IO direction (input or output). + void CheckLocation(Hashmap& locations, + const CastableBase* target, + const IOAttributes& attr, + Function::PipelineStage stage, + const core::type::Type* type, + IODirection dir); + + /// Validates interpolation attributes on entry point IO. + /// @param anchor where to attach error messages to. + /// @param ty the type of the IO object + /// @param attr the IO attributes of the object. + void CheckInterpolation(const CastableBase* anchor, + const core::type::Type* ty, + const IOAttributes& attr); + + /// Validates binding_point attributes on entry point IO. + /// @param anchor where to attach error messages to. + /// @param ty the type of the IO object + /// @param attr the IO attributes of the object + /// @param io_kind the type of shader IO object binding point is attached to + void CheckBindingPoint(const CastableBase* anchor, + const core::type::Type* ty, + const IOAttributes& attr, + const ShaderIOKind& io_kind); + + /// Validates the given let + /// @param l the let to validate + void CheckLet(const Let* l); + + /// Validates the given call + /// @param call the call to validate + void CheckCall(const Call* call); + + /// Validates the given bitcast + /// @param bitcast the bitcast to validate + void CheckBitcast(const Bitcast* bitcast); + + /// Validates that there exists the required bitcast override + /// @param bitcast the bitcast to validate types of + void CheckBitcastTypes(const Bitcast* bitcast); + + /// Validates the given builtin call + /// @param call the call to validate + void CheckBuiltinCall(const BuiltinCall* call); + + /// Validates a core builtin call + /// @param call the call to validate + /// @param overload the call intrinsic overload + void CheckCoreBuiltinCall(const CoreBuiltinCall* call, + const core::intrinsic::Overload& overload); + + /// Validates the given member builtin call + /// @param call the member call to validate + void CheckMemberBuiltinCall(const MemberBuiltinCall* call); + + /// Validates the given construct + /// @param construct the construct to validate + void CheckConstruct(const Construct* construct); + + /// Validates the given convert + /// @param convert the convert to validate + void CheckConvert(const Convert* convert); + + /// Validates the given discard + /// @note Does not validate that the discard is in a fragment shader, that + /// needs to be handled later in the validation. + /// @param discard the discard to validate + void CheckDiscard(const Discard* discard); + + /// Validates the given user call + /// @param call the call to validate + void CheckUserCall(const UserCall* call); + + /// Validates the given access + /// @param a the access to validate + void CheckAccess(const Access* a); + + /// Validates the given binary + /// @param b the binary to validate + void CheckBinary(const Binary* b); + + /// Validates the given unary + /// @param u the unary to validate + void CheckUnary(const Unary* u); + + /// Validates the given if + /// @param if_ the if to validate + void CheckIf(const If* if_); + + /// Validates the given loop + /// @param l the loop to validate + void CheckLoop(const Loop* l); + + /// Validates the loop body block + /// @param l the loop to validate + void CheckLoopBody(const Loop* l); + + /// Validates the loop continuing block + /// @param l the loop to validate + void CheckLoopContinuing(const Loop* l); + + /// Validates the given switch + /// @param s the switch to validate + void CheckSwitch(const Switch* s); + + /// Validates the given swizzle + /// @param s the swizzle to validate + void CheckSwizzle(const Swizzle* s); + + /// Validates the given terminator + /// @param b the terminator to validate + void CheckTerminator(const Terminator* b); + + /// Validates the break if instruction + /// @param b the break if to validate + void CheckBreakIf(const BreakIf* b); + + /// Validates the continue instruction + /// @param c the continue to validate + void CheckContinue(const Continue* c); + + /// Validates the given exit + /// @param e the exit to validate + void CheckExit(const Exit* e); + + /// Validates the next iteration instruction + /// @param n the next iteration to validate + void CheckNextIteration(const NextIteration* n); + + /// Validates the given exit if + /// @param e the exit if to validate + void CheckExitIf(const ExitIf* e); + + /// Validates the given return + /// @param r the return to validate + void CheckReturn(const Return* r); + + /// Validates the given unreachable + /// @param u the unreachable to validate + void CheckUnreachable(const Unreachable* u); + + /// Validates the @p exit targets a valid @p control instruction where the instruction may jump + /// over if control instructions. + /// @param exit the exit to validate + /// @param control the control instruction targeted + void CheckControlsAllowingIf(const Exit* exit, const Instruction* control); + + /// Validates the given exit switch + /// @param s the exit switch to validate + void CheckExitSwitch(const ExitSwitch* s); + + /// Validates the given exit loop + /// @param l the exit loop to validate + void CheckExitLoop(const ExitLoop* l); + + /// Validates the given load + /// @param l the load to validate + void CheckLoad(const Load* l); + + /// Validates the given store + /// @param s the store to validate + void CheckStore(const Store* s); + + /// Validates the given load vector element + /// @param l the load vector element to validate + void CheckLoadVectorElement(const LoadVectorElement* l); + + /// Validates the given store vector element + /// @param s the store vector element to validate + void CheckStoreVectorElement(const StoreVectorElement* s); + + /// Validates the given phony assignment + /// @param p the phony assignment to validate + void CheckPhony(const Phony* p); + + /// Validates that the number and types of the source instruction operands match the target's + /// values. + /// @param source_inst the source instruction + /// @param source_operand_offset the index of the first operand of the source instruction + /// @param source_operand_count the number of operands of the source instruction + /// @param target the receiver of the operand values + /// @param target_values the receiver of the operand values + void CheckOperandsMatchTarget(const Instruction* source_inst, + size_t source_operand_offset, + size_t source_operand_count, + const CastableBase* target, + VectorRef target_values); + + /// @param inst the instruction + /// @param idx the operand index + /// @returns the vector pointer type for the given instruction operand + const core::type::Type* GetVectorPtrElementType(const Instruction* inst, size_t idx); + + /// @returns true if @p ty and its elements can be loaded + bool CanLoad(const core::type::Type* ty); + + /// Executes all the pending tasks + void ProcessTasks(); + + /// Queues the block to be validated with ProcessTasks() + /// @param blk the block to validate + void QueueBlock(const Block* blk); + + /// Queues the list of instructions starting with @p inst to be validated + /// @param inst the first instruction + void QueueInstructions(const Instruction* inst); + + /// Begins validation of the block @p blk, and its instructions. + /// BeginBlock() pushes a new scope for values. + /// Must be paired with a call to EndBlock(). + void BeginBlock(const Block* blk); + + /// Ends validation of the block opened with BeginBlock() and closes the block's scope for + /// values. + void EndBlock(); + + /// Get the function that contains an instruction. + /// @param inst the instruction + /// @returns the function + const ir::Function* ContainingFunction(const ir::Instruction* inst) { + if (inst->Block() == mod_.root_block) { + return nullptr; + } + + return block_to_function_.GetOrAdd(inst->Block(), [&] { // + return ContainingFunction(inst->Block()->Parent()); + }); + } + + /// Get any endpoints that call a function. + /// @param f the function + /// @returns all end points that call the function + Hashset ContainingEndPoints(const ir::Function* f) { + if (!f) { + return {}; + } + + Hashset result{}; + Hashset visited{f}; + + auto call_sites = user_func_calls_.GetOr(f, Hashset()).Vector(); + while (!call_sites.IsEmpty()) { + auto call_site = call_sites.Pop(); + auto calling_function = ContainingFunction(call_site); + if (!calling_function) { + continue; + } + + if (visited.Contains(calling_function)) { + continue; + } + visited.Add(calling_function); + + if (calling_function->IsEntryPoint()) { + result.Add(calling_function); + } + + for (auto new_call_sites : + user_func_calls_.GetOr(f, Hashset())) { + call_sites.Push(new_call_sites); + } + } + + return result; + } + + /// ScopeStack holds a stack of values that are currently in scope + struct ScopeStack { + void Push() { stack_.Push({}); } + void Pop() { stack_.Pop(); } + void Add(const Value* value) { stack_.Back().Add(value); } + bool Contains(const Value* value) { + return stack_.Any([&](auto& v) { return v.Contains(value); }); + } + bool IsEmpty() const { return stack_.IsEmpty(); } + + private: + Vector, 4> stack_; + }; + + const Module& mod_; + Capabilities capabilities_; + std::optional disassembler_; // Use Disassemble() + diag::List diagnostics_; + Hashset all_functions_; + Hashset visited_instructions_; + Hashmap first_continues_; + Vector control_stack_; + Vector block_stack_; + ScopeStack scope_stack_; + Vector, 16> tasks_; + SymbolTable symbols_ = SymbolTable::Wrap(mod_.symbols); + core::type::Manager type_mgr_ = core::type::Manager::Wrap(mod_.Types()); + Hashmap block_to_function_{}; + Hashmap, 4> user_func_calls_; + Hashmap stage_restricted_instructions_; + core::ir::ReferencedModuleVars referenced_module_vars_; + Hashset seen_override_ids_; + Hashset entry_point_names_; + Hashset validated_types_{}; +}; + +Validator::Validator(const Module& mod, Capabilities capabilities) + : mod_(mod), capabilities_(capabilities), referenced_module_vars_(mod) {} + +Validator::~Validator() = default; + +Disassembler& Validator::Disassemble() { + if (!disassembler_) { + disassembler_.emplace(ir::Disassembler(mod_)); + } + return *disassembler_; +} + +Result Validator::Run() { + RunStructuralSoundnessChecks(); + + CheckForRecursion(); + CheckForOrphanedInstructions(); + CheckStageRestrictedInstructions(); + + if (diagnostics_.ContainsErrors()) { + diagnostics_.AddNote(Source{}) << "# Disassembly\n" << Disassemble().Text(); + return Failure{diagnostics_.Str()}; + } + return Success; +} + +void Validator::CheckForRecursion() { + if (diagnostics_.ContainsErrors()) { + return; + } + + ReferencedFunctions referenced_functions(mod_); + for (auto& func : mod_.functions) { + auto& refs = referenced_functions.TransitiveReferences(func); + if (refs.Contains(func)) { + // TODO(434684891): Consider improving this error with more information. + AddError(func) << "recursive function calls are not allowed"; + return; + } + } +} + +void Validator::CheckForOrphanedInstructions() { + if (diagnostics_.ContainsErrors()) { + return; + } + + // Check for orphaned instructions. + for (auto* inst : mod_.Instructions()) { + if (!visited_instructions_.Contains(inst)) { + AddError(inst) << "orphaned instruction: " << inst->FriendlyName(); + } + } +} + +void Validator::CheckStageRestrictedInstructions() { + if (diagnostics_.ContainsErrors()) { + return; + } + + // Check for instructions being used in stages that do not support them. + for (const auto& i : stage_restricted_instructions_) { + const auto& inst = i.key; + const auto& stages = i.value; + const auto* f = ContainingFunction(inst); + if (f == nullptr) { + continue; + } + + if (f->IsEntryPoint() && !stages.Contains(f->Stage())) { + AddError(inst) << "cannot be used in a " << f->Stage() << " shader"; + } else { + for (const Function* ep : ContainingEndPoints(f)) { + if (!stages.Contains(ep->Stage())) { + AddError(inst) << "cannot be used in a " << ep->Stage() << " shader"; + } + } + } + } +} + +void Validator::RunStructuralSoundnessChecks() { + scope_stack_.Push(); + TINT_DEFER({ + scope_stack_.Pop(); + TINT_ASSERT(scope_stack_.IsEmpty()); + TINT_ASSERT(tasks_.IsEmpty()); + TINT_ASSERT(control_stack_.IsEmpty()); + TINT_ASSERT(block_stack_.IsEmpty()); + }); + CheckRootBlock(mod_.root_block); + + for (auto& func : mod_.functions) { + if (!all_functions_.Add(func)) { + AddError(func) << "function " << NameOf(func) << " added to module multiple times"; + } + scope_stack_.Add(func); + } + + for (auto& func : mod_.functions) { + block_to_function_.Add(func->Block(), func); + CheckFunction(func); + } +} + +diag::Diagnostic& Validator::AddError(const Instruction* inst) { + auto src = Disassemble().InstructionSource(inst); + auto& diag = AddError(src) << inst->FriendlyName() << ": "; + + if (!block_stack_.IsEmpty()) { + AddNote(block_stack_.Back()) << "in block"; + + // Adding the note may trigger a resize and invalidate the error diagnostic reference, so we + // need to get a new reference to the error diagnostic here. + return *(diagnostics_.end() - 2); + } + return diag; +} + +diag::Diagnostic& Validator::AddError(const Instruction* inst, size_t idx) { + auto src = + Disassemble().OperandSource(Disassembler::IndexedValue{inst, static_cast(idx)}); + auto& diag = AddError(src) << inst->FriendlyName() << ": "; + + if (!block_stack_.IsEmpty()) { + AddNote(block_stack_.Back()) << "in block"; + + // Adding the note may trigger a resize and invalidate the error diagnostic reference, so we + // need to get a new reference to the error diagnostic here. + return *(diagnostics_.end() - 2); + } + return diag; +} + +diag::Diagnostic& Validator::AddResultError(const Instruction* inst, size_t idx) { + auto src = + Disassemble().ResultSource(Disassembler::IndexedValue{inst, static_cast(idx)}); + auto& diag = AddError(src) << inst->FriendlyName() << ": "; + + if (!block_stack_.IsEmpty()) { + AddNote(block_stack_.Back()) << "in block"; + + // Adding the note may trigger a resize and invalidate the error diagnostic reference, so we + // need to get a new reference to the error diagnostic here. + return *(diagnostics_.end() - 2); + } + return diag; +} + +diag::Diagnostic& Validator::AddError(const Block* blk) { + auto src = Disassemble().BlockSource(blk); + return AddError(src); +} + +diag::Diagnostic& Validator::AddError(const BlockParam* param) { + auto src = Disassemble().BlockParamSource(param); + return AddError(src); +} + +diag::Diagnostic& Validator::AddError(const Function* func) { + auto src = Disassemble().FunctionSource(func); + return AddError(src); +} + +diag::Diagnostic& Validator::AddError(const FunctionParam* param) { + auto src = Disassemble().FunctionParamSource(param); + return AddError(src); +} + +diag::Diagnostic& Validator::AddError(const CastableBase* base) { + diag::Diagnostic* diag = nullptr; + tint::Switch( + base, // + [&](const Block* block) { diag = &AddError(block); }, + [&](const BlockParam* param) { diag = &AddError(param); }, + [&](const Function* fn) { diag = &AddError(fn); }, + [&](const FunctionParam* param) { diag = &AddError(param); }, + [&](const Instruction* inst) { diag = &AddError(inst); }, + [&](const InstructionResult* res) { diag = &AddError(res); }); + TINT_ASSERT(diag); + return *diag; +} + +diag::Diagnostic& Validator::AddNote(const Instruction* inst) { + auto src = Disassemble().InstructionSource(inst); + return AddNote(src); +} + +diag::Diagnostic& Validator::AddNote(const Function* func) { + auto src = Disassemble().FunctionSource(func); + return AddNote(src); +} + +diag::Diagnostic& Validator::AddOperandNote(const Instruction* inst, size_t idx) { + auto src = + Disassemble().OperandSource(Disassembler::IndexedValue{inst, static_cast(idx)}); + return AddNote(src); +} + +diag::Diagnostic& Validator::AddResultNote(const Instruction* inst, size_t idx) { + auto src = + Disassemble().ResultSource(Disassembler::IndexedValue{inst, static_cast(idx)}); + return AddNote(src); +} + +diag::Diagnostic& Validator::AddNote(const Block* blk) { + auto src = Disassemble().BlockSource(blk); + return AddNote(src); +} + +diag::Diagnostic& Validator::AddError(Source src) { + auto& diag = diagnostics_.AddError(src); + diag.owned_file = Disassemble().File(); + return diag; +} + +diag::Diagnostic& Validator::AddNote(Source src) { + auto& diag = diagnostics_.AddNote(src); + diag.owned_file = Disassemble().File(); + return diag; +} + +void Validator::AddDeclarationNote(const CastableBase* decl) { + tint::Switch( + decl, // + [&](const Block* block) { AddDeclarationNote(block); }, + [&](const BlockParam* param) { AddDeclarationNote(param); }, + [&](const Function* fn) { AddDeclarationNote(fn); }, + [&](const FunctionParam* param) { AddDeclarationNote(param); }, + [&](const Instruction* inst) { AddDeclarationNote(inst); }, + [&](const InstructionResult* res) { AddDeclarationNote(res); }); +} + +void Validator::AddDeclarationNote(const Block* block) { + auto src = Disassemble().BlockSource(block); + if (src.file) { + AddNote(src) << NameOf(block) << " declared here"; + } +} + +void Validator::AddDeclarationNote(const BlockParam* param) { + auto src = Disassemble().BlockParamSource(param); + if (src.file) { + AddNote(src) << NameOf(param) << " declared here"; + } +} + +void Validator::AddDeclarationNote(const Function* fn) { + AddNote(fn) << NameOf(fn) << " declared here"; +} + +void Validator::AddDeclarationNote(const FunctionParam* param) { + auto src = Disassemble().FunctionParamSource(param); + if (src.file) { + AddNote(src) << NameOf(param) << " declared here"; + } +} + +void Validator::AddDeclarationNote(const Instruction* inst) { + auto src = Disassemble().InstructionSource(inst); + if (src.file) { + AddNote(src) << NameOf(inst) << " declared here"; + } +} + +void Validator::AddDeclarationNote(const InstructionResult* res) { + if (auto* inst = res->Instruction()) { + auto results = inst->Results(); + for (size_t i = 0; i < results.Length(); i++) { + if (results[i] == res) { + AddResultNote(res->Instruction(), i) << NameOf(res) << " declared here"; + return; + } + } + } +} + +StyledText Validator::NameOf(const CastableBase* decl) { + return tint::Switch( + decl, // + [&](const core::type::Type* ty) { return NameOf(ty); }, + [&](const Value* value) { return NameOf(value); }, + [&](const Instruction* inst) { return NameOf(inst); }, + [&](const Block* block) { return NameOf(block); }, // + TINT_ICE_ON_NO_MATCH); +} + +StyledText Validator::NameOf(const core::type::Type* ty) { + auto name = ty ? ty->FriendlyName() : "undef"; + return StyledText{} << style::Type(name); +} + +StyledText Validator::NameOf(const Value* value) { + return Disassemble().NameOf(value); +} + +StyledText Validator::NameOf(const Instruction* inst) { + auto name = inst ? inst->FriendlyName() : "undef"; + return StyledText{} << style::Instruction(name); +} + +StyledText Validator::NameOf(const Block* block) { + auto parent_name = block->Parent() ? block->Parent()->FriendlyName() : "undef"; + return StyledText{} << style::Instruction(parent_name) << " block " + << Disassemble().NameOf(block); +} + +bool Validator::CheckResult(const Instruction* inst, size_t idx) { + auto* result = inst->Result(idx); + if (DAWN_UNLIKELY(result == nullptr)) { + AddResultError(inst, idx) << "result is undefined"; + return false; + } + + if (DAWN_UNLIKELY(result->Type() == nullptr)) { + AddResultError(inst, idx) << "result type is undefined"; + return false; + } + + if (DAWN_UNLIKELY(result->Instruction() == nullptr)) { + AddResultError(inst, idx) << "result instruction is undefined"; + return false; + } + + if (DAWN_UNLIKELY(result->Instruction() != inst)) { + AddResultError(inst, idx) + << "result instruction does not match instruction (possible double usage)"; + return false; + } + + if (!inst->Is() && result->Type()->Is()) { + AddResultError(inst, idx) << "result type cannot be void"; + return false; + } + + if (inst->Is()) { + if (result->Type()->Is()) { + AddResultError(inst, idx) << "result type cannot be a pointer"; + return false; + } + if (!result->Type()->IsConstructible()) { + AddResultError(inst, idx) << "result type must be constructable"; + return false; + } + } + + if (result->Type()->Is() && mod_.NameOf(result)) { + AddResultError(inst, idx) << "void results must not have names"; + return false; + } + + return true; +} + +bool Validator::CheckResults(const ir::Instruction* inst, std::optional count = {}) { + if (count.has_value()) { + if (DAWN_UNLIKELY(inst->Results().Length() != count.value())) { + AddError(inst) << "expected exactly " << count.value() << " results, got " + << inst->Results().Length(); + return false; + } + } + + bool passed = true; + Hashset seen_instruction_results; + for (size_t i = 0; i < inst->Results().Length(); i++) { + if (DAWN_UNLIKELY(!CheckResult(inst, i))) { + passed = false; + } + + if (!seen_instruction_results.Add(inst->Result(i))) { + AddResultError(inst, i) << "result was seen previously as a result"; + passed = false; + } + } + return passed; +} + +bool Validator::CheckOperand(const Instruction* inst, size_t idx) { + auto* operand = inst->Operand(idx); + + if (DAWN_UNLIKELY(operand == nullptr)) { + // var instructions are allowed to have a nullptr initializers. + // terminator instructions use nullptr operands to signal 'undef'. + if (inst->IsAnyOf()) { + return true; + } + + AddError(inst, idx) << "operand is undefined"; + return false; + } + + // ir::Unused is a internal value used by some transforms to track unused entries, and is + // removed as part of generating an output shader. + if (DAWN_UNLIKELY(operand->Is())) { + return true; + } + + if (DAWN_UNLIKELY(operand->Type() == nullptr)) { + AddError(inst, idx) << "operand type is undefined"; + return false; + } + + if (DAWN_UNLIKELY(!operand->Alive())) { + AddError(inst, idx) << "operand is not alive"; + return false; + } + + if (DAWN_UNLIKELY(!operand->HasUsage(inst, idx))) { + AddError(inst, idx) << "operand missing usage"; + return false; + } + + if (auto fn = operand->As(); fn && !all_functions_.Contains(fn)) { + AddError(inst, idx) << NameOf(operand) << " is not part of the module"; + return false; + } + + if (DAWN_UNLIKELY(!operand->Is() && !operand->Is() && + !scope_stack_.Contains(operand))) { + AddError(inst, idx) << NameOf(operand) << " is not in scope"; + AddDeclarationNote(operand); + return false; + } + + return true; +} + +bool Validator::CheckOperands(const ir::Instruction* inst, + size_t min_count, + std::optional max_count) { + if (DAWN_UNLIKELY(inst->Operands().Length() < min_count)) { + if (max_count.has_value()) { + AddError(inst) << "expected between " << min_count << " and " << max_count.value() + << " operands, got " << inst->Operands().Length(); + } else { + AddError(inst) << "expected at least " << min_count << " operands, got " + << inst->Operands().Length(); + } + return false; + } + + if (DAWN_UNLIKELY(max_count.has_value() && inst->Operands().Length() > max_count.value())) { + AddError(inst) << "expected between " << min_count << " and " << max_count.value() + << " operands, got " << inst->Operands().Length(); + return false; + } + + bool passed = true; + for (size_t i = 0; i < inst->Operands().Length(); i++) { + if (DAWN_UNLIKELY(!CheckOperand(inst, i))) { + passed = false; + } + } + return passed; +} + +bool Validator::CheckOperands(const ir::Instruction* inst, std::optional count = {}) { + if (count.has_value()) { + if (DAWN_UNLIKELY(inst->Operands().Length() != count.value())) { + AddError(inst) << "expected exactly " << count.value() << " operands, got " + << inst->Operands().Length(); + return false; + } + } + + bool passed = true; + for (size_t i = 0; i < inst->Operands().Length(); i++) { + if (DAWN_UNLIKELY(!CheckOperand(inst, i))) { + passed = false; + } + } + return passed; +} + +bool Validator::CheckResultsAndOperandRange(const ir::Instruction* inst, + size_t num_results, + size_t min_operands, + std::optional max_operands = {}) { + // Intentionally avoiding short-circuiting here + bool results_passed = CheckResults(inst, num_results); + bool operands_passed = CheckOperands(inst, min_operands, max_operands); + return results_passed && operands_passed; +} + +bool Validator::CheckResultsAndOperands(const ir::Instruction* inst, + size_t num_results, + size_t num_operands) { + // Intentionally avoiding short-circuiting here + bool results_passed = CheckResults(inst, num_results); + bool operands_passed = CheckOperands(inst, num_operands); + return results_passed && operands_passed; +} + +void Validator::CheckType(const core::type::Type* root, + std::function diag, + Capabilities ignore_caps) { + if (root == nullptr) { + return; + } + + if (!capabilities_.Contains(Capability::kAllowNonCoreTypes)) { + // Check for core types, which are the only types declared in the `tint::core` namespace. + if (!std::string_view(root->TypeInfo().name).starts_with("tint::core")) { + diag() << "non-core types not allowed in core IR"; + return; + } + } + + if (!validated_types_.Add(ValidatedType{root, ignore_caps})) { + return; + } + + AddressSpace addrspace = AddressSpace::kUndefined; + if (auto* mv = root->As()) { + addrspace = mv->AddressSpace(); + } + + auto visit = [&](const core::type::Type* type) { + if (type->IsAbstract()) { + diag() << "abstracts are not permitted"; + return false; + } + + return tint::Switch( + type, + [&](const core::type::Struct* str) { + uint32_t cur_offset = 0; + for (auto* member : str->Members()) { + if (member->Type()->Is()) { + diag() << "struct member " << member->Index() << " cannot have void type"; + return false; + } + + if (!capabilities_.Contains(Capability::kMslAllowEntryPointInterface)) { + if (member->Type()->Is()) { + diag() << "struct member " << member->Index() + << " cannot be a pointer type"; + return false; + } + + if (member->Type()->Is()) { + diag() << "struct member " << member->Index() + << " cannot be a texture type"; + return false; + } + + if (member->Type()->Is()) { + diag() << "struct member " << member->Index() + << " cannot be a sampler type"; + return false; + } + } + + if (auto* arr = member->Type()->As(); + arr && arr->Count()->Is()) { + if (member != str->Members().Back()) { + diag() << "runtime-sized arrays can only be the last member of a " + "struct"; + return false; + } + } + + if (member->Align() == 0) { + diag() << "struct member must not have an alignment of 0"; + return false; + } + if (member->Type()->Align() == 0) { + diag() << "struct member type must not have an alignment of 0"; + return false; + } + + if (!capabilities_.Contains(Capability::kAllowStructMatrixDecorations)) { + if (member->RowMajor()) { + diag() << "Row major annotation not allowed on structures"; + return false; + } + if (member->HasMatrixStride()) { + diag() << "Matrix stride annotation not allowed on structures"; + return false; + } + } + + // TODO(448608979): Remove guard once updated to handle RowMajor correctly + if (!member->RowMajor()) { + if (member->Size() < member->Type()->Size()) { + diag() << "struct member " << member->Index() + << " with size=" << member->Size() + << " must be at least as large as the type with size " + << member->Type()->Size(); + return false; + } + + if (member->Align() % member->Type()->Align() != 0) { + diag() << "struct member alignment (" << member->Align() + << ") must be divisible by type alignment (" + << member->Type()->Align() << ")"; + return false; + } + } + + auto padding = member->Offset() - cur_offset; + if (padding >= internal_limits::kMaxStructMemberPadding) { + diag() << "struct member padding (" << padding + << ") is larger then the max (" + << internal_limits::kMaxStructMemberPadding << ")"; + return false; + } + cur_offset += padding + member->MinimumRequiredSize(); + } + if (str->Size() < cur_offset) { + diag() << "struct size (" << str->Size() + << ") is smaller than the end of the last member (" << cur_offset << ")"; + return false; + } + + auto padding = str->Size() - cur_offset; + if (padding >= internal_limits::kMaxStructMemberPadding) { + diag() << "struct padding (" << padding << ") is larger then the max (" + << internal_limits::kMaxStructMemberPadding << ")"; + return false; + } + + return true; + }, + [&](const core::type::Reference* ref) { + if (ref->StoreType()->Is()) { + diag() << "references to void are not permitted"; + return false; + } + + // Reference types are guarded by the AllowRefTypes capability. + if (!capabilities_.Contains(Capability::kAllowRefTypes) || + ignore_caps.Contains(Capability::kAllowRefTypes)) { + diag() << "reference types are not permitted here"; + return false; + } else if (type != root) { + // If they are allowed, reference types still cannot be nested. + diag() << "nested reference types are not permitted"; + return false; + } + return true; + }, + [&](const core::type::Pointer* ptr) { + if (ptr->StoreType()->Is()) { + diag() << "pointers to void are not permitted"; + return false; + } + + if (ptr->AddressSpace() == AddressSpace::kUniform || + ptr->AddressSpace() == AddressSpace::kHandle) { + if (ptr->Access() != core::Access::kRead) { + diag() << "uniform and handle pointers must be read access"; + return false; + } + } + + if (ptr->AddressSpace() == AddressSpace::kWorkgroup) { + if (ptr->Access() != core::Access::kReadWrite) { + diag() << "workgroup pointers must be read_write access"; + return false; + } + } + + if (ptr->AddressSpace() == AddressSpace::kHandle) { + if (!ptr->StoreType()->IsHandle()) { + diag() << "the 'handle' address space can only be used for handle types"; + return false; + } + } else { + if (ptr->StoreType()->IsHandle()) { + diag() << "handle types can only be declared in the 'handle' address space"; + return false; + } + } + + if (ptr->AddressSpace() == core::AddressSpace::kImmediate) { + if (ptr->Access() != core::Access::kRead) { + diag() << "immediate pointers must be read access"; + return false; + } + } + + if (ptr->StoreType()->Is()) { + diag() << "pointers to pointers are not allowed"; + return false; + } + return true; + }, + [&](const core::type::U64*) { + // u64 types are guarded by the Allow64BitIntegers capability. + if (!capabilities_.Contains(Capability::kAllow64BitIntegers)) { + diag() << "64-bit integer types are not permitted"; + return false; + } + return true; + }, + [&](const core::type::I8*) { + // i8 types are guarded by the Allow8BitIntegers capability. + if (!capabilities_.Contains(Capability::kAllow8BitIntegers)) { + diag() << "8-bit integer types are not permitted"; + return false; + } + return true; + }, + [&](const core::type::U8*) { + // u8 types are guarded by the Allow8BitIntegers capability. + if (!capabilities_.Contains(Capability::kAllow8BitIntegers)) { + diag() << "8-bit integer types are not permitted"; + return false; + } + return true; + }, + [&](const core::type::Array* arr) { + if (!arr->ElemType()->HasCreationFixedFootprint()) { + diag() << "array elements, " << NameOf(type) + << ", must have creation-fixed footprint"; + return false; + } + if (arr->Count()->Is()) { + if (addrspace != AddressSpace::kStorage) { + diag() << "runtime arrays must be in the 'storage' address space"; + return false; + } + } else if (auto* count = arr->Count()->As()) { + if (count->value == 0) { + diag() << "array requires a constant array size > 0"; + return false; + } + } + return true; + }, + [&](const core::type::Vector* v) { + if (!v->Type()->IsScalar()) { + diag() << "vector elements, " << NameOf(type) << ", must be scalars"; + return false; + } + return true; + }, + [&](const core::type::Matrix* m) { + if (!m->Type()->IsFloatScalar()) { + diag() << "matrix elements, " << NameOf(type) << ", must be float scalars"; + return false; + } + return true; + }, + [&](const core::type::Atomic* a) { + if (!a->Type()->IsAnyOf()) { + diag() << "atomic subtype must be i32 or u32"; + return false; + } + return true; + }, + [&](const core::type::SampledTexture* s) { + if (!s->Type()->IsAnyOf()) { + diag() << "invalid sampled texture sample type: " << NameOf(s->Type()); + return false; + } + return true; + }, + [&](const core::type::MultisampledTexture* ms) { + if (!ms->Type()->IsAnyOf()) { + diag() << "invalid multisampled texture sample type: " << NameOf(ms->Type()); + return false; + } + + switch (ms->Dim()) { + case core::type::TextureDimension::k2d: + break; + default: + diag() << "invalid multisampled texture dimension: " + << style::Literal(ToString(ms->Dim())); + return false; + } + return true; + }, + [&](const core::type::StorageTexture* s) { + switch (s->Dim()) { + case core::type::TextureDimension::kCube: + case core::type::TextureDimension::kCubeArray: + diag() << "dimension " << style::Literal(ToString(s->Dim())) + << " for storage textures does not in WGSL yet"; + return false; + case core::type::TextureDimension::kNone: + diag() << "invalid texture dimension " + << style::Literal(ToString(s->Dim())); + return false; + default: + return true; + } + }, + [&](const core::type::InputAttachment* i) { + if (!i->Type()->IsAnyOf()) { + diag() << "invalid input attachment component type: " << NameOf(i->Type()); + return false; + } + return true; + }, + [&](const core::type::SubgroupMatrix* m) { + if (!m->Type() + ->IsAnyOf()) { + diag() << "invalid subgroup matrix component type: " << NameOf(m->Type()); + return false; + } + if (!(addrspace == AddressSpace::kUndefined || + addrspace == AddressSpace::kFunction)) { + diag() << "invalid address space for subgroup matrix : " << addrspace; + return false; + } + return true; + }, + [&](const core::type::BindingArray* t) { + if (!t->Count()->Is()) { + diag() << "binding_array count must be a constant expression"; + return false; + } + + auto count = t->Count()->As()->value; + if (count == 0) { + diag() << "binding array requires a constant array size > 0"; + return false; + } + + if (!(addrspace == AddressSpace::kUndefined || + addrspace == AddressSpace::kHandle) && + !capabilities_.Contains(Capability::kMslAllowEntryPointInterface)) { + diag() << "invalid address space for binding_array : " << addrspace; + return false; + } + + if (!capabilities_.Contains(Capability::kAllowNonCoreTypes)) { + if (!t->ElemType()->Is()) { + diag() << "binding_array element type must be a sampled texture type"; + return false; + } + } + return true; + }, + [](Default) { return true; }); + }; + + Vector stack{root}; + Hashset seen{}; + while (!stack.IsEmpty()) { + auto* ty = stack.Pop(); + if (!ty) { + continue; + } + if (!visit(ty)) { + return; + } + + if (auto* view = ty->As(); view && seen.Add(view)) { + stack.Push(view->StoreType()); + continue; + } + + auto type_count = ty->Elements(); + if (type_count.type && seen.Add(type_count.type)) { + stack.Push(type_count.type); + continue; + } + + for (uint32_t i = 0; i < type_count.count; i++) { + if (auto* subtype = ty->Element(i); subtype && seen.Add(subtype)) { + stack.Push(subtype); + } + } + } +} + +void Validator::CheckRootBlock(const Block* blk) { + block_stack_.Push(blk); + TINT_DEFER(block_stack_.Pop()); + + for (auto* inst : *blk) { + if (inst->Block() != blk) { + AddError(inst) << "instruction in root block does not have root block as parent"; + continue; + } + + tint::Switch( + inst, // + [&](const core::ir::Override* o) { + if (capabilities_.Contains(Capability::kAllowOverrides)) { + CheckInstruction(o); + } else { + AddError(inst) << "root block: invalid instruction: " << inst->TypeInfo().name; + } + }, + [&](const core::ir::Var* var) { CheckInstruction(var); }, + [&](const core::ir::Let* let) { + if (capabilities_.Contains(Capability::kAllowModuleScopeLets)) { + CheckInstruction(let); + } else { + AddError(inst) << "root block: invalid instruction: " << inst->TypeInfo().name; + } + }, + [&](const core::ir::Construct* c) { + if (capabilities_.Contains(Capability::kAllowModuleScopeLets) || + capabilities_.Contains(Capability::kAllowOverrides)) { + CheckInstruction(c); + CheckOnlyUsedInRootBlock(inst); + } else { + AddError(inst) << "root block: invalid instruction: " << inst->TypeInfo().name; + } + }, + [&](Default) { + // Note, this validation around kAllowOverrides is looser than it could be. There + // are only certain expressions and builtins which can be used in an override, but + // the current checks are only doing type level checking. To tighten this up will + // require walking up the tree to make sure that operands are const/override and + // builtins are allowed. + if (capabilities_.Contains(Capability::kAllowOverrides) && + inst->IsAnyOf()) { + CheckInstruction(inst); + // If overrides are allowed we can have certain regular instructions in the root + // block, with the caveat that those instructions can _only_ be used in the root + // block. + CheckOnlyUsedInRootBlock(inst); + } else { + AddError(inst) << "root block: invalid instruction: " << inst->TypeInfo().name; + } + }); + } + // Our ConstExprIfs in the root require us to process tasks here. + ProcessTasks(); +} + +void Validator::CheckOnlyUsedInRootBlock(const Instruction* inst) { + if (inst->Result(0)) { + for (auto& usage : inst->Result(0)->UsagesSorted()) { + if (usage.instruction->Block() != mod_.root_block) { + AddError(inst) << "root block: instruction used outside of root block " + << inst->TypeInfo().name; + } + } + } + + CheckInstruction(inst); +} + +void Validator::CheckFunction(const Function* func) { + // Scope holds the parameters and block + scope_stack_.Push(); + TINT_DEFER(scope_stack_.Pop()); + + if (func->IsEntryPoint()) { + // Check that there is at most one entry point unless we allow multiple entry points. + if (!capabilities_.Contains(Capability::kAllowMultipleEntryPoints)) { + if (!entry_point_names_.IsEmpty()) { + AddError(func) << "a module with multiple entry points requires the " + "AllowMultipleEntryPoints capability"; + return; + } + } + + // Checking the name early, so its usage can be recorded, even if the function is malformed. + const auto name = mod_.NameOf(func).Name(); + if (!entry_point_names_.Add(name)) { + AddError(func) << "entry point name " << style::Function(name) << " is not unique"; + } + } + + if (!func->Type() || !func->Type()->Is()) { + AddError(func) << "functions must have type ''"; + return; + } + + if (!func->Block()) { + AddError(func) << "root block for function is undefined"; + return; + } + + if (func->Block()->Is()) { + AddError(func) << "root block for function cannot be a multi-in block"; + return; + } + + Hashset param_set{}; + for (auto* param : func->Params()) { + if (!param->Alive()) { + AddError(param) << "destroyed parameter found in function parameter list"; + return; + } + if (!param->Function()) { + AddError(param) << "function parameter has nullptr parent function"; + return; + } else if (param->Function() != func) { + AddError(param) << "function parameter has incorrect parent function"; + AddNote(param->Function()) << "parent function declared here"; + return; + } + + if (!param->Type()) { + AddError(param) << "function parameter has nullptr type"; + return; + } + + if (!param_set.Add(param)) { + AddError(param) << "function parameter is not unique"; + continue; + } + + // References not allowed on function signatures even with Capability::kAllowRefTypes. + CheckType( + param->Type(), [&]() -> diag::Diagnostic& { return AddError(param); }, + Capabilities{Capability::kAllowRefTypes}); + + if (!IsValidFunctionParamType(param->Type())) { + auto ptr_ty = param->Type()->As(); + bool allowed_ptr_to_handle = + capabilities_.Contains(Capability::kAllowPointerToHandle) && ptr_ty != nullptr && + ptr_ty->StoreType()->IsHandle(); + + auto struct_ty = param->Type()->As(); + if (!allowed_ptr_to_handle && + (!capabilities_.Contains(Capability::kMslAllowEntryPointInterface) || + (struct_ty == nullptr) || + struct_ty->Members().Any([](const core::type::StructMember* m) { + return !IsValidFunctionParamType(m->Type()); + }))) { + AddError(param) << "function parameter type, " << NameOf(param->Type()) + << ", must be constructible, a pointer, or a handle"; + } + } + if (func->IsEntryPoint() && + !capabilities_.Contains(Capability::kMslAllowEntryPointInterface)) { + if (param->Type()->Is()) { + AddError(param) << "entry point parameters cannot be pointers"; + } + } + + if (func->IsFragment()) { + WalkTypeAndMembers(param, param->Type(), param->Attributes(), + [this](const auto* p, const auto* t, const auto& a) { + CheckFrontFacingIfBool( + p, a, t, + "fragment entry point params can only be a bool if " + "decorated with @builtin(front_facing)"); + }); + } else if (func->IsEntryPoint()) { + WalkTypeAndMembers( + param, param->Type(), param->Attributes(), + [this](const auto* p, const auto* t, const auto&) { + CheckNotBool(p, t, + "entry point params can only be a bool for fragment shaders"); + }); + } + + AddressSpace address_space = AddressSpace::kUndefined; + auto* mv = param->Type()->As(); + if (mv) { + address_space = mv->AddressSpace(); + } else { + // ModuleScopeVars transform in MSL backends unwraps pointers to handles + if (param->Type()->IsHandle()) { + address_space = AddressSpace::kHandle; + } + } + + if (address_space == AddressSpace::kPixelLocal) { + if (!mv->StoreType()->Is()) { + AddError(param) << "pixel_local param must be of type struct"; + } + } + + if (func->IsEntryPoint()) { + ValidateShaderIOAnnotations(param, param->Type(), param->BindingPoint(), + param->Attributes(), ShaderIOKind::kInputParam); + } else { + if (param->BindingPoint().has_value()) { + AddError(param) + << "input param to non-entry point function has a binding point set"; + } + + if (param->Builtin().has_value()) { + AddError(param) << "builtins can only be decorated on entry point params"; + } + } + + if (!capabilities_.Contains(Capability::kMslAllowEntryPointInterface) && + func->IsEntryPoint()) { + if (mv && mv->Is() && address_space == AddressSpace::kWorkgroup) { + AddError(param) << "input param to entry point cannot be a ptr in the 'workgroup' " + "address space"; + } + } + + scope_stack_.Add(param); + } + + // References not allowed on function signatures even with Capability::kAllowRefTypes. + CheckType( + func->ReturnType(), [&]() -> diag::Diagnostic& { return AddError(func); }, + Capabilities{Capability::kAllowRefTypes}); + + // void needs to be filtered out, since it isn't constructible, but used in the IR when no + // return is specified. + if (DAWN_UNLIKELY(!func->ReturnType()->Is() && + !func->ReturnType()->IsConstructible())) { + AddError(func) << "function return type must be constructible"; + } + + ValidateIOAttributes(func); + + if (func->IsEntryPoint()) { + if (DAWN_UNLIKELY(mod_.NameOf(func).Name().empty())) { + AddError(func) << "entry points must have names"; + } + } + + CheckWorkgroupSize(func); + + CheckSubgroupSize(func); + + if (func->Stage() == Function::PipelineStage::kCompute) { + if (DAWN_UNLIKELY(func->ReturnType() && !func->ReturnType()->Is())) { + AddError(func) << "compute entry point must not have a return type, found " + << NameOf(func->ReturnType()); + } + } + + if (func->IsEntryPoint()) { + ValidateShaderIOAnnotations(func, func->ReturnType(), std::nullopt, + func->ReturnAttributes(), ShaderIOKind::kResultValue); + + WalkTypeAndMembers( + func, func->ReturnType(), func->ReturnAttributes(), + [this](const Function* f, const core::type::Type* t, const IOAttributes&) { + CheckNotBool(f, t, "entry point returns can not be 'bool'"); + }); + + Hashset binding_points{}; + const Var* user_declared_immediate = nullptr; + + for (auto var : referenced_module_vars_.TransitiveReferences(func)) { + if (!capabilities_.Contains(Capability::kAllowDuplicateBindings) && + var->BindingPoint().has_value()) { + auto bp = var->BindingPoint().value(); + if (!binding_points.Add(bp)) { + AddError(var) << "found non-unique binding point, " << bp + << ", being referenced in entry point, " << NameOf(func); + } + } + + const auto* mv = var->Result()->Type()->As(); + const auto* ty = var->Result()->Type()->UnwrapPtrOrRef(); + const auto attr = var->Attributes(); + if (!mv || !ty) { + continue; + } + + if (mv->AddressSpace() == AddressSpace::kImmediate) { + if (user_declared_immediate) { + AddError(var) << "multiple user-declared immediate data variables referenced " + "by entry point " + << NameOf(func); + return; + } + user_declared_immediate = var; + } + + if (mv->AddressSpace() != AddressSpace::kIn && + mv->AddressSpace() != AddressSpace::kOut) { + continue; + } + + if (func->IsFragment() && mv->AddressSpace() == AddressSpace::kIn) { + WalkTypeAndMembers( + var, ty, attr, [this](const auto* v, const auto* t, const auto& a) { + CheckFrontFacingIfBool( + v, a, t, + "input address space values referenced by fragment shaders " + "can only be 'bool' if decorated with " + "@builtin(front_facing)"); + }); + } else { + WalkTypeAndMembers( + var, ty, attr, [this](const auto* v, const auto* t, const auto&) { + CheckNotBool( + v, t, + "IO address space values referenced by shader entry points can " + "only be 'bool' if in the input space, used only by fragment " + "shaders and decorated with @builtin(front_facing)"); + }); + } + } + } + + if (func->IsVertex()) { + CheckPositionPresentForVertexOutput(func); + } + + QueueBlock(func->Block()); + ProcessTasks(); +} + +void Validator::ValidateIOAttributes(const Function* func) { + const auto stage = func->Stage(); + struct Task { + const CastableBase* anchor; + const core::type::Type* type; + const IOAttributes& attr; + IODirection dir; + ShaderIOKind io_kind; + }; + Vector tasks; + + // Gather parameters. + for (auto* param : func->Params()) { + tasks.Push({param, param->Type(), param->Attributes(), IODirection::kInput, + ShaderIOKind::kInputParam}); + } + + // Gather return value. + tasks.Push({func, func->ReturnType(), func->ReturnAttributes(), IODirection::kOutput, + ShaderIOKind::kResultValue}); + + // Gather referenced module variables. + for (auto* var : referenced_module_vars_.TransitiveReferences(func)) { + auto* mv = var->Result()->Type()->As(); + if (mv == nullptr) { + continue; + } + if (mv->AddressSpace() == AddressSpace::kIn || mv->AddressSpace() == AddressSpace::kOut || + mv->AddressSpace() == AddressSpace::kHandle) { + tasks.Push({var, mv->StoreType(), var->Attributes(), IODirectionFor(mv->AddressSpace()), + ShaderIOKind::kModuleScopeVar}); + } + } + + if (stage != Function::PipelineStage::kUndefined) { + // Shared context for blend_src and location validation + BlendSrcContext input_ctx{func->Stage(), {}, {}, nullptr, IODirection::kInput}; + BlendSrcContext output_ctx{func->Stage(), {}, {}, nullptr, IODirection::kOutput}; + + // First pass: pre-populate location hashes for blend_src. + for (const auto& task : tasks) { + auto& ctx = task.dir == IODirection::kInput ? input_ctx : output_ctx; + WalkTypeAndMembers( + ctx, task.type, task.attr, + [task](BlendSrcContext& c, const core::type::Type*, const IOAttributes& a) { + if (a.blend_src.has_value() && a.location.has_value()) { + c.locations.Add(a.location.value(), task.anchor); + } + }); + } + + // Second pass: validate blend_src usages. + for (const auto& task : tasks) { + auto& ctx = task.dir == IODirection::kInput ? input_ctx : output_ctx; + CheckBlendSrc(ctx, task.anchor, task.type, task.attr); + } + + if (!output_ctx.blend_srcs.IsEmpty()) { + if (output_ctx.blend_srcs.Count() != 2) { + AddError(func) << "if any @blend_src is used on an output, then @blend_src(0) and " + "@blend_src(1) must be used"; + } + } + + // Third pass: validate all non-blend_src location usages. + for (const auto& task : tasks) { + if (task.dir == IODirection::kInput) { + CheckLocation(input_ctx.locations, task.anchor, task.attr, func->Stage(), task.type, + task.dir); + } else if (task.dir == IODirection::kOutput) { + CheckLocation(output_ctx.locations, task.anchor, task.attr, func->Stage(), + task.type, task.dir); + } + } + } + + // Validate all the interpolation usages. + for (const auto& task : tasks) { + CheckInterpolation(task.anchor, task.type, task.attr); + } + + if (stage != Function::PipelineStage::kUndefined) { + // Validate all the binding_point usages, and ensure things that require binding_point have + // them. + for (const auto& task : tasks) { + CheckBindingPoint(task.anchor, task.type, task.attr, task.io_kind); + } + } + + IOAttributeContext impl_ctx{.input_builtins = {}, .output_builtins = {}}; + // Validate all remaining attributes on IO objects + for (const auto& task : tasks) { + ValidateIOAttributesImpl(impl_ctx, task.anchor, task.type, task.attr, stage, task.dir, + task.io_kind); + } +} + +void Validator::ValidateIOAttributesImpl(IOAttributeContext& ctx, + const CastableBase* msg_anchor, + const core::type::Type* ty, + const IOAttributes& attr, + Function::PipelineStage stage, + IODirection dir, + ShaderIOKind io_kind) { + bool skip_builtins = capabilities_.Contains(Capability::kLoosenValidationForShaderIO) && + io_kind == ShaderIOKind::kModuleScopeVar; + const IOAttributeUsage usage = IOAttributeUsageFor(stage, dir); + WalkTypeAndMembers( + *this, ty, attr, + [&ctx, msg_anchor, usage, io_kind, skip_builtins, dir]( + Validator& v, const core::type::Type* t, const IOAttributes& a) { + const auto checkers = IOAttributeCheckersFor(a, skip_builtins); + if (checkers.IsEmpty()) { + return; + } + + if (a.builtin.has_value() && !skip_builtins) { + const auto& builtin = a.builtin.value(); + + uint32_t count = 0; + switch (dir) { + case IODirection::kInput: + count = ++(ctx.input_builtins.GetOrAddZeroEntry(builtin).value); + break; + case IODirection::kOutput: + count = ++(ctx.output_builtins.GetOrAddZeroEntry(builtin).value); + break; + default: + // This shouldn't ever happen, but this will get caught later in the + // checker, so just ignoring + break; + } + if (v.capabilities_.Contains(Capability::kAllowClipDistancesOnF32ScalarAndVector) && + builtin == BuiltinValue::kClipDistances) { + if (count > 2) { + v.AddError(msg_anchor) + << "too many instances of builtin 'clip_distances' on entry point " + << ToString(dir) + << ", only two allowed with 'kAllowClipDistancesOnF32ScalarAndVector' " + "capability enabled"; + } + } else { + if (count > 1) { + v.AddError(msg_anchor) + << "duplicate instance of builtin '" << ToString(builtin) + << "' on entry point " << ToString(dir) + << ", must be unique per entry point i/o direction"; + } + } + } + + auto failed = tint::Hashset(); + + if (usage != IOAttributeUsage::kUndefinedUsage) { + for (const auto* checker : checkers) { + if (!checker->valid_usages.Contains(usage)) { + failed.Add(checker); + + std::stringstream msg; + msg << ToString(checker->kind) << " IO attributes cannot be declared for a " + << ToString(usage) << ". "; + if (checker->valid_usages.Size() == 1) { + const auto& u = *checker->valid_usages.begin(); + msg << "They can only be used for a " << ToString(u) << "."; + } else { + msg << "They can only be used for " << ToString(checker->valid_usages); + } + v.AddError(msg_anchor) << msg.str(); + } + } + } + + for (const auto& checker : checkers) { + if (failed.Contains(checker)) { + continue; + } + + if (!checker->valid_io_kinds.Contains(io_kind)) { + failed.Add(checker); + + std::stringstream msg; + msg << ToString(checker->kind) << " IO attributes cannot be declared on a " + << ToString(io_kind) << ". "; + if (checker->valid_io_kinds.Size() == 1) { + const auto& k = *checker->valid_io_kinds.begin(); + msg << "They can only be used on a " << ToString(k) << "."; + } else { + msg << "They can only be used on " << ToString(checker->valid_io_kinds); + } + v.AddError(msg_anchor) << msg.str(); + } + } + + for (const auto& checker : checkers) { + if (failed.Contains(checker)) { + continue; + } + + if (!checker->type_check(t, v.capabilities_)) { + failed.Add(checker); + v.AddError(msg_anchor) << ToString(checker->kind) << " " << checker->type_error; + } + } + + for (const auto& checker : checkers) { + if (failed.Contains(checker)) { + continue; + } + + if (auto res = checker->check(t, a, v.capabilities_, usage); res != Success) { + failed.Add(checker); + v.AddError(msg_anchor) << res.Failure(); + } + } + }); +} + +void Validator::CheckFrontFacingIfBool(const CastableBase* msg_anchor, + const IOAttributes& attr, + const core::type::Type* ty, + const std::string& err) { + if (ty->Is() && attr.builtin != BuiltinValue::kFrontFacing) { + AddError(msg_anchor) << err; + } +} + +void Validator::CheckNotBool(const CastableBase* msg_anchor, + const core::type::Type* ty, + const std::string& err) { + if (ty->Is()) { + AddError(msg_anchor) << err; + } +} + +void Validator::CheckWorkgroupSize(const Function* func) { + if (!func->IsCompute()) { + if (func->WorkgroupSize().has_value()) { + AddError(func) << "@workgroup_size only valid on compute entry point"; + } + return; + } + + if (!func->WorkgroupSize().has_value()) { + AddError(func) << "compute entry point requires @workgroup_size"; + return; + } + + auto workgroup_sizes = func->WorkgroupSize().value(); + // The number parameters cannot be checked here, since it is stored internally as a 3 element + // array, so will always have 3 elements at this point. + TINT_ASSERT(workgroup_sizes.size() == 3); + + uint64_t total_size = 1; + + std::optional sizes_ty; + for (auto* size : workgroup_sizes) { + if (!size || !size->Type()) { + AddError(func) << "a @workgroup_size param is undefined or missing a type"; + return; + } + + auto* ty = size->Type(); + if (!ty->IsAnyOf()) { + AddError(func) << "@workgroup_size params must be an 'i32' or 'u32', received " + << NameOf(ty); + return; + } + + if (!sizes_ty.has_value()) { + sizes_ty = ty; + } + + if (sizes_ty != ty) { + AddError(func) << "@workgroup_size params must be all 'i32's or all 'u32's"; + return; + } + + if (auto* c = size->As()) { + if (c->Value()->ValueAs() <= 0) { + AddError(func) << "@workgroup_size params must be greater than 0"; + return; + } + total_size *= c->Value()->ValueAs(); + + constexpr uint64_t kMaxGridSize = 0xffffffff; + if (total_size > kMaxGridSize) { + AddError(func) << "workgroup grid size cannot exceed 0x" << std::hex + << kMaxGridSize; + } + continue; + } + + if (!capabilities_.Contains(Capability::kAllowOverrides)) { + AddError(func) << "@workgroup_size param is not a constant value, and IR capability " + "'kAllowOverrides' is not set"; + return; + } + + if (auto* r = size->As()) { + if (!r->Instruction()) { + AddError(func) << "instruction for @workgroup_size param is not defined"; + return; + } + + if (r->Instruction()->Block() != mod_.root_block) { + AddError(func) << "@workgroup_size param defined by non-module scope value"; + return; + } + + if (r->Instruction()->Is()) { + continue; + } + + // TODO(376624999): Finish implementing checking that this is a override/constant + // expression, i.e. calculated from only appropriate values/operations, once override + // implementation is complete + // for each value/operation used to calculate param: + // if not constant expression && not override expression: + // fail + // pass + + continue; + } + + AddError(func) << "@workgroup_size must be an InstructionResult or a Constant"; + } +} + +void Validator::CheckSubgroupSize(const Function* func) { + // @subgroup_size is optional + if (!func->SubgroupSize().has_value()) { + return; + } + + if (!func->IsCompute()) { + AddError(func) << "@subgroup_size only valid on compute entry point"; + return; + } + + auto subgroup_size = func->SubgroupSize().value(); + if (subgroup_size == nullptr) { + AddError(func) << "a @subgroup_size param must have a value"; + return; + } + + if (!subgroup_size->Type()) { + AddError(func) << "a @subgroup_size param is missing a type"; + return; + } + + auto* ty = subgroup_size->Type(); + if (!ty->IsAnyOf()) { + AddError(func) << "@subgroup_size param must be an 'i32' or 'u32', received " << NameOf(ty); + return; + } + + if (auto* c = subgroup_size->As()) { + int64_t value = c->Value()->ValueAs(); + if (value <= 0) { + AddError(func) << "@subgroup_size param must be greater than 0"; + return; + } + + if (!IsPowerOfTwo(value)) { + AddError(func) << "@subgroup_size param must be a power of 2"; + return; + } + + return; + } + + if (!capabilities_.Contains(Capability::kAllowOverrides)) { + AddError(func) << "@subgroup_size param is not a constant value, and IR capability " + "'kAllowOverrides' is not set"; + return; + } + + if (auto* r = subgroup_size->As()) { + if (!r->Instruction()) { + AddError(func) << "instruction for @subgroup_size param is not defined"; + return; + } + + if (r->Instruction()->Block() != mod_.root_block) { + AddError(func) << "@subgroup_size param defined by non-module scope value"; + return; + } + + if (r->Instruction()->Is()) { + return; + } + } + + AddError(func) << "@subgroup_size must be an InstructionResult or a Constant"; +} + +void Validator::CheckPositionPresentForVertexOutput(const Function* ep) { + if (IsPositionPresent(ep->ReturnAttributes(), ep->ReturnType())) { + return; + } + + for (const auto& var : referenced_module_vars_.TransitiveReferences(ep)) { + const auto* ty = var->Result()->Type()->UnwrapPtrOrRef(); + if (!ty) { + continue; + } + + const auto attr = var->Attributes(); + if (IsPositionPresent(attr, ty)) { + return; + } + } + AddError(ep) << "position must be declared for vertex entry point output"; +} + +void Validator::ProcessTasks() { + while (!tasks_.IsEmpty()) { + tasks_.Pop()(); + } +} + +void Validator::QueueBlock(const Block* blk) { + tasks_.Push([this] { EndBlock(); }); + tasks_.Push([this, blk] { BeginBlock(blk); }); +} + +void Validator::BeginBlock(const Block* blk) { + scope_stack_.Push(); + block_stack_.Push(blk); + + if (auto* mb = blk->As()) { + for (auto* param : mb->Params()) { + if (!param->Alive()) { + AddError(param) << "destroyed parameter found in block parameter list"; + return; + } + if (!param->Block()) { + AddError(param) << "block parameter has nullptr parent block"; + return; + } else if (param->Block() != mb) { + AddError(param) << "block parameter has incorrect parent block"; + AddNote(param->Block()) << "parent block declared here"; + return; + } + + // References not allowed on block parameters even with Capability::kAllowRefTypes. + CheckType( + param->Type(), [&]() -> diag::Diagnostic& { return AddError(param); }, + Capabilities{Capability::kAllowRefTypes}); + + if (param->Type()->Is()) { + AddError(param) << "block parameter type cannot be void"; + } + + scope_stack_.Add(param); + } + } + + if (!blk->Terminator()) { + AddError(blk) << "block does not end in a terminator instruction"; + } + + // Validate the instructions w.r.t. the parent block + for (auto* inst : *blk) { + if (inst->Block() != blk) { + AddError(inst) << "block instruction does not have same block as parent"; + AddNote(blk) << "in block"; + } + } + + // Enqueue validation of the instructions of the block + if (!blk->IsEmpty()) { + QueueInstructions(blk->Instructions()); + } +} + +void Validator::EndBlock() { + scope_stack_.Pop(); + block_stack_.Pop(); +} + +void Validator::QueueInstructions(const Instruction* inst) { + if (diagnostics_.ContainsErrors()) { + return; + } + + tasks_.Push([this, inst] { + // Tasks are processed LIFO, so push the next instruction to the stack before checking the + // current instruction, which may need to add more blocks to the stack itself. + if (inst->next) { + QueueInstructions(inst->next); + } + CheckInstruction(inst); + }); +} + +void Validator::CheckInstruction(const Instruction* inst) { + visited_instructions_.Add(inst); + if (!inst->Alive()) { + AddError(inst) << "destroyed instruction found in instruction list"; + return; + } + + auto results = inst->Results(); + for (size_t i = 0; i < results.Length(); ++i) { + auto* res = results[i]; + if (!res) { + continue; + } + CheckType(res->Type(), [&]() -> diag::Diagnostic& { return AddResultError(inst, i); }); + } + + auto ops = inst->Operands(); + for (size_t i = 0; i < ops.Length(); ++i) { + auto* op = ops[i]; + if (!op) { + continue; + } + + CheckType(op->Type(), [&]() -> diag::Diagnostic& { return AddError(inst, i); }); + } + + tint::Switch( + inst, // + [&](const Access* a) { CheckAccess(a); }, // + [&](const Binary* b) { CheckBinary(b); }, // + [&](const Call* c) { CheckCall(c); }, // + [&](const If* if_) { CheckIf(if_); }, // + [&](const Let* let) { CheckLet(let); }, // + [&](const Load* load) { CheckLoad(load); }, // + [&](const LoadVectorElement* l) { CheckLoadVectorElement(l); }, // + [&](const Loop* l) { CheckLoop(l); }, // + [&](const Phony* p) { CheckPhony(p); }, // + [&](const Store* s) { CheckStore(s); }, // + [&](const StoreVectorElement* s) { CheckStoreVectorElement(s); }, // + [&](const Switch* s) { CheckSwitch(s); }, // + [&](const Swizzle* s) { CheckSwizzle(s); }, // + [&](const Terminator* b) { CheckTerminator(b); }, // + [&](const Unary* u) { CheckUnary(u); }, // + [&](const Override* o) { CheckOverride(o); }, // + [&](const Var* var) { CheckVar(var); }, // + [&](const Default) { AddError(inst) << "missing validation"; }); + + for (auto* result : results) { + scope_stack_.Add(result); + } +} + +void Validator::CheckOverride(const Override* o) { + // Intentionally not checking operands, since Override may have a null operand + if (!CheckResults(o, Override::kNumResults)) { + return; + } + + if (o->OverrideId().has_value()) { + if (!seen_override_ids_.Add(o->OverrideId().value())) { + AddError(o) << "duplicate override id encountered: " << o->OverrideId().value().value; + return; + } + } + + if (!o->Result()->Type()->IsScalar()) { + AddError(o) << "override type " << NameOf(o->Result()->Type()) << " is not a scalar"; + return; + } + + if (o->Initializer()) { + if (!CheckOperand(o, ir::Var::kInitializerOperandOffset)) { + return; + } + if (o->Initializer()->Type() != o->Result()->Type()) { + AddError(o) << "override type " << NameOf(o->Result()->Type()) + << " does not match initializer type " << NameOf(o->Initializer()->Type()); + return; + } + } + + if (!o->OverrideId().has_value() && (o->Initializer() == nullptr)) { + AddError(o) << "must have an id or an initializer"; + return; + } +} + +void Validator::CheckVar(const Var* var) { + if (!CheckResultsAndOperands(var, Var::kNumResults, Var::kNumOperands)) { + return; + } + + auto* result_type = var->Result()->Type(); + auto* mv = result_type->As(); + if (!mv) { + AddError(var) << "result type " << NameOf(result_type) + << " must be a pointer or a reference"; + return; + } + + if (var->Block() != mod_.root_block && mv->AddressSpace() != AddressSpace::kFunction) { + if (!capabilities_.Contains(Capability::kMslAllowEntryPointInterface) || + mv->AddressSpace() != AddressSpace::kPrivate) { + AddError(var) << "vars in a function scope must be in the 'function' address space"; + return; + } + } + + // Check that initializer and result type match + if (var->Initializer()) { + if (mv->AddressSpace() != AddressSpace::kFunction && + mv->AddressSpace() != AddressSpace::kPrivate && + mv->AddressSpace() != AddressSpace::kOut) { + AddError(var) << "only variables in the function, private, or __out address space may " + "be initialized"; + return; + } + + if (!CheckOperand(var, ir::Var::kInitializerOperandOffset)) { + return; + } + + if (var->Initializer()->Type() != result_type->UnwrapPtrOrRef()) { + AddError(var) << "initializer type " << NameOf(var->Initializer()->Type()) + << " does not match store type " << NameOf(result_type->UnwrapPtrOrRef()); + return; + } + } + + CheckBindingPoint(var, var->Result(0)->Type(), var->Attributes(), + ShaderIOKind::kModuleScopeVar); + + if (var->Block() == mod_.root_block && mv->AddressSpace() == AddressSpace::kFunction) { + AddError(var) << "vars in the 'function' address space must be in a function scope"; + return; + } + + if (mv->AddressSpace() == AddressSpace::kWorkgroup) { + if (auto* ary = result_type->UnwrapPtr()->As()) { + if (auto* count = ary->Count()->As()) { + if (!scope_stack_.Contains(count->value)) { + AddError(var) << NameOf(count->value) << " is not in scope"; + } + } + } + } + + if (mv->AddressSpace() == AddressSpace::kStorage) { + if (mv->StoreType() && !mv->StoreType()->IsHostShareable()) { + AddError(var) << "vars in the 'storage' address space must be host-shareable"; + return; + } + if (mv->Access() != core::Access::kReadWrite && mv->Access() != core::Access::kRead) { + AddError(var) + << "vars in the 'storage' address space must have access 'read' or 'read-write'"; + return; + } + } + + if (mv->AddressSpace() == AddressSpace::kUniform) { + if (!(mv->StoreType()->IsConstructible() || mv->StoreType()->Is()) || + !mv->StoreType()->IsHostShareable()) { + AddError(var) << "vars in the 'uniform' address space must be host-shareable and " + "constructible or a buffer"; + return; + } + } + + if (mv->AddressSpace() == AddressSpace::kImmediate) { + if (mv->StoreType() && !mv->StoreType()->IsHostShareable()) { + AddError(var) << "vars in the 'immediate' address space must be host-shareable"; + return; + } + } + + if (var->InputAttachmentIndex().has_value()) { + if (mv->AddressSpace() != AddressSpace::kHandle) { + AddError(var) << "'@input_attachment_index' is not valid for non-handle var"; + return; + } + if (!capabilities_.Contains(Capability::kAllowAnyInputAttachmentIndexType) && + !mv->UnwrapPtrOrRef()->Is()) { + AddError(var) + << "'@input_attachment_index' is only valid for 'input_attachment' type var"; + return; + } + } + + if (var->Block() == mod_.root_block) { + if (mv->AddressSpace() == AddressSpace::kIn || mv->AddressSpace() == AddressSpace::kOut) { + ValidateShaderIOAnnotations(var, var->Result()->Type(), var->BindingPoint(), + var->Attributes(), ShaderIOKind::kModuleScopeVar); + } + } + + if (mv->AddressSpace() == core::AddressSpace::kPixelLocal) { + if (var->Block() == mod_.root_block) { + if (!mv->StoreType()->Is()) { + AddError(var) << "pixel_local var must be of type struct"; + return; + } + } + } +} + +void Validator::CheckBlendSrc(BlendSrcContext& ctx, + const CastableBase* target, + const core::type::Type* ty, + const IOAttributes& attr) { + if (attr.blend_src.has_value()) { + if (!capabilities_.Contains(Capability::kLoosenValidationForShaderIO)) { + AddError(target) << "blend_src cannot be used on non-struct-member types"; + } + CheckBlendSrcImpl(ctx, target, ty, attr); + } + + if (auto* s = ty->As()) { + if (s->Members().Any([](auto* m) { return m->Attributes().blend_src.has_value(); })) { + auto location_count = 0u; + for (const auto* mem : s->Members()) { + auto& mem_attr = mem->Attributes(); + if (mem_attr.location.has_value()) { + location_count++; + } + CheckBlendSrcImpl(ctx, target, mem->Type(), mem_attr); + } + + if (location_count != 2) { + AddError(target) + << "structs with blend_src members must have exactly 2 members with " + "location annotations"; + } + return; + } + } + + // Reject blend_src on nested members + if (!capabilities_.Contains(Capability::kLoosenValidationForShaderIO)) { + WalkTypeAndMembers( + ctx, ty, attr, + [&target, this](BlendSrcContext&, const core::type::Type*, const IOAttributes& a) { + if (a.blend_src.has_value()) { + AddError(target) + << "blend_src cannot be used on members of non-top level structs"; + } + }); + } +} + +void Validator::CheckBlendSrcImpl(BlendSrcContext& ctx, + const CastableBase* target, + const core::type::Type* ty, + const IOAttributes& attr) { + if (!attr.blend_src.has_value()) { + return; + } + + auto bs_val = attr.blend_src.value(); + if (bs_val != 0 && bs_val != 1) { + AddError(target) << "blend_src value must be 0 or 1"; + } + if (!ctx.blend_srcs.Add(bs_val)) { + AddError(target) << "duplicate blend_src(" << bs_val << ") on entry point " + << ToString(ctx.dir); + } + + if (ctx.dir != IODirection::kOutput || ctx.stage != Function::PipelineStage::kFragment) { + AddError(target) << "blend_src can only be used on fragment shader outputs"; + return; + } + if (!attr.location.has_value() || attr.location.value() != 0) { + AddError(target) << "struct members with blend_src must be located at 0"; + } + + if (!ctx.blend_src_type) { + if (!ty->IsNumericScalarOrVector()) { + AddError(target) << "blend_src must be a numeric scalar or vector, but has type " + << ty->FriendlyName(); + } + ctx.blend_src_type = ty; + } else if (ctx.blend_src_type != ty) { + AddError(target) << "blend_src type " << ty->FriendlyName() + << " does not match other blend_src type " + << ctx.blend_src_type->FriendlyName(); + } +} + +void Validator::CheckLocation(Hashmap& locations, + const CastableBase* target, + const IOAttributes& attr, + const Function::PipelineStage stage, + const core::type::Type* type, + const IODirection dir) { + struct WalkContext { + Validator* validator; + Hashmap& locations; + const CastableBase* target; + const Function::PipelineStage stage; + const IODirection dir; + }; + WalkContext ctx{this, locations, target, stage, dir}; + + WalkTypeAndMembers( + ctx, type, attr, + [](WalkContext& context, const core::type::Type* ty, const IOAttributes& attribute) { + if (ty->Is()) { + return; + } + + if (attribute.blend_src) { + // locations associated with a blend_src usage should already be + // pre-populated in locations + return; + } + + if (attribute.location.has_value()) { + if (context.stage == Function::PipelineStage::kCompute && + context.dir == IODirection::kInput) { + context.validator->AddError(context.target) + << "location attribute is not valid for compute shader inputs"; + } + + auto loc = attribute.location.value(); + if (const auto conflict = context.locations.Get(loc)) { + context.validator->AddError(context.target) + << "duplicate location(" << loc << ") on entry point " + << ToString(context.dir); + context.validator->AddDeclarationNote(*conflict.value); + } else { + context.locations.Add(loc, context.target); + } + } + }); +} + +void Validator::CheckInterpolation(const CastableBase* anchor, + const core::type::Type* ty, + const IOAttributes& attr) { + bool ctx = false; + + WalkTypeAndMembers( + ctx, ty, attr, + [this, anchor](bool& in_location_composite, const core::type::Type* t, + const IOAttributes& a) { + if (a.interpolation.has_value()) { + if (!capabilities_.Contains(Capability::kAllowLocationForNumericElements) && + t->As()) { + AddError(anchor) << "interpolation cannot be applied to a struct without " + "'kAllowLocationForNumericElements' capability"; + } + + bool has_location = a.location.has_value() || in_location_composite; + if (!has_location) { + if (auto* str = t->As()) { + has_location |= str->Members().All( + [](const auto* mem) { return mem->Attributes().location.has_value(); }); + } + } + has_location |= (capabilities_.Contains(Capability::kLoosenValidationForShaderIO) && + a.builtin.has_value()); + + if (!has_location) { + if (!capabilities_.Contains(Capability::kLoosenValidationForShaderIO)) { + AddError(anchor) << "interpolation attribute requires a location attribute"; + } else { + AddError(anchor) << "interpolation attribute requires a location attribute " + "(or location-like shader I/O annotation)"; + } + } + } + + in_location_composite |= a.location.has_value(); + }); +} + +void Validator::CheckBindingPoint(const CastableBase* anchor, + const core::type::Type* ty, + const IOAttributes& attr, + const ShaderIOKind& io_kind) { + const auto& binding_point = attr.binding_point; + auto address_space = AddressSpace::kUndefined; + if (const auto* mv = ty->As()) { + address_space = mv->AddressSpace(); + } else { + // ModuleScopeVars transform in MSL backends unwraps pointers to handles + if (ty->IsHandle()) { + address_space = AddressSpace::kHandle; + } + } + + if (binding_point.has_value() && io_kind != ShaderIOKind::kModuleScopeVar && + !capabilities_.Contains(Capability::kMslAllowEntryPointInterface)) { + AddError(anchor) << "binding_points are only valid on resource variables"; + } + + switch (address_space) { + case AddressSpace::kHandle: + if (!capabilities_.Contains(Capability::kAllowHandleVarsWithoutBindings)) { + if (!binding_point.has_value()) { + AddError(anchor) + << "a " << ToString(address_space) << " resource requires a binding point"; + } + } + break; + case AddressSpace::kStorage: + case AddressSpace::kUniform: + if (!binding_point.has_value()) { + AddError(anchor) << "a " << ToString(address_space) + << " resource requires a binding point"; + } + break; + default: + if (binding_point.has_value()) { + AddError(anchor) << "a " << ToString(address_space) + << " non-resource cannot have a binding point"; + } + break; + } +} + +void Validator::ValidateShaderIOAnnotations(const CastableBase* msg_anchor, + const core::type::Type* ty, + const std::optional& binding_point, + const IOAttributes& attr, + ShaderIOKind kind) { + EnumSet annotations; + + // Since there is no entries in the set at this point, this should never fail. + TINT_ASSERT(AddIOAnnotationsFromIOAttributes(annotations, attr) == Success); + + if (binding_point.has_value()) { + annotations.Add(IOAnnotation::kBindingPoint); + } + + if (auto* mv = ty->As()) { + if (mv->AddressSpace() == AddressSpace::kWorkgroup) { + annotations.Add(IOAnnotation::kWorkgroup); + } + } + + if (ty->Is()) { + if (!annotations.Empty()) { + AddError(msg_anchor) << ToString(kind) << " with void type should never be annotated"; + } + return; // Early return because later rules assume non-void types. + } + + if (attr.location.has_value()) { + if (capabilities_.Contains(Capability::kAllowLocationForNumericElements)) { + std::function is_numeric = + [&is_numeric](const core::type::Type* t) -> bool { + t = t->UnwrapPtrOrRef(); + bool result = false; + tint::Switch( + t, + [&](const core::type::Struct* s) { + for (auto* m : s->Members()) { + if (!is_numeric(m->Type())) { + return; + } + } + result = true; + }, + [&](Default) { + auto* e = t->DeepestElement()->UnwrapPtrOrRef(); + tint::Switch( + e, [&](const core::type::Struct* s) { result = is_numeric(s); }, + [&](Default) { result = e->IsNumericScalarOrVector(); }); + }); + return result; + }; + if (!is_numeric(ty)) { + AddError(msg_anchor) + << ToString(kind) + << " with a location attribute must contain only numeric elements " + << ty->FriendlyName(); + return; + } + } else { + if (!ty->UnwrapPtrOrRef()->IsNumericScalarOrVector()) { + AddError(msg_anchor) << ToString(kind) + << " with a location attribute must be a numeric scalar or " + "vector, but has type " + << ty->FriendlyName(); + return; + } + } + } + + if (auto* ty_struct = ty->UnwrapPtrOrRef()->As()) { + for (const auto* mem : ty_struct->Members()) { + EnumSet mem_annotations = annotations; + auto add_result = AddIOAnnotationsFromIOAttributes(mem_annotations, mem->Attributes()); + if (add_result != Success) { + AddError(msg_anchor) + << ToString(kind) + << " struct member has same IO annotation, as top-level struct, '" + << ToString(add_result.Failure()) << "'"; + return; + } + + if (mem->Attributes().location.has_value()) { + if (capabilities_.Contains(Capability::kAllowLocationForNumericElements)) { + if (!mem->Type()->UnwrapPtrOrRef()->IsNumericScalarOrVector() && + !mem->Type()->UnwrapPtrOrRef()->Is()) { + AddError(msg_anchor) + << ToString(kind) + << " struct member with a location attribute must be a numeric scalar, " + "a numeric vector or a struct, but has type " + << mem->Type()->FriendlyName(); + return; + } + } else { + if (!mem->Type()->UnwrapPtrOrRef()->IsNumericScalarOrVector()) { + AddError(msg_anchor) << ToString(kind) + << " struct member with a location attribute must be " + "a numeric scalar or vector, but has type " + << mem->Type()->FriendlyName(); + return; + } + } + } + + if (capabilities_.Contains(Capability::kMslAllowEntryPointInterface)) { + if (auto* mv = mem->Type()->As()) { + if (mv->AddressSpace() == AddressSpace::kWorkgroup) { + mem_annotations.Add(IOAnnotation::kWorkgroup); + } + } + } + + if (mem_annotations.Empty()) { + AddError(msg_anchor) << ToString(kind) + << " struct members must have at least one IO annotation, " + "e.g. a binding point, a location, etc"; + } else if (mem_annotations.Size() > 1) { + AddError(msg_anchor) + << ToString(kind) << " struct member has more than one IO annotation, " + << ToString(mem_annotations); + } + } + } else { + if (annotations.Empty()) { + if (!(capabilities_.Contains(Capability::kAllowUnannotatedModuleIOVariables) && + kind == ShaderIOKind::kModuleScopeVar)) { + AddError(msg_anchor) << ToString(kind) + << " must have at least one IO annotation, e.g. a binding " + "point, a location, etc"; + } + } else if (annotations.Size() > 1) { + AddError(msg_anchor) << ToString(kind) << " has more than one IO annotation, " + << ToString(annotations); + } + } +} + +void Validator::CheckLet(const Let* l) { + if (!CheckResultsAndOperands(l, Let::kNumResults, Let::kNumOperands)) { + return; + } + + auto* value_ty = l->Value()->Type(); + if (capabilities_.Contains(Capability::kAllowAnyLetType)) { + if (value_ty->Is()) { + AddError(l) << "value type cannot be void"; + } + } else { + if (!value_ty->IsConstructible() && !value_ty->Is()) { + AddError(l) << "value type, " << NameOf(value_ty) + << ", must be concrete constructible type or a pointer type"; + } + } + + auto* result_ty = l->Result()->Type(); + if (!capabilities_.Contains(Capability::kAllowAnyLetType)) { + if (auto* ptr = result_ty->As()) { + if (ptr->AddressSpace() == AddressSpace::kHandle && + !capabilities_.Contains(Capability::kAllowPointerToHandle)) { + AddError(l) << "handle pointer cannot be captured in a let"; + } + } else if (!result_ty->IsConstructible()) { + AddError(l) << "result type, " << NameOf(result_ty) + << ", must be concrete constructible type or a pointer type"; + } + } + + if (value_ty != result_ty) { + AddError(l) << "result type " << NameOf(l->Result()->Type()) + << " does not match value type " << NameOf(l->Value()->Type()); + } +} + +void Validator::CheckCall(const Call* call) { + tint::Switch( + call, // + [&](const Bitcast* b) { CheckBitcast(b); }, // + [&](const BuiltinCall* c) { CheckBuiltinCall(c); }, // + [&](const MemberBuiltinCall* c) { CheckMemberBuiltinCall(c); }, // + [&](const Construct* c) { CheckConstruct(c); }, // + [&](const Convert* c) { CheckConvert(c); }, // + [&](const Discard* d) { // + stage_restricted_instructions_.Add( + d, SupportedStages{Function::PipelineStage::kFragment}); // + CheckDiscard(d); // + }, // + [&](const UserCall* c) { // + if (c->Target()) { // + auto calls = // + user_func_calls_.GetOr(c->Target(), // + Hashset{}); // + calls.Add(c); // + user_func_calls_.Replace(c->Target(), calls); // + } + CheckUserCall(c); + }, + [&](Default) { + // Validation of custom IR instructions + }); +} + +void Validator::CheckBitcast(const Bitcast* bitcast) { + if (!CheckResultsAndOperands(bitcast, Bitcast::kNumResults, Bitcast::kNumOperands)) { + return; + } + + CheckBitcastTypes(bitcast); +} + +void Validator::CheckBitcastTypes(const Bitcast* bitcast) { + // Caller is responsible for checking results and operands + const auto* val_type = bitcast->Operand(Bitcast::kValueOperandOffset)->Type(); + const auto* result_type = bitcast->Result()->Type(); + + const auto add_error = [&]() { + AddError(bitcast) << "bitcast is not defined for " << NameOf(val_type) << " -> " + << NameOf(result_type); + }; + + // Check that there exists an overload for the provided types + if (val_type->IsAnyOf()) { + // S, where S is i32, u32, or f32 + // S -> S, identity and reinterpretation + if (result_type->IsAnyOf()) { + return; + } + + // S -> vec2 + if (auto* vec_type = result_type->As()) { + auto elements = vec_type->Elements(); + if (elements.count == 2 && Is(elements.type)) { + return; + } + } + } else if (val_type->Is()) { + // f16 -> f16, identity + if (result_type->Is()) { + return; + } + } else if (val_type->Is()) { + auto val_elements = val_type->Elements(); + if (!val_elements.type) { + // Malformed vector + add_error(); + return; + } + + std::optional result_elements; + if (result_type->As()) { + result_elements = result_type->Elements(); + if (!result_elements->type) { + // Malformed vector + add_error(); + return; + } + } + + if (val_elements.type->IsAnyOf()) { + // vecN, where S is i32, u32, or f32 + // vecN -> vecN, identity and reinterpretation cases + if (result_elements.has_value() && val_elements.count == result_elements->count && + result_elements->type + ->IsAnyOf()) { + return; + } + + // vec2 -> vec4 + if (val_elements.count == 2) { + if (result_elements.has_value() && result_elements->count == 4 && + result_elements->type->Is()) { + return; + } + } + } else if (val_elements.type->Is()) { + if (result_elements.has_value()) { + if (result_elements->type->Is()) { + // vecN -> vecN, identity + if (val_elements.count == result_elements->count) { + return; + } + } else { + // vec4 -> vec2, where S is i32, u32, or f32 + if (val_elements.count == 4 && result_elements->count == 2 && + result_elements->type + ->IsAnyOf()) { + return; + } + } + } else { + // vec2 -> i32, u32, or f32 + if (val_elements.count == 2 && + result_type->IsAnyOf()) { + return; + } + } + } + } + + // No matching case for val and result type combination + add_error(); +} + +void Validator::CheckBuiltinCall(const BuiltinCall* call) { + // This check cannot be more precise, since until intrinsic lookup below, it is unknown what + // number of operands are expected, but still need to enforce things are in scope, + // have types, etc. + if (!CheckResults(call, BuiltinCall::kNumResults) || !CheckOperands(call)) { + return; + } + + // CheckOperands above ensures that all args are non-null and have a valid type + auto args = Transform<8>(call->Args(), [&](const ir::Value* v) { return v->Type(); }); + + intrinsic::Context context{ + call->TableData(), + type_mgr_, + symbols_, + }; + + auto builtin = core::intrinsic::LookupFn(context, call->FriendlyName().c_str(), call->FuncId(), + call->ExplicitTemplateParams(), args, + core::EvaluationStage::kRuntime); + if (builtin != Success) { + AddError(call) << builtin.Failure(); + return; + } + + TINT_ASSERT(builtin->return_type); + + if (builtin->return_type != call->Result()->Type()) { + AddError(call) << "call result type " << NameOf(call->Result()->Type()) + << " does not match builtin return type " << NameOf(builtin->return_type); + return; + } + + if (auto* bc = call->As()) { + CheckCoreBuiltinCall(bc, builtin.Get()); + } + + // Track the stages that this builtin call is limited to, so that we can check them against the + // entry points that they are used from. + SupportedStages stages; + if (builtin->info->flags.Contains(intrinsic::OverloadFlag::kSupportsComputePipeline)) { + stages.Add(Function::PipelineStage::kCompute); + } + if (builtin->info->flags.Contains(intrinsic::OverloadFlag::kSupportsFragmentPipeline)) { + stages.Add(Function::PipelineStage::kFragment); + } + if (builtin->info->flags.Contains(intrinsic::OverloadFlag::kSupportsVertexPipeline)) { + stages.Add(Function::PipelineStage::kVertex); + } + stage_restricted_instructions_.Add(call, stages); +} + +void Validator::CheckCoreBuiltinCall(const CoreBuiltinCall* call, + const core::intrinsic::Overload& overload) { + if (call->Func() == core::BuiltinFn::kQuadBroadcast || + call->Func() == core::BuiltinFn::kSubgroupBroadcast) { + TINT_ASSERT(call->Args().Length() == 2); + constexpr uint32_t kIdArg = 1; + auto* id = call->Args()[kIdArg]; + if (!id->Is()) { + AddError(call, kIdArg) << "non-constant ID provided"; + } + return; + } + + auto idx_for_usage = [&](core::ParameterUsage usage) -> std::optional { + for (uint32_t i = 0; i < overload.parameters.Length(); ++i) { + auto& p = overload.parameters[i]; + if (p.usage == usage) { + return int32_t(i); + } + } + return std::nullopt; + }; + + auto check_arg_in_range = [&](core::ParameterUsage usage, int32_t min, int32_t max) { + auto idx_opt = idx_for_usage(usage); + if (!idx_opt.has_value()) { + return; + } + uint32_t idx = idx_opt.value(); + TINT_ASSERT(idx < call->Args().Length()); + + auto* val = call->Args()[idx]; + if (auto* const_val = val->As()) { + auto* cnst = const_val->Value(); + + if (val->Type()->Is()) { + for (size_t i = 0; i < cnst->NumElements(); i++) { + auto value = cnst->Index(i)->ValueAs(); + if (value < min || value > max) { + AddError(call, idx) + << value << " outside range of [" << min << ", " << max << "]"; + return; + } + } + } else { + auto value = cnst->ValueAs(); + if (value < min || value > max) { + AddError(call, idx) + << value << " outside range of [" << min << ", " << max << "]"; + return; + } + } + } else { + AddError(call, idx) << "expected a constant value"; + return; + } + }; + + check_arg_in_range(core::ParameterUsage::kComponent, 0, 3); + check_arg_in_range(core::ParameterUsage::kOffset, -8, 7); +} + +void Validator::CheckMemberBuiltinCall(const MemberBuiltinCall* call) { + // This check cannot be more precise, since until intrinsic lookup below, it is unknown what + // number of operands are expected, but still need to enforce things are in scope, + // have types, etc. + if (!CheckResults(call, MemberBuiltinCall::kNumResults) || !CheckOperands(call)) { + return; + } + + auto args = Vector({call->Object()->Type()}); + for (auto* arg : call->Args()) { + args.Push(arg->Type()); + } + intrinsic::Context context{ + call->TableData(), + type_mgr_, + symbols_, + }; + + auto result = core::intrinsic::LookupMemberFn(context, call->FriendlyName().c_str(), + call->FuncId(), call->ExplicitTemplateParams(), + std::move(args), core::EvaluationStage::kRuntime); + if (result != Success) { + AddError(call) << result.Failure(); + return; + } + + if (result->return_type != call->Result()->Type()) { + AddError(call) << "member call result type " << NameOf(call->Result()->Type()) + << " does not match builtin return type " << NameOf(result->return_type); + } +} + +void Validator::CheckConstruct(const Construct* construct) { + if (!CheckResultsAndOperandRange(construct, Construct::kNumResults, Construct::kMinOperands)) { + return; + } + + auto* result_type = construct->Result()->Type(); + + if (!result_type->IsConstructible()) { + // We only allow `construct` to create non-constructible types when they are structures that + // contain pointers and handle types, with the corresponding capability enabled. + if (!(result_type->Is() && + capabilities_.Contains(Capability::kMslAllowEntryPointInterface))) { + AddError(construct) << "type is not constructible"; + return; + } + } + + auto args = construct->Args(); + if (args.IsEmpty()) { + // Zero-value constructors are valid for all constructible types. + return; + } + + auto check_args_match_elements = [&] { + // Check that type type of each argument matches the expected element type of the composite. + for (size_t i = 0; i < args.Length(); i++) { + if (args[i]->Is()) { + continue; + } + auto* expected_type = result_type->Element(static_cast(i)); + if (args[i]->Type() != expected_type) { + AddError(construct, Construct::kArgsOperandOffset + i) + << "type " << NameOf(args[i]->Type()) << " of argument " << i + << " does not match expected type " << NameOf(expected_type); + } + } + }; + + if (result_type->Is()) { + // The only valid non-zero scalar constructor is the identity operation. + if (args.Length() > 1) { + AddError(construct) << "scalar construct must not have more than one argument"; + } + if (args[0]->Type() != result_type) { + AddError(construct, 0u) << "scalar construct argument type " << NameOf(args[0]->Type()) + << " does not match result type " << NameOf(result_type); + } + } else if (auto* sg_mat = result_type->As()) { + if (args.Length() > 1) { + AddError(construct) << "subgroup matrix construct must not have more than 1 argument"; + } else { + // 8-bit integer matrices use 32-bit shader scalar types in WGSL. + // Some backends may support 8-bit integers, in which case they would pass an 8-bit + // type for the constructor value instead. + auto* scalar_ty = sg_mat->Type(); + if (scalar_ty->Is()) { + scalar_ty = type_mgr_.i32(); + } else if (scalar_ty->Is()) { + scalar_ty = type_mgr_.u32(); + } + if (args[0]->Type() != scalar_ty && args[0]->Type() != sg_mat->Type()) { + AddError(construct) + << "subgroup matrix construct argument type " << NameOf(args[0]->Type()) + << " does not match matrix shader scalar type " << NameOf(scalar_ty); + } + } + } else if (auto* vec = result_type->As()) { + auto table = intrinsic::Table(type_mgr_, symbols_); + auto ctor_conv = intrinsic::VectorCtorConv(vec->Width()); + auto arg_types = Transform<4>(args, [&](auto* v) { return v->Type(); }); + auto match = table.Lookup(ctor_conv, Vector{vec->Type()}, std::move(arg_types), + core::EvaluationStage::kConstant); + if (match != Success || vec->Type() != arg_types[0]->DeepestElement()) { + AddError(construct) << "no matching overload for " << vec->FriendlyName() + << " constructor"; + } + } else if (auto* mat = result_type->As()) { + auto table = intrinsic::Table(type_mgr_, symbols_); + auto ctor_conv = intrinsic::MatrixCtorConv(mat->Columns(), mat->Rows()); + auto arg_types = Transform<8>(args, [&](auto* v) { return v->Type(); }); + auto match = table.Lookup(ctor_conv, Vector{mat->Type()}, std::move(arg_types), + core::EvaluationStage::kConstant); + if (match != Success) { + AddError(construct) << "no matching overload for " << mat->FriendlyName() + << " constructor"; + } + } else if (auto* arr = result_type->As()) { + if (args.Length() != arr->ConstantCount()) { + AddError(construct) << "array has " << arr->ConstantCount().value() + << " elements, but construct provides " << args.Length() + << " arguments"; + return; + } + check_args_match_elements(); + } else if (auto* str = As(result_type)) { + auto members = str->Members(); + if (args.Length() != str->Members().Length()) { + AddError(construct) << "structure has " << members.Length() + << " members, but construct provides " << args.Length() + << " arguments"; + return; + } + check_args_match_elements(); + } +} + +void Validator::CheckConvert(const Convert* convert) { + if (!CheckResultsAndOperands(convert, Convert::kNumResults, Convert::kNumOperands)) { + return; + } + + auto* result_type = convert->Result()->Type(); + auto* value_type = convert->Operand(Convert::kValueOperandOffset)->Type(); + + intrinsic::CtorConv conv_ty; + Vector template_type; + tint::Switch( + result_type, // + [&](const core::type::I32*) { conv_ty = intrinsic::CtorConv::kI32; }, // + [&](const core::type::U32*) { conv_ty = intrinsic::CtorConv::kU32; }, // + [&](const core::type::F32*) { conv_ty = intrinsic::CtorConv::kF32; }, // + [&](const core::type::F16*) { conv_ty = intrinsic::CtorConv::kF16; }, // + [&](const core::type::Bool*) { conv_ty = intrinsic::CtorConv::kBool; }, // + [&](const core::type::Vector* v) { + conv_ty = intrinsic::VectorCtorConv(v->Width()); + template_type.Push(v->Type()); + }, + [&](const core::type::Matrix* m) { + conv_ty = intrinsic::MatrixCtorConv(m->Columns(), m->Rows()); + template_type.Push(m->Type()); + }, + [&](Default) { conv_ty = intrinsic::CtorConv::kNone; }); + + if (conv_ty == intrinsic::CtorConv::kNone) { + AddError(convert) << "not defined for result type, " << NameOf(result_type); + return; + } + + auto table = intrinsic::Table(type_mgr_, symbols_); + auto match = + table.Lookup(conv_ty, template_type, Vector{value_type}, core::EvaluationStage::kOverride); + if (match != Success || !match->info->flags.Contains(intrinsic::OverloadFlag::kIsConverter)) { + AddError(convert) << "No defined converter for " << NameOf(value_type) << " -> " + << NameOf(result_type); + return; + } +} + +void Validator::CheckDiscard(const tint::core::ir::Discard* discard) { + CheckResultsAndOperands(discard, Discard::kNumResults, Discard::kNumOperands); +} + +void Validator::CheckUserCall(const UserCall* call) { + if (!CheckResultsAndOperandRange(call, UserCall::kNumResults, UserCall::kMinOperands)) { + return; + } + + if (!call->Target()) { + AddError(call, UserCall::kFunctionOperandOffset) << "target not defined or not a function"; + return; + } + + if (call->Target()->IsEntryPoint()) { + AddError(call, UserCall::kFunctionOperandOffset) + << "call target must not have a pipeline stage"; + } + + if (call->Target()->ReturnType() != call->Result()->Type()) { + AddError(call) << "result type does not match function return type"; + return; + } + + auto args = call->Args(); + auto params = call->Target()->Params(); + if (args.Length() != params.Length()) { + AddError(call, UserCall::kFunctionOperandOffset) + << "function has " << params.Length() << " parameters, but call provides " + << args.Length() << " arguments"; + return; + } + + for (size_t i = 0; i < args.Length(); i++) { + if (args[i]->Type() != params[i]->Type()) { + AddError(call, UserCall::kArgsOperandOffset + i) + << "type " << NameOf(params[i]->Type()) << " of function parameter " << i + << " does not match argument type " << NameOf(args[i]->Type()); + } + } +} + +void Validator::CheckAccess(const Access* a) { + if (!CheckResultsAndOperandRange(a, Access::kNumResults, Access::kMinNumOperands)) { + return; + } + + auto* obj_view = a->Object()->Type()->As(); + auto* ty = obj_view ? obj_view->StoreType() : a->Object()->Type(); + + enum Kind : uint8_t { kPtr, kRef, kValue }; + + auto kind_of = [&](const core::type::Type* type) { + return tint::Switch( + type, // + [&](const core::type::Pointer*) { return kPtr; }, // + [&](const core::type::Reference*) { return kRef; }, // + [&](Default) { return kValue; }); + }; + + const Kind in_kind = kind_of(a->Object()->Type()); + auto desc_of = [&](Kind kind, const core::type::Type* type) { + switch (kind) { + case kPtr: + return StyledText{} + << style::Type("ptr<", obj_view->AddressSpace(), ", ", type->FriendlyName(), + ", ", obj_view->Access(), ">"); + case kRef: + return StyledText{} + << style::Type("ref<", obj_view->AddressSpace(), ", ", type->FriendlyName(), + ", ", obj_view->Access(), ">"); + default: + return NameOf(type); + } + }; + + for (size_t i = 0; i < a->Indices().Length(); i++) { + auto err = [&]() -> diag::Diagnostic& { + return AddError(a, i + Access::kIndicesOperandOffset); + }; + auto note = [&]() -> diag::Diagnostic& { + return AddOperandNote(a, i + Access::kIndicesOperandOffset); + }; + + auto* index = a->Indices()[i]; + if (DAWN_UNLIKELY(!index->Type() || !index->Type()->IsIntegerScalar())) { + err() << "index type " << NameOf(index->Type()) << " must be an integer"; + return; + } + + if (!capabilities_.Contains(Capability::kAllowVectorElementPointer)) { + if (in_kind != kValue && ty->Is()) { + err() << "cannot obtain address of vector element"; + return; + } + } + + if (auto* const_index = index->As()) { + auto* value = const_index->Value(); + if (!value->Type() || value->Type()->IsSignedIntegerScalar()) { + // index is a signed integer scalar. Check that the index isn't negative. + // If the index is unsigned, we can skip this. + auto idx = value->ValueAs(); + if (DAWN_UNLIKELY(idx < 0)) { + err() << "constant index must be positive, got " << idx; + return; + } + } + + auto idx = value->ValueAs(); + auto* el = ty->Element(idx); + if (DAWN_UNLIKELY(!el)) { + // Is index in bounds? + if (auto el_count = ty->Elements().count; el_count != 0 && idx >= el_count) { + err() << "index out of bounds for type " << desc_of(in_kind, ty); + note() << "acceptable range: [0.." << (el_count - 1) << "]"; + return; + } + err() << "type " << desc_of(in_kind, ty) << " cannot be indexed"; + return; + } + ty = el; + } else { + auto* el = ty->Elements().type; + if (DAWN_UNLIKELY(!el)) { + err() << "type " << desc_of(in_kind, ty) << " cannot be dynamically indexed"; + return; + } + ty = el; + } + } + + auto* want = a->Result()->Type(); + auto* want_view = want->As(); + bool ok = true; + if (obj_view) { + // Pointer source always means pointer result. + ok = (want_view != nullptr) && ty == want_view->StoreType(); + if (ok) { + // Also check that the address space and access modes match. + ok = obj_view->Is() == want_view->Is() && + obj_view->AddressSpace() == want_view->AddressSpace() && + obj_view->Access() == want_view->Access(); + } + } else { + // Otherwise, result types should exactly match. + ok = ty == want; + } + if (DAWN_UNLIKELY(!ok)) { + AddError(a) << "result of access chain is type " << desc_of(in_kind, ty) + << " but instruction type is " << NameOf(want); + } +} + +void Validator::CheckBinary(const Binary* b) { + if (!CheckResultsAndOperands(b, Binary::kNumResults, Binary::kNumOperands)) { + return; + } + + if (b->Op() == core::BinaryOp::kLogicalAnd) { + AddError(b) << "logical-and is not valid in the IR"; + return; + } + if (b->Op() == core::BinaryOp::kLogicalOr) { + AddError(b) << "logical-or is not valid in the IR"; + return; + } + + if (b->LHS() && b->RHS()) { + intrinsic::Context context{b->TableData(), type_mgr_, symbols_}; + + auto overload = + core::intrinsic::LookupBinary(context, b->Op(), b->LHS()->Type(), b->RHS()->Type(), + core::EvaluationStage::kRuntime, /* is_compound */ false); + if (overload != Success) { + AddError(b) << overload.Failure(); + return; + } + + if (auto* result = b->Result(0)) { + if (overload->return_type != result->Type()) { + AddError(b) << "result value type " << NameOf(result->Type()) << " does not match " + << style::Instruction(Disassemble().NameOf(b->Op())) << " result type " + << NameOf(overload->return_type); + } + } + } +} + +void Validator::CheckUnary(const Unary* u) { + if (!CheckResultsAndOperands(u, Unary::kNumResults, Unary::kNumOperands)) { + return; + } + + if (u->Val()) { + intrinsic::Context context{u->TableData(), type_mgr_, symbols_}; + + auto overload = core::intrinsic::LookupUnary(context, u->Op(), u->Val()->Type(), + core::EvaluationStage::kRuntime); + if (overload != Success) { + AddError(u) << overload.Failure(); + return; + } + + if (auto* result = u->Result(0)) { + if (overload->return_type != result->Type()) { + AddError(u) << "result value type " << NameOf(result->Type()) << " does not match " + << style::Instruction(Disassemble().NameOf(u->Op())) << " result type " + << NameOf(overload->return_type); + } + } + } +} + +void Validator::CheckIf(const If* if_) { + CheckResults(if_); + CheckOperands(if_, If::kNumOperands); + + if (if_->Condition() && !if_->Condition()->Type()->Is()) { + AddError(if_, If::kConditionOperandOffset) << "condition type must be 'bool'"; + } + + if (if_->False() && if_->False()->Is()) { + AddError(if_) << "if false block must be a block"; + } + if (if_->True() && if_->True()->Is()) { + AddError(if_) << "if true block must be a block"; + } + + tasks_.Push([this] { control_stack_.Pop(); }); + + if (!if_->False()->IsEmpty()) { + QueueBlock(if_->False()); + } + + QueueBlock(if_->True()); + + tasks_.Push([this, if_] { control_stack_.Push(if_); }); +} + +void Validator::CheckLoop(const Loop* l) { + CheckResults(l); + CheckOperands(l, 0); + + if (!l->Initializer()->IsEmpty()) { + if (!l->Initializer()->Terminator() || + !l->Initializer()->Terminator()->Is()) { + AddError(l->Initializer()) << "loop initializer must have a NextIteration terminator"; + } + } + + // Note: Tasks are queued in reverse order of their execution + tasks_.Push([this, l] { + first_continues_.Remove(l); // No need for this any more. Free memory. + control_stack_.Pop(); + }); + if (!l->Initializer()->IsEmpty()) { + tasks_.Push([this] { EndBlock(); }); + } + tasks_.Push([this] { EndBlock(); }); + if (!l->Continuing()->IsEmpty()) { + tasks_.Push([this] { EndBlock(); }); + } + + // ⎡Initializer ⎤ + // ⎢ ⎡Body ⎤⎥ + // ⎣ ⎣ [Continuing ] ⎦⎦ + + if (!l->Continuing()->IsEmpty()) { + tasks_.Push([this, l] { + CheckLoopContinuing(l); + BeginBlock(l->Continuing()); + }); + } + + tasks_.Push([this, l] { + CheckLoopBody(l); + BeginBlock(l->Body()); + }); + if (!l->Initializer()->IsEmpty()) { + tasks_.Push([this, l] { BeginBlock(l->Initializer()); }); + } + tasks_.Push([this, l] { control_stack_.Push(l); }); +} + +void Validator::CheckLoopBody(const Loop* loop) { + // If the body block has parameters, there must be an initializer block. + if (!loop->Body()->Params().IsEmpty()) { + if (!loop->HasInitializer()) { + AddError(loop) << "loop with body block parameters must have an initializer"; + } + } +} + +void Validator::CheckLoopContinuing(const Loop* loop) { + if (!loop->HasContinuing()) { + return; + } + + // Ensure that values used in the loop continuing are not from the loop body, after a + // continue instruction. + if (auto* first_continue = first_continues_.GetOr(loop, nullptr)) { + // Find the instruction in the body block that is or holds the first continue + // instruction. + const Instruction* holds_continue = first_continue; + while (holds_continue && holds_continue->Block() && + holds_continue->Block() != loop->Body()) { + holds_continue = holds_continue->Block()->Parent(); + } + + // Check that all subsequent instruction values are not used in the continuing block. + for (auto* inst = holds_continue; inst; inst = inst->next) { + for (auto* result : inst->Results()) { + result->ForEachUseUnsorted([&](Usage use) { + if (TransitivelyHolds(loop->Continuing(), use.instruction)) { + AddError(use.instruction, use.operand_index) + << NameOf(result) + << " cannot be used in continuing block as it is declared after the " + "first " + << style::Instruction("continue") << " in the loop's body"; + AddDeclarationNote(result); + AddNote(first_continue) + << "loop body's first " << style::Instruction("continue"); + } + }); + } + } + } + + if (!loop->Continuing()->Terminator()->IsAnyOf()) { + AddError(loop->Continuing()) + << "loop continuing terminator can only be next_iteration or break_if"; + } +} + +void Validator::CheckSwitch(const Switch* s) { + CheckResults(s); + CheckOperands(s, Switch::kNumOperands); + + if (s->Condition() && !s->Condition()->Type()->IsIntegerScalar()) { + auto* cond_ty = s->Condition() ? s->Condition()->Type() : nullptr; + AddError(s, Switch::kConditionOperandOffset) + << "condition type " << NameOf(cond_ty) << " must be an integer scalar"; + } + + tasks_.Push([this] { control_stack_.Pop(); }); + + bool found_default = false; + for (auto& cse : s->Cases()) { + if (cse.block->Is()) { + AddError(s) << "case block must be a block"; + } + + if (cse.selectors.IsEmpty()) { + AddError(s) << "case does not have any selectors"; + } + + QueueBlock(cse.block); + for (const auto& sel : cse.selectors) { + if (sel.IsDefault()) { + if (found_default) { + AddError(s) << "multiple default selectors in switch"; + } + found_default = true; + } else if (!sel.val->Type()->IsIntegerScalar()) { + AddError(s) << "case selector type " << NameOf(sel.val->Type()) + << " must be an integer scalar"; + } + } + } + + if (!found_default) { + AddError(s) << "missing default case for switch"; + } + + tasks_.Push([this, s] { control_stack_.Push(s); }); +} + +void Validator::CheckSwizzle(const Swizzle* s) { + if (!CheckResultsAndOperands(s, Swizzle::kNumResults, Swizzle::kNumOperands)) { + return; + } + + auto* src_vec = s->Object()->Type()->As(); + if (!src_vec) { + AddError(s) << "object of swizzle, " << NameOf(s->Object()) << ", is not a vector, " + << NameOf(s->Object()->Type()); + return; + } + + auto indices = s->Indices(); + if (indices.Length() < Swizzle::kMinNumIndices) { + AddError(s) << "expected at least " << Swizzle::kMinNumIndices << " indices"; + return; + } + + if (indices.Length() > Swizzle::kMaxNumIndices) { + AddError(s) << "expected at most " << Swizzle::kMaxNumIndices << " indices"; + return; + } + + auto elem_count = src_vec->Elements().count; + for (auto& idx : indices) { + if (idx > Swizzle::kMaxIndexValue || idx >= elem_count) { + AddError(s) << "invalid index value"; + return; + } + } + + auto* elem_ty = src_vec->Elements().type; + auto* expected_ty = type_mgr_.MatchWidth(elem_ty, indices.Length()); + auto* result_ty = s->Result()->Type(); + if (result_ty != expected_ty) { + AddError(s) << "result type " << NameOf(result_ty) << " does not match expected type, " + << NameOf(expected_ty); + return; + } +} + +void Validator::CheckTerminator(const Terminator* b) { + // All terminators should have zero results + if (!CheckResults(b, 0)) { + return; + } + + // Operands must be alive and in scope if they are not nullptr. + if (!CheckOperands(b)) { + return; + } + + tint::Switch( + b, // + [&](const ir::BreakIf* i) { CheckBreakIf(i); }, // + [&](const ir::Continue* c) { CheckContinue(c); }, // + [&](const ir::Exit* e) { CheckExit(e); }, // + [&](const ir::NextIteration* n) { CheckNextIteration(n); }, // + [&](const ir::Return* ret) { CheckReturn(ret); }, // + [&](const ir::TerminateInvocation*) {}, // + [&](const ir::Unreachable* u) { CheckUnreachable(u); }, // + [&](Default) { AddError(b) << "missing validation"; }); + + if (b->next) { + AddError(b) << "must be the last instruction in the block"; + } +} + +void Validator::CheckBreakIf(const BreakIf* b) { + if (b->Condition() == nullptr) { + AddError(b) << "break_if condition cannot be nullptr"; + return; + } + + if (!b->Condition()->Type() || !b->Condition()->Type()->Is()) { + AddError(b) << "condition must be a 'bool'"; + return; + } + + auto* loop = b->Loop(); + if (loop == nullptr) { + AddError(b) << "has no associated loop"; + return; + } + + if (loop->Continuing() != b->Block()) { + AddError(b) << "must only be called directly from loop continuing"; + } + + auto next_iter_values = b->NextIterValues(); + if (auto* body = loop->Body()) { + CheckOperandsMatchTarget(b, b->ArgsOperandOffset(), next_iter_values.size(), body, + body->Params()); + } + + auto exit_values = b->ExitValues(); + CheckOperandsMatchTarget(b, b->ArgsOperandOffset() + next_iter_values.size(), + exit_values.size(), loop, loop->Results()); +} + +void Validator::CheckContinue(const Continue* c) { + auto* loop = c->Loop(); + if (loop == nullptr) { + AddError(c) << "has no associated loop"; + return; + } + if (!TransitivelyHolds(loop->Body(), c)) { + if (control_stack_.Any(Eq(loop))) { + AddError(c) << "must only be called from loop body"; + } else { + AddError(c) << "called outside of associated loop"; + } + } + + if (auto* cont = loop->Continuing()) { + CheckOperandsMatchTarget(c, Continue::kArgsOperandOffset, c->Args().Length(), cont, + cont->Params()); + } + + first_continues_.Add(loop, c); +} + +void Validator::CheckExit(const Exit* e) { + if (e->ControlInstruction() == nullptr) { + AddError(e) << "has no parent control instruction"; + return; + } + + if (control_stack_.IsEmpty()) { + AddError(e) << "found outside all control instructions"; + return; + } + + auto args = e->Args(); + CheckOperandsMatchTarget(e, e->ArgsOperandOffset(), args.Length(), e->ControlInstruction(), + e->ControlInstruction()->Results()); + + tint::Switch( + e, // + [&](const ir::ExitIf* i) { CheckExitIf(i); }, // + [&](const ir::ExitLoop* l) { CheckExitLoop(l); }, // + [&](const ir::ExitSwitch* s) { CheckExitSwitch(s); }, // + [&](Default) { AddError(e) << "missing validation"; }); +} + +void Validator::CheckNextIteration(const NextIteration* n) { + auto* loop = n->Loop(); + if (loop == nullptr) { + AddError(n) << "has no associated loop"; + return; + } + if (!TransitivelyHolds(loop->Initializer(), n) && !TransitivelyHolds(loop->Continuing(), n)) { + if (control_stack_.Any(Eq(loop))) { + AddError(n) << "must only be called from loop initializer or continuing"; + } else { + AddError(n) << "called outside of associated loop"; + } + } + + if (auto* body = loop->Body()) { + CheckOperandsMatchTarget(n, NextIteration::kArgsOperandOffset, n->Args().Length(), body, + body->Params()); + } +} + +void Validator::CheckExitIf(const ExitIf* e) { + if (control_stack_.Back() != e->If()) { + AddError(e) << "if target jumps over other control instructions"; + AddNote(control_stack_.Back()) << "first control instruction jumped"; + } +} + +void Validator::CheckReturn(const Return* ret) { + if (!CheckOperands(ret, Return::kMinOperands, Return::kMaxOperands)) { + return; + } + + auto* func = ret->Func(); + if (func == nullptr) { + // Func() returning nullptr after CheckResultsAndOperandRange is due to the first + // operand being not a function + AddError(ret) << "expected function for first operand"; + return; + } + + if (func != ContainingFunction(ret)) { + AddError(ret) << "function operand does not match containing function"; + return; + } + + if (func->ReturnType()->Is()) { + if (ret->HasValue()) { + AddError(ret) << "unexpected return value"; + } + } else { + if (!ret->Value()) { + AddError(ret) << "expected return value"; + } else if (ret->Value()->Type() != func->ReturnType()) { + AddError(ret) << "return value type " << NameOf(ret->Value()->Type()) + << " does not match function return type " << NameOf(func->ReturnType()); + } + } +} + +void Validator::CheckUnreachable(const Unreachable* u) { + CheckResultsAndOperands(u, Unreachable::kNumResults, Unreachable::kNumOperands); +} + +void Validator::CheckControlsAllowingIf(const Exit* exit, const Instruction* control) { + bool found = false; + for (auto ctrl : tint::Reverse(control_stack_)) { + if (ctrl == control) { + found = true; + break; + } + // A exit switch can step over if instructions, but no others. + if (!ctrl->Is()) { + AddError(exit) << control->FriendlyName() + << " target jumps over other control instructions"; + AddNote(ctrl) << "first control instruction jumped"; + return; + } + } + if (!found) { + AddError(exit) << control->FriendlyName() << " not found in parent control instructions"; + } +} + +void Validator::CheckExitSwitch(const ExitSwitch* s) { + CheckControlsAllowingIf(s, s->ControlInstruction()); +} + +void Validator::CheckExitLoop(const ExitLoop* l) { + CheckControlsAllowingIf(l, l->ControlInstruction()); + + const Instruction* inst = l; + const Loop* control = l->Loop(); + while (inst) { + // Found parent loop + if (inst->Block()->Parent() == control) { + if (inst->Block() == control->Continuing()) { + AddError(l) << "loop exit jumps out of continuing block"; + if (control->Continuing() != l->Block()) { + AddNote(control->Continuing()) << "in continuing block"; + } + } else if (inst->Block() == control->Initializer()) { + AddError(l) << "loop exit not permitted in loop initializer"; + if (control->Initializer() != l->Block()) { + AddNote(control->Initializer()) << "in initializer block"; + } + } + break; + } + inst = inst->Block()->Parent(); + } +} + +bool Validator::CanLoad(const core::type::Type* ty) { + return tint::Switch( + ty, // + [&](const core::type::Array* arr) { + if (arr->Count()->Is()) { + return false; + } + return CanLoad(arr->Elements().type); + }, + [&](const core::type::Struct* str) { + for (auto* member : str->Members()) { + if (member->Type()->Is() && + capabilities_.Contains(Capability::kMslAllowEntryPointInterface)) { + continue; + } + if (!CanLoad(member->Type())) { + return false; + } + } + return true; + }, + [&](Default) { return ty->IsConstructible() || ty->IsHandle(); }); +} + +void Validator::CheckLoad(const Load* l) { + if (!CheckResultsAndOperands(l, Load::kNumResults, Load::kNumOperands)) { + return; + } + + if (auto* from = l->From()) { + auto* mv = from->Type()->As(); + if (!mv) { + AddError(l, Load::kFromOperandOffset) + << "load source operand " << NameOf(from->Type()) << " is not a memory view"; + return; + } + + if (mv->Access() != core::Access::kRead && mv->Access() != core::Access::kReadWrite) { + AddError(l, Load::kFromOperandOffset) + << "load source operand has a non-readable access type, " + << style::Literal(ToString(mv->Access())); + return; + } + + if (l->Result()->Type() != mv->StoreType()) { + AddError(l, Load::kFromOperandOffset) + << "result type " << NameOf(l->Result()->Type()) + << " does not match source store type " << NameOf(mv->StoreType()); + } + + if (!CanLoad(mv->StoreType())) { + AddError(l, Load::kFromOperandOffset) + << "type " << NameOf(mv->StoreType()) << " cannot be loaded"; + return; + } + } +} + +void Validator::CheckStore(const Store* s) { + if (!CheckResultsAndOperands(s, Store::kNumResults, Store::kNumOperands)) { + return; + } + + if (auto* from = s->From()) { + if (auto* to = s->To()) { + auto* mv = As(to->Type()); + if (!mv) { + AddError(s, Store::kToOperandOffset) + << "store target operand " << NameOf(to->Type()) << " is not a memory view"; + return; + } + + if (mv->Access() != core::Access::kWrite && mv->Access() != core::Access::kReadWrite) { + AddError(s, Store::kToOperandOffset) + << "store target operand has a non-writeable access type, " + << style::Literal(ToString(mv->Access())); + return; + } + + auto* value_type = from->Type(); + auto* store_type = mv->StoreType(); + if (value_type != store_type) { + AddError(s, Store::kFromOperandOffset) + << "value type " << NameOf(value_type) << " does not match store type " + << NameOf(store_type); + return; + } + + if (!store_type->IsConstructible()) { + AddError(s) << "store type " << NameOf(store_type) << " is not constructible"; + return; + } + } + } +} + +void Validator::CheckLoadVectorElement(const LoadVectorElement* l) { + if (!CheckResultsAndOperands(l, LoadVectorElement::kNumResults, + LoadVectorElement::kNumOperands)) { + return; + } + + if (auto* res = l->Result(0)) { + auto* el_ty = GetVectorPtrElementType(l, LoadVectorElement::kFromOperandOffset); + if (!el_ty) { + return; + } + if (res->Type() != el_ty) { + AddResultError(l, 0) << "result type " << NameOf(res->Type()) + << " does not match vector pointer element type " << NameOf(el_ty); + return; + } + } + + if (!l->Index()->Type()->IsIntegerScalar()) { + AddError(l, LoadVectorElement::kIndexOperandOffset) + << "load vector element index must be an integer scalar"; + } + if (auto* c = l->Index()->As()) { + auto val = c->Value()->ValueAs(); + + auto* vec_ty = l->From()->Type()->UnwrapPtrOrRef()->As(); + TINT_ASSERT(vec_ty); + + if (val >= vec_ty->Width()) { + AddError(l, LoadVectorElement::kIndexOperandOffset) + << "load vector element index must be in range [0, " << (vec_ty->Width() - 1) + << "]"; + } + } +} + +void Validator::CheckStoreVectorElement(const StoreVectorElement* s) { + if (!CheckResultsAndOperands(s, StoreVectorElement::kNumResults, + StoreVectorElement::kNumOperands)) { + return; + } + + if (auto* value = s->Value()) { + auto* el_ty = GetVectorPtrElementType(s, StoreVectorElement::kToOperandOffset); + if (!el_ty) { + return; + } + if (value->Type() != el_ty) { + AddError(s, StoreVectorElement::kValueOperandOffset) + << "value type " << NameOf(value->Type()) + << " does not match vector pointer element type " << NameOf(el_ty); + return; + } + + // The `GetVectorPtrElementType` has already validated that the pointer exists. + auto* mv = s->To()->Type()->As(); + if (mv->Access() != core::Access::kWrite && mv->Access() != core::Access::kReadWrite) { + AddError(s, StoreVectorElement::kToOperandOffset) + << "store_vector_element target operand has a non-writeable access type, " + << style::Literal(ToString(mv->Access())); + return; + } + } + + if (!s->Index()->Type()->IsIntegerScalar()) { + AddError(s, StoreVectorElement::kIndexOperandOffset) + << "store vector element index must be an integer scalar"; + } + if (auto* c = s->Index()->As()) { + auto val = c->Value()->ValueAs(); + + auto* vec_ty = s->To()->Type()->UnwrapPtrOrRef()->As(); + TINT_ASSERT(vec_ty); + + if (val >= vec_ty->Width()) { + AddError(s, StoreVectorElement::kIndexOperandOffset) + << "store vector element index must be in range [0, " << (vec_ty->Width() - 1) + << "]"; + } + } +} + +void Validator::CheckPhony(const Phony* p) { + if (!capabilities_.Contains(Capability::kAllowPhonyInstructions)) { + AddError(p) << "missing capability 'kAllowPhonyInstructions'"; + return; + } + + if (!CheckResultsAndOperands(p, Phony::kNumResults, Phony::kNumOperands)) { + return; + } +} + +void Validator::CheckOperandsMatchTarget(const Instruction* source_inst, + size_t source_operand_offset, + size_t source_operand_count, + const CastableBase* target, + VectorRef target_values) { + if (source_operand_count != target_values.Length()) { + auto values = [&](size_t n) { return n == 1 ? " value" : " values"; }; + AddError(source_inst) << "provides " << source_operand_count << values(source_operand_count) + << " but " << NameOf(target) << " expects " << target_values.Length() + << values(target_values.Length()); + AddDeclarationNote(target); + } + size_t count = std::min(source_operand_count, target_values.Length()); + for (size_t i = 0; i < count; i++) { + auto* source_value = source_inst->Operand(source_operand_offset + i); + auto* target_value = target_values[i]; + if (!source_value || !target_value) { + continue; // Caller should be checking operands are not null + } + auto* source_type = source_value->Type(); + auto* target_type = target_value->Type(); + if (source_type != target_type) { + AddError(source_inst, source_operand_offset + i) + << "operand with type " << NameOf(source_type) << " does not match " + << NameOf(target) << " target type " << NameOf(target_type); + AddDeclarationNote(target_value); + } + } +} + +const core::type::Type* Validator::GetVectorPtrElementType(const Instruction* inst, size_t idx) { + auto* operand = inst->Operands()[idx]; + if (DAWN_UNLIKELY(!operand)) { + AddError(inst, idx) << "missing element operand"; + return nullptr; + } + + auto* type = operand->Type(); + if (DAWN_UNLIKELY(!type)) { + AddError(inst, idx) << "missing operand type"; + return nullptr; + } + + auto* memory_view_ty = type->As(); + if (DAWN_LIKELY(memory_view_ty)) { + auto* vec_ty = memory_view_ty->StoreType()->As(); + if (DAWN_LIKELY(vec_ty)) { + return vec_ty->Type(); + } + } + + AddError(inst, idx) << "operand " << NameOf(type) << " must be a pointer to a vector"; + return nullptr; +} + +} // namespace + +Result Validate(const Module& mod, Capabilities capabilities) { + Validator v(mod, capabilities); + TINT_CHECK_RESULT(v.Run()); + return Success; +} + +Result ValidateAndDumpIfNeeded([[maybe_unused]] const Module& ir, + [[maybe_unused]] const char* msg, + [[maybe_unused]] Capabilities capabilities, + [[maybe_unused]] std::string_view timing) { +#if TINT_DUMP_IR_WHEN_VALIDATING + auto printer = StyledTextPrinter::Create(stdout); + std::cout << "=========================================================\n"; + std::cout << "== IR dump " << timing << " " << msg << ":\n"; + std::cout << "=========================================================\n"; + printer->Print(Disassembler(ir).Text()); +#endif + +#if TINT_ENABLE_IR_VALIDATION + TINT_CHECK_RESULT(Validate(ir, capabilities)); +#endif + + return Success; +} + +} // namespace tint::core::ir + +namespace std { + +template <> +struct hash { + size_t operator()(const tint::core::ir::ValidatedType& v) const { return Hash(v.ty, v.caps); } +}; + +template <> +struct equal_to { + bool operator()(const tint::core::ir::ValidatedType& a, + const tint::core::ir::ValidatedType& b) const { + return a.ty->Equals(*(b.ty)) && a.caps == b.caps; + } +}; + +} // namespace std diff --git a/3rdparty/dawn/src/tint/lang/core/ir/validator.h b/3rdparty/dawn/src/tint/lang/core/ir/validator.h new file mode 100644 index 000000000..dda544275 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/validator.h @@ -0,0 +1,119 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_VALIDATOR_H_ +#define SRC_TINT_LANG_CORE_IR_VALIDATOR_H_ + +#include +#include "src/tint/utils/containers/enum_set.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +class Function; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// Enumerator of optional IR capabilities. +enum class Capability : uint8_t { + /// Allows 8-bit integer types. + kAllow8BitIntegers, + /// Allows 64-bit integer types. + kAllow64BitIntegers, + /// Allows ClipDistances on f32 and vecN parameters + kAllowClipDistancesOnF32ScalarAndVector, + /// Allows handle vars to not have binding points + kAllowHandleVarsWithoutBindings, + /// Allows module scoped lets + kAllowModuleScopeLets, + /// Allows multiple entry points in the module. + kAllowMultipleEntryPoints, + /// Allow overrides + kAllowOverrides, + /// Allows ref types + kAllowRefTypes, + /// Allows access instructions to create pointers to vector elements. + kAllowVectorElementPointer, + /// Allows phony assignment instructions to be used. + kAllowPhonyInstructions, + /// Allows lets to have any type, used by MSL backend for module scoped vars + kAllowAnyLetType, + /// Allows input_attachment_index to be associated with any type, used by + /// SPIRV backend for spirv.image. + kAllowAnyInputAttachmentIndexType, + /// Allows binding points to be non-unique. Used after BindingRemapper is + /// invoked by MSL & GLSL backends. + kAllowDuplicateBindings, + /// Allows module scope `var`s to exist without an IO annotation + kAllowUnannotatedModuleIOVariables, + /// Allows non-core types in the IR module + kAllowNonCoreTypes, + /// Allows matrix annotations on structure members + kAllowStructMatrixDecorations, + /// Allows @location on structs, matrices, and arrays that have numeric elements + kAllowLocationForNumericElements, + /// Allows a pointer to a handle type + kAllowPointerToHandle, + /// Allows ShaderIO specific features, like blend_src on non-struct members. + /// These are not separate capabilities, because they are enabled/disabled in lockstep with each + /// other. + /// TODO(448417342): Validate in/out address space usage based on this capability + kLoosenValidationForShaderIO, + /// Allows the PointSize builtin to be used. + kAllowPointSizeBuiltin, + /// Allows MSL specific entry point variance. + /// Specifically pointers and handle address space variables inside structures, private address + /// space variables in function scopes, workgroup address space pointers as entry point inputs, + /// binding point on non-module scope variables in entry point interface. + kMslAllowEntryPointInterface, +}; + +/// Capabilities is a set of Capability +using Capabilities = EnumSet; + +/// Validates that a given IR module is correctly formed +/// @param mod the module to validate +/// @param capabilities the optional capabilities that are allowed +/// @returns success or failure +Result Validate(const Module& mod, Capabilities capabilities = {}); + +/// Validates the module @p ir and dumps its contents if required by the build configuration. +/// @param ir the module to transform +/// @param msg the msg to accompany the output +/// @param capabilities the optional capabilities that are allowed +/// @param timing when the validation is run. +/// @returns success or failure +Result ValidateAndDumpIfNeeded(const Module& ir, + const char* msg, + Capabilities capabilities = {}, + std::string_view timing = "before"); + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_VALIDATOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/value.cc b/3rdparty/dawn/src/tint/lang/core/ir/value.cc new file mode 100644 index 000000000..dfbb26893 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/value.cc @@ -0,0 +1,84 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/value.h" + +#include + +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Value); + +namespace tint::core::ir { + +Value::Value(const core::type::Type* type) : type_(type) {} + +Value::~Value() = default; + +void Value::Destroy() { + TINT_ASSERT(Alive()); + flags_.Add(Flag::kDead); +} + +void Value::ForEachUseUnsorted(std::function func) const { + auto uses = uses_; + for (auto& use : uses) { + func(use); + } +} + +void Value::ForEachUseSorted(std::function func) const { + auto uses = UsagesSorted(); + for (auto& use : uses) { + func(use); + } +} + +void Value::ReplaceAllUsesWith(std::function replacer) { + while (!uses_.IsEmpty()) { + auto& use = *uses_.begin(); + auto* replacement = replacer(use); + use->instruction->SetOperand(use->operand_index, replacement); + } +} + +void Value::ReplaceAllUsesWith(Value* replacement) { + while (!uses_.IsEmpty()) { + auto& use = *uses_.begin(); + use->instruction->SetOperand(use->operand_index, replacement); + } +} + +Vector Value::UsagesSorted() const { + auto v = uses_.Vector(); + std::sort(v.begin(), v.end()); + return v; +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/value.h b/3rdparty/dawn/src/tint/lang/core/ir/value.h new file mode 100644 index 000000000..eff43479e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/value.h @@ -0,0 +1,170 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_VALUE_H_ +#define SRC_TINT_LANG_CORE_IR_VALUE_H_ + +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::core::ir { +class CloneContext; +class Instruction; +} // namespace tint::core::ir + +namespace tint::core::ir { + +/// A specific usage of a Value in the IR. +struct Usage { + /// The instruction that is using the value; + Instruction* instruction = nullptr; + /// The index of the operand that is the value being used. + size_t operand_index = 0u; + + /// @returns the hash code of the Usage + tint::HashCode HashCode() const { return Hash(instruction, operand_index); } + + /// An equality helper for Usage. + /// @param other the usage to compare against + /// @returns true if the two usages are equal + bool operator==(const Usage& other) const { + return instruction == other.instruction && operand_index == other.operand_index; + } + + /// A comparison helper for Usage. + /// @param other the usage to compare against + /// @returns true if `this` is less then `other`. + bool operator<(const Usage& other) const { + if (instruction == nullptr && other.instruction != nullptr) { + return false; + } + if (instruction != nullptr && other.instruction == nullptr) { + return true; + } + if (instruction == other.instruction) { + return operand_index < other.operand_index; + } + return instruction < other.instruction; + } +}; + +/// Value in the IR. +class Value : public Castable { + public: + /// Destructor + ~Value() override; + + /// @returns the type of the value + const core::type::Type* Type() const { return type_; } + + /// Sets the type of the value to @p type + /// @param type the new type of the value + void SetType(const core::type::Type* type) { type_ = type; } + + /// 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(); + + /// @param ctx the CloneContext used to clone this value + /// @returns a clone of this value + virtual Value* Clone(CloneContext& ctx) = 0; + + /// @returns true if the Value has not been destroyed with Destroy() + bool Alive() const { return !flags_.Contains(Flag::kDead); } + + /// Adds a usage of this value. + /// @param u the usage + void AddUsage(Usage u) { uses_.Add(u); } + + /// Remove a usage of this value. + /// @param u the usage + void RemoveUsage(Usage u) { uses_.Remove(u); } + + /// @returns the set of usages of this value. An instruction may appear multiple times if it + /// uses the value for multiple different operands. + const Hashset& UsagesUnsorted() const { return uses_; } + + /// @returns a sorted list of usages of this value. The usages are in the order of + /// where the instructions are ordered earliest instruction to + /// latest and the operand indices from lowest to highest. + Vector UsagesSorted() const; + + /// @returns true if this Value has any usages + bool IsUsed() const { return !uses_.IsEmpty(); } + + /// @returns the number of usages of this Value + size_t NumUsages() const { return uses_.Count(); } + + /// @returns true if the usages contains the instruction and operand index pair. + /// @param instruction the instruction + /// @param operand_index the in + bool HasUsage(const Instruction* instruction, size_t operand_index) const { + return uses_.Contains(Usage{const_cast(instruction), operand_index}); + } + + /// Apply a function to all uses of the value that exist prior to calling this method. The uses + /// are in unsorted ordered. + /// @param func the function will be applied to each use + void ForEachUseUnsorted(std::function func) const; + + /// Apply a function to all uses of the value that exist prior to calling this method. The uses + /// are sorted in (instruction,operand) order + /// @param func the function will be applied to each use + void ForEachUseSorted(std::function func) const; + + /// Replace all uses of the value. + /// @param replacer a function which returns a replacement for a given use + void ReplaceAllUsesWith(std::function replacer); + + /// Replace all uses of the value. + /// @param replacement the replacement value + void ReplaceAllUsesWith(Value* replacement); + + protected: + /// Constructor + /// @param type the type of the value + explicit Value(const core::type::Type* type); + + private: + /// Flags applied to an Value + enum class Flag { + /// The value has been destroyed + kDead, + }; + + const core::type::Type* type_ = nullptr; + Hashset uses_; + + /// Bitset of value flags + tint::EnumSet flags_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_VALUE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/ir/var.cc b/3rdparty/dawn/src/tint/lang/core/ir/var.cc new file mode 100644 index 000000000..f6816fa11 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/var.cc @@ -0,0 +1,87 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/ir/var.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Var); + +namespace tint::core::ir { + +Var::Var(Id id) : Base(id) {} + +Var::Var(Id id, InstructionResult* result) : Base(id) { + if (result && result->Type()) { + TINT_ASSERT(result->Type()->Is()); + } + + // Default to no initializer. + AddOperand(Var::kInitializerOperandOffset, nullptr); + AddResult(result); +} + +Var::~Var() = default; + +Var* Var::Clone(CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* new_var = ctx.ir.CreateInstruction(new_result); + + new_var->attributes_ = attributes_; + + if (auto* init = Initializer()) { + new_var->SetInitializer(ctx.Clone(init)); + } + + auto name = ctx.ir.NameOf(this); + if (name.IsValid()) { + ctx.ir.SetName(new_var, name.Name()); + } + return new_var; +} + +void Var::SetInitializer(Value* initializer) { + SetOperand(Var::kInitializerOperandOffset, initializer); +} + +void Var::DestroyIfOnlyAssigned() { + auto* result = Result(); + if (result->UsagesUnsorted().All( + [](const Usage& u) { return u.instruction->Is(); })) { + while (result->IsUsed()) { + auto& usage = *result->UsagesUnsorted().begin(); + usage->instruction->Destroy(); + } + Destroy(); + } +} + +} // namespace tint::core::ir diff --git a/3rdparty/dawn/src/tint/lang/core/ir/var.h b/3rdparty/dawn/src/tint/lang/core/ir/var.h new file mode 100644 index 000000000..ccdb30dce --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/ir/var.h @@ -0,0 +1,149 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_IR_VAR_H_ +#define SRC_TINT_LANG_CORE_IR_VAR_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/interpolation.h" +#include "src/tint/lang/core/io_attributes.h" +#include "src/tint/lang/core/ir/operand_instruction.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::ir { + +/// A var instruction in the IR. +class Var : public Castable> { + public: + /// The offset in Operands() for the initializer + static constexpr size_t kInitializerOperandOffset = 0; + + /// The fixed number of results returned by this instruction + static constexpr size_t kNumResults = 1; + + /// The fixed number of operands expected by this instruction + static constexpr size_t kNumOperands = 1; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Var(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + explicit Var(Id id, InstructionResult* result); + + ~Var() override; + + /// @copydoc Instruction::Clone() + Var* Clone(CloneContext& ctx) override; + + /// Sets the var initializer + /// @param initializer the initializer + void SetInitializer(Value* initializer); + /// @returns the initializer + Value* Initializer() { return Operand(kInitializerOperandOffset); } + /// @returns the initializer + const Value* Initializer() const { return Operand(kInitializerOperandOffset); } + + /// Sets the binding point + /// @param group the group + /// @param binding the binding + void SetBindingPoint(uint32_t group, uint32_t binding) { + attributes_.binding_point = {group, binding}; + } + /// @returns the binding points if `Attributes` contains `kBindingPoint` + std::optional BindingPoint() const { return attributes_.binding_point; } + + /// Sets the input attachment index + /// @param index the index + void SetInputAttachmentIndex(uint32_t index) { attributes_.input_attachment_index = index; } + /// @returns the input attachment index if any + std::optional InputAttachmentIndex() const { + return attributes_.input_attachment_index; + } + + /// Sets the interpolation. + /// @param interpolation the optional location interpolation settings + void SetInterpolation(std::optional interpolation) { + attributes_.interpolation = interpolation; + } + + /// Sets the parameter as invariant + /// @param val the value to set for invariant + void SetInvariant(bool val) { attributes_.invariant = val; } + + /// Sets the blend source. + /// @param src the optional value + void SetBlendSrc(std::optional src) { attributes_.blend_src = src; } + + /// Sets the color. + /// @param col the optional color value + void SetColor(std::optional col) { attributes_.color = col; } + + /// Sets the location. + /// @param loc the optional location value + void SetLocation(std::optional loc) { attributes_.location = loc; } + + /// Sets the builtin information. Note, it is currently an error if the builtin is already set. + /// @param val the builtin to set + void SetBuiltin(core::BuiltinValue val) { + TINT_ASSERT(!attributes_.builtin.has_value()); + attributes_.builtin = val; + } + /// Returns the builtin information, if available + std::optional Builtin() const { return attributes_.builtin; } + + /// Resets the IO attributes + void ResetAttributes() { attributes_ = {}; } + + /// Sets the IO attributes + /// @param attrs the attributes + void SetAttributes(const IOAttributes& attrs) { attributes_ = attrs; } + + /// @returns the IO attributes + const IOAttributes& Attributes() const { return attributes_; } + + /// @returns the IO attributes + IOAttributes& Attributes() { return attributes_; } + + /// Destroys this instruction along with any assignment instructions, if the var is never read. + void DestroyIfOnlyAssigned(); + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return "var"; } + + private: + IOAttributes attributes_; +}; + +} // namespace tint::core::ir + +#endif // SRC_TINT_LANG_CORE_IR_VAR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/number.cc b/3rdparty/dawn/src/tint/lang/core/number.cc new file mode 100644 index 000000000..e54098a1e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/number.cc @@ -0,0 +1,416 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/number.h" + +#include +#include +#include + +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/memory/bitcast.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::core { +namespace { + +constexpr uint16_t kF16Nan = 0x7e00u; +constexpr uint16_t kF16PosInf = 0x7c00u; +constexpr uint16_t kF16NegInf = 0xfc00u; + +constexpr uint16_t kF16SignMask = 0x8000u; +constexpr uint16_t kF16ExponentMask = 0x7c00u; +constexpr uint16_t kF16MantissaMask = 0x03ffu; + +constexpr uint32_t kF16MantissaBits = 10; +constexpr uint32_t kF16ExponentBias = 15; + +constexpr uint32_t kF32SignMask = 0x80000000u; +constexpr uint32_t kF32ExponentMask = 0x7f800000u; +constexpr uint32_t kF32MantissaMask = 0x007fffffu; + +constexpr uint32_t kF32MantissaBits = 23; +constexpr uint32_t kF32ExponentBias = 127; + +constexpr uint32_t kMaxF32BiasedExpForF16NormalNumber = 142; +constexpr uint32_t kMinF32BiasedExpForF16NormalNumber = 113; +constexpr uint32_t kMaxF32BiasedExpForF16SubnormalNumber = 112; +constexpr uint32_t kMinF32BiasedExpForF16SubnormalNumber = 103; + +} // namespace + +f16::type f16::Quantize(f16::type value) { + if (value > kHighestValue) { + return std::numeric_limits::infinity(); + } + if (value < kLowestValue) { + return -std::numeric_limits::infinity(); + } + + // Below value must be within the finite range of a f16. + // Assert we use binary32 (i.e. float) as underlying type, which has 4 bytes. + static_assert(std::is_same()); + + uint32_t u32 = tint::Bitcast(value); + if ((u32 & ~kF32SignMask) == 0) { + return value; // +/- zero + } + if ((u32 & kF32ExponentMask) == kF32ExponentMask) { // exponent all 1's + return value; // inf or nan + } + + // We are now going to quantize a f32 number into subnormal f16 and store the result value back + // into a f32 variable. Notice that all subnormal f16 values are just normal f32 values. Below + // will show that we can do this quantization by just masking out 13 or more lowest mantissa + // bits of the original f32 number. + // + // Note: + // * f32 has 1 sign bit, 8 exponent bits for biased exponent (i.e. unbiased exponent + 127), and + // 23 mantissa bits. Binary form: s_eeeeeeee_mmmmmmmmmmmmmmmmmmmmmmm + // + // * f16 has 1 sign bit, 5 exponent bits for biased exponent (i.e. unbiased exponent + 15), and + // 10 mantissa bits. Binary form: s_eeeee_mmmmmmmmmm + // + // The largest finite f16 number has a biased exponent of 11110 in binary, or 30 decimal, and so + // an unbiased exponent of 30 - 15 = 15. + // + // The smallest finite f16 number has a biased exponent of 00001 in binary, or 1 decimal, and so + // a unbiased exponent of 1 - 15 = -14. + // + // We may follow the argument below: + // 1. All normal or subnormal f16 values, range from 0x1.p-24 to 0x1.ffcp15, are exactly + // representable by a normal f32 number. + // 1.1. We can denote the set of all f32 number that are exact representation of finite f16 + // values by `R`. + // 1.2. We can do the quantization by mapping a normal f32 value v (in the f16 finite range) + // to a certain f32 number v' in the set R, which is the largest (by the meaning of absolute + // value) one among all values in R that are no larger than v. + // + // 2. We can decide whether a given normal f32 number v is in the set R, by looking at its + // mantissa bits and biased exponent `e`. Recall that biased exponent e is unbiased exponent + + // 127, and in the range of 1 to 254 for normal f32 number. + // 2.1. If e >= 143, i.e. abs(v) >= 2^16 > f16::kHighestValue = 0x1.ffcp15, v is larger than + // any finite f16 value and can not be in set R. 2.2. If 142 >= e >= 113, or + // f16::kHighestValue >= abs(v) >= f16::kSmallestValue = 2^-14, v falls in the range of normal + // f16 values. In this case, v is in the set R iff the lowest 13 mantissa bits are all 0. (See + // below for proof) + // 2.2.1. If we let v' be v with lowest 13 mantissa bits masked to 0, v' will be in set R + // and the largest one in set R that no larger than v. Such v' is the quantized value of v. + // 2.3. If 112 >= e >= 103, i.e. 2^-14 > abs(v) >= f16::kSmallestSubnormalValue = 2^-24, v + // falls in the range of subnormal f16 values. In this case, v is in the set R iff the lowest + // 126-e mantissa bits are all 0. Notice that 126-e is in range 14 to 23, inclusive. (See + // below for proof) + // 2.3.1. If we let v' be v with lowest 126-e mantissa bits masked to 0, v' will be in set R + // and the largest on in set R that no larger than v. Such v' is the quantized value of v. + // 2.4. If 2^-24 > abs(v) > 0, i.e. 103 > e, v is smaller than any finite f16 value and not + // equal to 0.0, thus can not be in set R. + // 2.5. If abs(v) = 0, v is in set R and is just +-0.0. + // + // Proof for 2.2 + // ------------- + // Any normal f16 number, in binary form, s_eeeee_mmmmmmmmmm, has value + // + // (s == 0 ? 1 : -1) * (1 + uint(mmmmm_mmmmm) * (2^-10)) * 2^(uint(eeeee) - 15) + // + // in which unit(bbbbb) means interprete binary pattern "bbbbb" as unsigned binary number, + // and we have 1 <= uint(eeeee) <= 30. + // + // This value is equal to a normal f32 number with binary + // s_EEEEEEEE_mmmmmmmmmm0000000000000 + // + // where uint(EEEEEEEE) = uint(eeeee) + 112, so that unbiased exponent is kept unchanged + // + // uint(EEEEEEEE) - 127 = uint(eeeee) - 15 + // + // and its value is + // (s == 0 ? 1 : -1) * + // (1 + uint(mmmmm_mmmmm_00000_00000_000) * (2^-23)) * 2^(uint(EEEEEEEE) - 127) + // == (s == 0 ? 1 : -1) * + // (1 + uint(mmmmm_mmmmm) * (2^-10)) * 2^(uint(eeeee) - 15) + // + // Notice that uint(EEEEEEEE) is in range [113, 142], showing that it is a normal f32 number. + // So we proved that any normal f16 number can be exactly representd by a normal f32 number + // with biased exponent in range [113, 142] and the lowest 13 mantissa bits 0. + // + // On the other hand, since mantissa bits mmmmmmmmmm are arbitrary, the value of any f32 + // that has a biased exponent in range [113, 142] and lowest 13 mantissa bits zero is equal + // to a normal f16 value. Hence we prove 2.2. + // + // Proof for 2.3 + // ------------- + // Any subnormal f16 number has a binary form of s_00000_mmmmmmmmmm, and its value is + // + // (s == 0 ? 1 : -1) * uint(mmmmmmmmmm) * (2^-10) * (2^-14) + // == (s == 0 ? 1 : -1) * uint(mmmmmmmmmm) * (2^-24). + // + // We discuss the bit pattern of mantissa bits mmmmmmmmmm. + // Case 1: mantissa bits have no leading zero bit, s_00000_1mmmmmmmmm + // In this case the value is + // (s == 0 ? 1 : -1) * uint(1mmmm_mmmmm) * (2^-10) * (2^-14) + // == (s == 0 ? 1 : -1) * ( uint(1_mmmmm_mmmm) * (2^-9)) * (2^-15) + // == (s == 0 ? 1 : -1) * (1 + uint(mmmmm_mmmm) * (2^-9)) * (2^-15) + // == (s == 0 ? 1 : -1) * (1 + uint(mmmmm_mmmm0_00000_00000_000) * (2^-23)) * (2^-15) + // + // which is equal to the value of the normal f32 number + // + // s_EEEEEEEE_mmmmm_mmmm0_00000_00000_000 + // + // where uint(EEEEEEEE) == -15 + 127 = 112. Hence we proved that any subnormal f16 number + // with no leading zero mantissa bit can be exactly represented by a f32 number with + // biased exponent 112 and the lowest 14 mantissa bits zero, and the value of any f32 + // number with biased exponent 112 and the lowest 14 mantissa bits zero is equal to a + // subnormal f16 number with no leading zero mantissa bit. + // + // Case 2: mantissa bits has 1 leading zero bit, s_00000_01mmmmmmmm + // In this case the value is + // (s == 0 ? 1 : -1) * uint(01mmm_mmmmm) * (2^-10) * (2^-14) + // == (s == 0 ? 1 : -1) * ( uint(01_mmmmm_mmm) * (2^-8)) * (2^-16) + // == (s == 0 ? 1 : -1) * (1 + uint(mmmmm_mmm) * (2^-8)) * (2^-16) + // == (s == 0 ? 1 : -1) * (1 + uint(mmmmm_mmm00_00000_00000_000) * (2^-23)) * (2^-16) + // + // which is equal to the value of normal f32 number + // + // s_EEEEEEEE_mmmmm_mmm00_00000_00000_000 + // + // where uint(EEEEEEEE) = -16 + 127 = 111. Hence we proved that any subnormal f16 number + // with 1 leading zero mantissa bit can be exactly represented by a f32 number with + // biased exponent 111 and the lowest 15 mantissa bits zero, and the value of any f32 + // number with biased exponent 111 and the lowest 15 mantissa bits zero is equal to a + // subnormal f16 number with 1 leading zero mantissa bit. + // + // Case 3 to case 8: ...... + // + // Case 9: mantissa bits has 8 leading zero bits, s_00000_000000001m + // In this case the value is + // (s == 0 ? 1 : -1) * uint(00000_0001m) * (2^-10) * (2^-14) + // == (s == 0 ? 1 : -1) * ( uint(000000001_m) * (2^-1)) * (2^-23) + // == (s == 0 ? 1 : -1) * (1 + uint(m) * (2^-1)) * (2^-23) + // == (s == 0 ? 1 : -1) * (1 + uint(m0000_00000_00000_00000_000) * (2^-23)) * (2^-23) + // + // which is equal to the value of normal f32 number + // + // s_EEEEEEEE_m0000_00000_00000_00000_000 + // + // where uint(EEEEEEEE) = -23 + 127 = 104. Hence we proved that any subnormal f16 number + // with 8 leading zero mantissa bit can be exactly represented by a f32 number with + // biased exponent 104 and the lowest 22 mantissa bits zero, and the value of any f32 + // number with biased exponent 104 and the lowest 22 mantissa bits zero are equal to a + // subnormal f16 number with 8 leading zero mantissa bit. + // + // Case 10: mantissa bits has 9 leading zero bits, s_00000_0000000001 + // In this case the value is just +-2^-24 == +-0x1.0p-24, + // the f32 number has biased exponent 103 and all 23 mantissa bits zero. + // + // Case 11: mantissa bits has 10 leading zero bits, s_00000_0000000000, just 0.0 + // + // Concluding all these case, we proved that any subnormal f16 number with N leading zero + // mantissa bit can be exactly represented by a f32 number with biased exponent 112 - N and the + // lowest 14 + N mantissa bits zero, and the value of any f32 number with biased exponent + // 112 - N (= e) and the lowest 14 + N (= 126 - e) mantissa bits zero are equal to a subnormal + // f16 number with N leading zero mantissa bits. N is in range [0, 9], so the f32 number's + // biased exponent e is in range [103, 112], or unbiased exponent in [-24, -15]. + + float abs_value = std::fabs(value); + if (abs_value >= kSmallestValue) { + // Value falls in the normal f16 range, quantize it to a normal f16 value by masking out + // lowest 13 mantissa bits. + u32 = u32 & ~((1u << (kF32MantissaBits - kF16MantissaBits)) - 1); + } else if (abs_value >= kSmallestSubnormalValue) { + // Value should be quantized to a subnormal f16 value. + + // Get the biased exponent `e` of f32 value, e.g. value 127 representing exponent 2^0. + uint32_t biased_exponent_original = (u32 & kF32ExponentMask) >> kF32MantissaBits; + // Since we ensure that kSmallestValue = 0x1f-14 > abs(value) >= kSmallestSubnormalValue = + // 0x1f-24, value will have a unbiased exponent in range -24 to -15 (inclusive), and the + // corresponding biased exponent in f32 is in range 103 to 112 (inclusive). + TINT_ASSERT((kMinF32BiasedExpForF16SubnormalNumber <= biased_exponent_original) && + (biased_exponent_original <= kMaxF32BiasedExpForF16SubnormalNumber)); + + // As we have proved, masking out the lowest 126-e mantissa bits of input value will result + // in a valid subnormal f16 value, which is exactly the required quantization result. + uint32_t discard_bits = 126 - biased_exponent_original; // In range 14 to 23 (inclusive) + TINT_ASSERT((14 <= discard_bits) && (discard_bits <= kF32MantissaBits)); + uint32_t discard_mask = (1u << discard_bits) - 1; + u32 = u32 & ~discard_mask; + } else { + // value is too small that it can't even be represented as subnormal f16 number. Quantize + // to zero. + return value > 0 ? 0.0 : -0.0; + } + + return tint::Bitcast(u32); +} + +uint16_t f16::BitsRepresentation() const { + // Assert we use binary32 (i.e. float) as underlying type, which has 4 bytes. + static_assert(std::is_same()); + + // The stored value in f16 object must be already quantized, so it should be either NaN, +/- + // Inf, or exactly representable by normal or subnormal f16. + + if (std::isnan(value)) { + return kF16Nan; + } + + if (std::isinf(value)) { + return value > 0 ? kF16PosInf : kF16NegInf; + } + + // Now quantized_value must be a finite f16 exactly-representable value. + // The following table shows exponent cases for all finite f16 exactly-representable value. + // --------------------------------------------------------------------------- + // | Value category | Unbiased exp | F16 biased exp | F32 biased exp | + // |------------------|----------------|------------------|------------------| + // | +/- zero | \ | 0 | 0 | + // | Subnormal f16 | [-24, -15] | 0 | [103, 112] | + // | Normal f16 | [-14, 15] | [1, 30] | [113, 142] | + // --------------------------------------------------------------------------- + + uint32_t f32_bit_pattern = tint::Bitcast(value); + uint32_t f32_biased_exponent = (f32_bit_pattern & kF32ExponentMask) >> kF32MantissaBits; + uint32_t f32_mantissa = f32_bit_pattern & kF32MantissaMask; + + uint16_t f16_sign_part = static_cast((f32_bit_pattern & kF32SignMask) >> 16); + TINT_ASSERT((f16_sign_part & ~kF16SignMask) == 0); + + if ((f32_bit_pattern & ~kF32SignMask) == 0) { + // +/- zero + return f16_sign_part; + } + + if ((kMinF32BiasedExpForF16NormalNumber <= f32_biased_exponent) && + (f32_biased_exponent <= kMaxF32BiasedExpForF16NormalNumber)) { + // Normal f16 + uint32_t f16_biased_exponent = f32_biased_exponent - kF32ExponentBias + kF16ExponentBias; + uint16_t f16_exp_part = static_cast(f16_biased_exponent << kF16MantissaBits); + uint16_t f16_mantissa_part = + static_cast(f32_mantissa >> (kF32MantissaBits - kF16MantissaBits)); + + TINT_ASSERT((f16_exp_part & ~kF16ExponentMask) == 0); + TINT_ASSERT((f16_mantissa_part & ~kF16MantissaMask) == 0); + + return f16_sign_part | f16_exp_part | f16_mantissa_part; + } + + if ((kMinF32BiasedExpForF16SubnormalNumber <= f32_biased_exponent) && + (f32_biased_exponent <= kMaxF32BiasedExpForF16SubnormalNumber)) { + // Subnormal f16 + // The resulting exp bits are always 0, and the mantissa bits should be handled specially. + uint16_t f16_exp_part = 0; + // The resulting subnormal f16 will have only 1 valid mantissa bit if the unbiased exponent + // of value is of the minimum, i.e. -24; and have all 10 mantissa bits valid if the unbiased + // exponent of value is of the maximum, i.e. -15. + uint32_t f16_valid_mantissa_bits = + f32_biased_exponent - kMinF32BiasedExpForF16SubnormalNumber + 1; + // The resulting f16 mantissa part comes from right-shifting the f32 mantissa bits with + // leading 1 added. + uint16_t f16_mantissa_part = + static_cast((f32_mantissa | (kF32MantissaMask + 1)) >> + (kF32MantissaBits + 1 - f16_valid_mantissa_bits)); + + TINT_ASSERT((1 <= f16_valid_mantissa_bits) && + (f16_valid_mantissa_bits <= kF16MantissaBits)); + TINT_ASSERT((f16_mantissa_part & ~((1u << f16_valid_mantissa_bits) - 1)) == 0); + TINT_ASSERT((f16_mantissa_part != 0)); + + return f16_sign_part | f16_exp_part | f16_mantissa_part; + } + + // Neither zero, subnormal f16 or normal f16, shall never hit. + TINT_UNREACHABLE(); +} + +// static +core::Number f16::FromBits(uint16_t bits) { + // Assert we use binary32 (i.e. float) as underlying type, which has 4 bytes. + static_assert(std::is_same()); + + if (bits == kF16PosInf) { + return f16(std::numeric_limits::infinity()); + } + if (bits == kF16NegInf) { + return f16(-std::numeric_limits::infinity()); + } + + auto f16_sign_bit = uint32_t(bits & kF16SignMask); + // If none of the other bits are set we have a 0. If only the sign bit is set we have a -0. + if ((bits & ~kF16SignMask) == 0) { + return f16(f16_sign_bit > 0 ? -0.f : 0.f); + } + + auto f16_mantissa = uint32_t(bits & kF16MantissaMask); + auto f16_biased_exponent = uint32_t(bits & kF16ExponentMask); + + // F16 NaN has all expoennt bits set and at least one mantissa bit set + if (((f16_biased_exponent & kF16ExponentMask) == kF16ExponentMask) && f16_mantissa != 0) { + return f16(std::numeric_limits::quiet_NaN()); + } + + // Shift the exponent over to be a regular number. + f16_biased_exponent >>= kF16MantissaBits; + + // Add the F32 bias and remove the F16 bias. + uint32_t f32_biased_exponent = f16_biased_exponent + kF32ExponentBias - kF16ExponentBias; + + if (f16_biased_exponent == 0) { + // Subnormal number + // + // All subnormal F16 values can be represented as normal F32 values. Shift the mantissa and + // set the exponent as if this was a normal f16 value. + + // While the first F16 exponent bit is not set + constexpr uint32_t kF16FirstExponentBit = 0x0400; + while ((f16_mantissa & kF16FirstExponentBit) == 0) { + // Shift the mantissa to the left + f16_mantissa <<= 1; + // Decrease the biased exponent to counter the shift + f32_biased_exponent -= 1; + } + + // Remove the first exponent bit from the mantissa value + f16_mantissa &= ~kF16FirstExponentBit; + // Increase the exponent to deal with the masked off value. + f32_biased_exponent += 1; + } + + // The mantissa bits are shifted over the difference in mantissa size to be in the F32 location. + uint32_t f32_mantissa = f16_mantissa << (kF32MantissaBits - kF16MantissaBits); + + // Shift the exponent to the F32 exponent position before the mantissa. + f32_biased_exponent <<= kF32MantissaBits; + + // Shift the sign bit over to the f32 sign bit position + uint32_t f32_sign_bit = f16_sign_bit << 16; + + // Combine values together into the F32 value as a uint32_t. + uint32_t val = f32_sign_bit | f32_biased_exponent | f32_mantissa; + + // Bitcast to a F32 and then store into the F16 Number + return f16(tint::Bitcast(val)); +} + +} // namespace tint::core diff --git a/3rdparty/dawn/src/tint/lang/core/number.h b/3rdparty/dawn/src/tint/lang/core/number.h new file mode 100644 index 000000000..61178fa44 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/number.h @@ -0,0 +1,787 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_NUMBER_H_ +#define SRC_TINT_LANG_CORE_NUMBER_H_ + +#include +#include +#include +#include +#include + +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/result.h" +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/string_stream.h" + +// Forward declaration +namespace tint::core { +/// Number wraps a integer or floating point number, enforcing explicit casting. +template +struct Number; +} // namespace tint::core + +namespace tint::core::detail { +/// Base template for IsNumber +template +struct IsNumber : std::false_type {}; + +/// Specialization for IsNumber +template +struct IsNumber> : std::true_type {}; + +/// An empty structure used as a unique template type for Number when +/// specializing for the f16 type. +struct NumberKindF16 {}; + +/// Helper for obtaining the underlying type for a Number. +template +struct NumberUnwrapper { + /// When T is not a Number, then type defined to be T. + using type = T; +}; + +/// NumberUnwrapper specialization for Number. +template +struct NumberUnwrapper> { + /// The Number's underlying type. + using type = typename Number::type; +}; + +} // namespace tint::core::detail + +namespace tint::core { + +/// Evaluates to true iff T is a Number +template +constexpr bool IsNumber = tint::core::detail::IsNumber::value; + +/// Resolves to the underlying type for a Number. +template +using UnwrapNumber = typename tint::core::detail::NumberUnwrapper::type; + +/// Evaluates to true iff T or Number is a floating-point type or is NumberKindF16. +template +constexpr bool IsFloatingPoint = std::is_floating_point_v> || + std::is_same_v, tint::core::detail::NumberKindF16>; + +/// Evaluates to true iff T or Number is an integral type. +template +constexpr bool IsIntegral = std::is_integral_v>; + +/// Evaluates to true iff T or Number is a signed integer type. +template +constexpr bool IsSignedIntegral = + std::is_integral_v> && std::is_signed_v>; + +/// Evaluates to true iff T or Number is an unsigned integer type. +template +constexpr bool IsUnsignedIntegral = + std::is_integral_v> && std::is_unsigned_v>; + +/// Evaluates to true iff T is an integer type, floating-point type or is NumberKindF16. +template +constexpr bool IsNumeric = IsIntegral || IsFloatingPoint; + +/// Returns the bit width of T +template +constexpr size_t BitWidth = sizeof(UnwrapNumber) * 8; + +/// NumberBase is a CRTP base class for Number +template +struct NumberBase { + /// @returns value of type `Number` with the highest value for that type. + static NumberT Highest() { return NumberT(NumberT::kHighestValue); } + /// @returns value of type `Number` with the lowest value for that type. + static NumberT Lowest() { return NumberT(NumberT::kLowestValue); } + /// @returns value of type `Number` with the smallest value for that type. + static NumberT Smallest() { return NumberT(NumberT::kSmallestValue); } + /// @returns value of type `Number` that represents NaN for that type. + static NumberT NaN() { + return NumberT(std::numeric_limits>::quiet_NaN()); + } + /// @returns value of type `Number` that represents infinity for that type. + static NumberT Inf() { return NumberT(std::numeric_limits>::infinity()); } +}; + +// Largest integers representable in the source floating point format. +// These values are chosen specifically to enable f32 clamping. +// See https://github.com/gpuweb/gpuweb/issues/5043 +constexpr int32_t kMaxI32WhichIsAlsoF32 = 0x7FFFFF80; +constexpr uint32_t kMaxU32WhichIsAlsoF32 = 0xFFFFFF00; + +/// Number wraps a integer or floating point number, enforcing explicit casting. +template +struct Number : NumberBase> { + static_assert(IsNumeric, "Number constructed with non-numeric type"); + + /// type is the underlying type of the Number + using type = T; + + /// Number of bits in the number. + static constexpr size_t kNumBits = sizeof(T) * 8; + + /// Highest finite representable value of this type. + static constexpr type kHighestValue = std::numeric_limits::max(); + + /// Lowest finite representable value of this type. + static constexpr type kLowestValue = std::numeric_limits::lowest(); + + /// Smallest positive normal value of this type. + static constexpr type kSmallestValue = + std::is_integral_v ? 0 : std::numeric_limits::min(); + + /// Smallest positive subnormal value of this type, 0 for integral type. + static constexpr type kSmallestSubnormalValue = + std::is_integral_v ? 0 : std::numeric_limits::denorm_min(); + + /// Constructor. The value is zero-initialized. + Number() = default; + + /// Constructor. + /// @param v the value to initialize this Number to + template + explicit Number(U v) : value(static_cast(v)) {} + + /// Constructor. + /// @param v the value to initialize this Number to + template + explicit Number(Number v) : value(static_cast(v.value)) {} + + /// Conversion operator + /// @returns the value as T + operator T() const { return value; } + + /// Negation operator + /// @returns the negative value of the number + Number operator-() const { return Number(-value); } + + /// Assignment operator + /// @param v the new value + /// @returns this Number so calls can be chained + Number& operator=(T v) { + value = v; + return *this; + } + + /// The number value + type value = {}; +}; + +/// Writes the number to the ostream. +/// @param out the stream to write to +/// @param num the Number +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Number num) { + return out << num.value; +} + +/// The partial specification of Number for f16 type, storing the f16 value as float, +/// and enforcing proper explicit casting. +template <> +struct Number + : NumberBase> { + /// C++ does not have a native float16 type, so we use a 32-bit float instead. + using type = float; + + /// Number of bits in the number. + static constexpr size_t kNumBits = 16; + + /// Highest finite representable value of this type. + static constexpr type kHighestValue = 65504.0f; // 2¹⁵ × (1 + 1023/1024) + + /// Lowest finite representable value of this type. + static constexpr type kLowestValue = -65504.0f; + + /// Smallest positive normal value of this type. + /// binary16 0_00001_0000000000, value is 2⁻¹⁴. + static constexpr type kSmallestValue = 0x1p-14f; + + /// Smallest positive subnormal value of this type. + /// binary16 0_00000_0000000001, value is 2⁻¹⁴ * 2⁻¹⁰ = 2⁻²⁴. + static constexpr type kSmallestSubnormalValue = 0x1p-24f; + + /// Constructor. The value is zero-initialized. + Number() = default; + + /// Constructor. + /// @param v the value to initialize this Number to + template + explicit Number(U v) : value(Quantize(static_cast(v))) {} + + /// Constructor. + /// @param v the value to initialize this Number to + template + explicit Number(Number v) : value(Quantize(static_cast(v.value))) {} + + /// Conversion operator + /// @returns the value as the internal representation type of F16 + operator float() const { return value; } + + /// Negation operator + /// @returns the negative value of the number + Number operator-() const { return Number(-value); } + + /// Assignment operator with parameter as native floating point type + /// @param v the new value + /// @returns this Number so calls can be chained + Number& operator=(type v) { + value = Quantize(v); + return *this; + } + + /// Get the binary16 bit pattern in type uint16_t of this value. + /// @returns the binary16 bit pattern, in type uint16_t, of the stored quantized f16 value. If + /// the value is NaN, the returned value will be 0x7e00u. If the value is positive infinity, the + /// returned value will be 0x7c00u. If the input value is negative infinity, the returned value + /// will be 0xfc00u. + uint16_t BitsRepresentation() const; + + /// 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 FromBits(uint16_t bits); + + /// @param value the input float32 value + /// @returns the float32 value quantized to the smaller float16 value, through truncation of the + /// mantissa bits (no rounding). If the float32 value is too large (positive or negative) to be + /// represented by a float16 value, then the returned value will be positive or negative + /// infinity. + static type Quantize(type value); + + /// The number value, stored as float + type value = {}; +}; + +/// `AInt` is a type alias to `Number`. +using AInt = Number; +/// `AFloat` is a type alias to `Number`. +using AFloat = Number; + +/// `i8` is a type alias to `Number`. +using i8 = Number; +/// `i32` is a type alias to `Number`. +using i32 = Number; +/// `u8` is a type alias to `Number`. +using u8 = Number; +/// `u32` is a type alias to `Number`. +using u32 = Number; +/// `u64` is a type alias to `Number`. +using u64 = Number; +/// `f32` is a type alias to `Number` +using f32 = Number; +/// `f16` is a type alias to `Number`, which should be IEEE 754 binary16. +/// However since C++ don't have native binary16 type, the value is stored as float. +using f16 = Number; + +/// The algorithms in this module require support for infinity and quiet NaNs on +/// floating point types. +static_assert(std::numeric_limits::has_infinity); +static_assert(std::numeric_limits::has_quiet_NaN); +static_assert(std::numeric_limits::has_infinity); +static_assert(std::numeric_limits::has_quiet_NaN); + +/// True iff T is an abstract number type +template +constexpr bool IsAbstract = std::is_same_v || std::is_same_v; + +/// @returns the friendly name of Number type T +template + requires(IsNumber) +const char* FriendlyName() { + if constexpr (std::is_same_v) { + return "abstract-int"; + } else if constexpr (std::is_same_v) { + return "abstract-float"; + } else if constexpr (std::is_same_v) { + return "i32"; + } else if constexpr (std::is_same_v) { + return "u32"; + } else if constexpr (std::is_same_v) { + return "f32"; + } else if constexpr (std::is_same_v) { + return "f16"; + } else { + static_assert(!sizeof(T), "Unhandled type"); + } +} + +/// @returns the friendly name of T when T is bool +template + requires(std::is_same_v) +const char* FriendlyName() { + return "bool"; +} + +/// Enumerator of failure reasons when converting from one number to another. +enum class ConversionFailure { + kExceedsPositiveLimit, // The value was too big (+'ve) to fit in the target type + kExceedsNegativeLimit, // The value was too big (-'ve) to fit in the target type +}; + +/// Writes the conversion failure message to the ostream. +/// @param out the stream to write to +/// @param failure the ConversionFailure +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, ConversionFailure failure) { + switch (failure) { + case ConversionFailure::kExceedsPositiveLimit: + return out << "value exceeds positive limit for type"; + case ConversionFailure::kExceedsNegativeLimit: + return out << "value exceeds negative limit for type"; + } + return out << ""; +} + +/// Converts a number from one type to another, checking that the value fits in the target type. +/// @param num the value to convert +/// @returns the resulting value of the conversion, or a failure reason. +template +tint::Result CheckedConvert(Number num) { + // Use the highest-precision integer or floating-point type to perform the comparisons. + using T = std::conditional_t> || IsFloatingPoint, + AFloat::type, AInt::type>; + const auto value = static_cast(num.value); + // Float to integral conversions clamp to the target range. + // https://gpuweb.github.io/gpuweb/wgsl/#scalar-floating-point-to-integral-conversion + constexpr auto float_to_integral = IsFloatingPoint && IsIntegral>; + if constexpr (std::is_same_v) { + // Special case checks for u64 as its range does not fit into an AInt. + if (value < 0) { + if constexpr (float_to_integral) { + return TO(0); + } + if constexpr (IsSignedIntegral) { + return ConversionFailure::kExceedsNegativeLimit; + } + } + } else if constexpr (std::is_same_v && + (std::is_same_v || std::is_same_v)) { + // The WGSL spec dictates that the conversion of f32 to u32/i32 saturates to integer + // values representable in float. This highly particular for f32 converting to u32/i32 for + // only the highest integer value. + const T kHighestIntWhichIsAlsoFloat = IsSignedIntegral + ? static_cast(kMaxI32WhichIsAlsoF32) + : static_cast(kMaxU32WhichIsAlsoF32); + if (value > kHighestIntWhichIsAlsoFloat) { + return TO(kHighestIntWhichIsAlsoFloat); + } + + if (value < static_cast(TO::kLowestValue)) { + return TO(TO::kLowestValue); + } + } else { + if (value > static_cast(TO::kHighestValue)) { + if (float_to_integral) { + return TO(TO::kHighestValue); + } + return ConversionFailure::kExceedsPositiveLimit; + } + if (value < static_cast(TO::kLowestValue)) { + if (float_to_integral) { + return TO(TO::kLowestValue); + } + return ConversionFailure::kExceedsNegativeLimit; + } + } + return TO(value); // Success +} + +/// Equality operator. +/// @param a the LHS number +/// @param b the RHS number +/// @returns true if the numbers `a` and `b` are exactly equal. +/// For floating point types, negative zero equals zero. +/// IEEE 754 says "Comparison shall ignore the sign of zero (so +0 = -0)." +template +bool operator==(Number a, Number b) { + // Use the highest-precision integer or floating-point type to perform the comparisons. + using T = + std::conditional_t || IsFloatingPoint, AFloat::type, AInt::type>; + auto va = static_cast(a.value); + auto vb = static_cast(b.value); + return std::equal_to()(va, vb); +} + +/// Inequality operator. +/// @param a the LHS number +/// @param b the RHS number +/// @returns true if the numbers `a` and `b` are exactly unequal. Also considers sign bit. +template +bool operator!=(Number a, Number b) { + return !(a == b); +} + +/// Equality operator. +/// @param a the LHS number +/// @param b the RHS number +/// @returns true if the numbers `a` and `b` are exactly equal. +template + requires(IsNumeric) +bool operator==(Number a, B b) { + return a == Number(b); +} + +/// Inequality operator. +/// @param a the LHS number +/// @param b the RHS number +/// @returns true if the numbers `a` and `b` are exactly unequal. +template + requires(IsNumeric) +bool operator!=(Number a, B b) { + return !(a == b); +} + +/// Equality operator. +/// @param a the LHS number +/// @param b the RHS number +/// @returns true if the numbers `a` and `b` are exactly equal. +template + requires(IsNumeric) +bool operator==(A a, Number b) { + return Number(a) == b; +} + +/// Inequality operator. +/// @param a the LHS number +/// @param b the RHS number +/// @returns true if the numbers `a` and `b` are exactly unequal. +template + requires(IsNumeric) +bool operator!=(A a, Number b) { + return !(a == b); +} + +/// Define 'TINT_HAS_OVERFLOW_BUILTINS' if the compiler provide overflow checking builtins. +/// If the compiler does not support these builtins, then these are emulated with algorithms +/// described in: +/// https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow +#if defined(__GNUC__) && __GNUC__ >= 5 +#define TINT_HAS_OVERFLOW_BUILTINS +#elif defined(__clang__) +#if __has_builtin(__builtin_add_overflow) && __has_builtin(__builtin_mul_overflow) +#define TINT_HAS_OVERFLOW_BUILTINS +#endif +#endif + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a + b, or an empty optional if the resulting value overflowed the AInt +inline std::optional CheckedAdd(AInt a, AInt b) { + int64_t result; +#ifdef TINT_HAS_OVERFLOW_BUILTINS + if (__builtin_add_overflow(a.value, b.value, &result)) { + return {}; + } +#else // TINT_HAS_OVERFLOW_BUILTINS + if (a.value >= 0) { + if (b.value > AInt::kHighestValue - a.value) { + return {}; + } + } else { + if (b.value < AInt::kLowestValue - a.value) { + return {}; + } + } + result = a.value + b.value; +#endif // TINT_HAS_OVERFLOW_BUILTINS + return AInt(result); +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a + b, or an empty optional if the resulting value overflowed the float value +template + requires(IsFloatingPoint) +inline std::optional CheckedAdd(FloatingPointT a, FloatingPointT b) { + auto result = FloatingPointT{a.value + b.value}; + if (!std::isfinite(result.value)) { + return {}; + } + return result; +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a - b, or an empty optional if the resulting value overflowed the AInt +inline std::optional CheckedSub(AInt a, AInt b) { + int64_t result; +#ifdef TINT_HAS_OVERFLOW_BUILTINS + if (__builtin_sub_overflow(a.value, b.value, &result)) { + return {}; + } +#else // TINT_HAS_OVERFLOW_BUILTINS + if (b.value >= 0) { + if (a.value < AInt::kLowestValue + b.value) { + return {}; + } + } else { + if (a.value > AInt::kHighestValue + b.value) { + return {}; + } + } + result = a.value - b.value; +#endif // TINT_HAS_OVERFLOW_BUILTINS + return AInt(result); +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a + b, or an empty optional if the resulting value overflowed the float value +template + requires(IsFloatingPoint) +inline std::optional CheckedSub(FloatingPointT a, FloatingPointT b) { + auto result = FloatingPointT{a.value - b.value}; + if (!std::isfinite(result.value)) { + return {}; + } + return result; +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a * b, or an empty optional if the resulting value overflowed the AInt +inline std::optional CheckedMul(AInt a, AInt b) { + int64_t result; +#ifdef TINT_HAS_OVERFLOW_BUILTINS + if (__builtin_mul_overflow(a.value, b.value, &result)) { + return {}; + } +#else // TINT_HAS_OVERFLOW_BUILTINS + if (a > 0) { + if (b > 0) { + if (a > (AInt::kHighestValue / b)) { + return {}; + } + } else { + if (b < (AInt::kLowestValue / a)) { + return {}; + } + } + } else { + if (b > 0) { + if (a < (AInt::kLowestValue / b)) { + return {}; + } + } else { + if ((a != 0) && (b < (AInt::kHighestValue / a))) { + return {}; + } + } + } + result = a.value * b.value; +#endif // TINT_HAS_OVERFLOW_BUILTINS + return AInt(result); +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a * b, or an empty optional if the resulting value overflowed the float value +template + requires(IsFloatingPoint) +inline std::optional CheckedMul(FloatingPointT a, FloatingPointT b) { + auto result = FloatingPointT{a.value * b.value}; + if (!std::isfinite(result.value)) { + return {}; + } + return result; +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a / b, or an empty optional if the resulting value overflowed the AInt +inline std::optional CheckedDiv(AInt a, AInt b) { + if (b == 0) { + return {}; + } + + if (b == -1 && a == AInt::Lowest()) { + return {}; + } + + return AInt{a.value / b.value}; +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns a / b, or an empty optional if the resulting value overflowed the float value +template + requires(IsFloatingPoint) +inline std::optional CheckedDiv(FloatingPointT a, FloatingPointT b) { + if (b == FloatingPointT{0.0}) { + return {}; + } + auto result = FloatingPointT{a.value / b.value}; + if (!std::isfinite(result.value)) { + return {}; + } + return result; +} + +namespace detail { +/// @param e1 the LHS number +/// @param e2 the RHS number +/// @returns the remainder of e1 / e2 +template +inline T Mod(T e1, T e2) { + if constexpr (IsIntegral) { + return e1 % e2; + + } else { + return e1 - e2 * std::trunc(e1 / e2); + } +} +} // namespace detail + +/// @param a the LHS number +/// @param b the RHS number +/// @returns the remainder of a / b, or an empty optional if the resulting value overflowed the AInt +inline std::optional CheckedMod(AInt a, AInt b) { + if (b == 0) { + return {}; + } + + if (b == -1 && a == AInt::Lowest()) { + return {}; + } + + return AInt{tint::core::detail::Mod(a.value, b.value)}; +} + +/// @param a the LHS number +/// @param b the RHS number +/// @returns the remainder of a / b, or an empty optional if the resulting value overflowed the +/// float value +template + requires(IsFloatingPoint) +inline std::optional CheckedMod(FloatingPointT a, FloatingPointT b) { + if (b == FloatingPointT{0.0}) { + return {}; + } + auto result = FloatingPointT{tint::core::detail::Mod(a.value, b.value)}; + if (!std::isfinite(result.value)) { + return {}; + } + return result; +} + +/// @param a the LHS number of the multiply +/// @param b the RHS number of the multiply +/// @param c the RHS number of the addition +/// @returns a * b + c, or an empty optional if the value overflowed the AInt +inline std::optional CheckedMadd(AInt a, AInt b, AInt c) { + if (auto mul = CheckedMul(a, b)) { + return CheckedAdd(mul.value(), c); + } + return {}; +} + +/// @param base the base number of the exponent operation +/// @param exp the exponent +/// @returns the value of `base` raised to the power `exp`, or an empty optional if the operation +/// cannot be performed. +template + requires(IsFloatingPoint) +inline std::optional CheckedPow(FloatingPointT base, FloatingPointT exp) { + static_assert(IsNumber); + if ((base < 0) || (base == 0 && exp <= 0)) { + return {}; + } + auto result = FloatingPointT{std::pow(base.value, exp.value)}; + if (!std::isfinite(result.value)) { + return {}; + } + return result; +} + +} // namespace tint::core + +namespace tint::core::number_suffixes { + +/// Literal suffix for abstract integer literals +inline AInt operator""_a(unsigned long long int value) { // NOLINT + return AInt(static_cast(value)); +} + +/// Literal suffix for abstract float literals +inline AFloat operator""_a(long double value) { // NOLINT + return AFloat(static_cast(value)); +} + +/// Literal suffix for i32 literals +inline i32 operator""_i(unsigned long long int value) { // NOLINT + return i32(static_cast(value)); +} + +/// Literal suffix for u32 literals +inline u32 operator""_u(unsigned long long int value) { // NOLINT + return u32(static_cast(value)); +} + +/// Literal suffix for f32 literals +inline f32 operator""_f(long double value) { // NOLINT + return f32(static_cast(value)); +} + +/// Literal suffix for f32 literals +inline f32 operator""_f(unsigned long long int value) { // NOLINT + return f32(static_cast(value)); +} + +/// Literal suffix for f16 literals +inline f16 operator""_h(long double value) { // NOLINT + return f16(static_cast(value)); +} + +/// Literal suffix for f16 literals +inline f16 operator""_h(unsigned long long int value) { // NOLINT + return f16(static_cast(value)); +} + +} // namespace tint::core::number_suffixes + +namespace std { + +/// Custom std::hash specialization for tint::Number +template +class hash> { + public: + /// @param n the Number + /// @return the hash value + inline std::size_t operator()(const tint::core::Number& n) const { + return std::hash()(n.value); + } +}; + +} // namespace std + +#endif // SRC_TINT_LANG_CORE_NUMBER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/abstract_float.cc b/3rdparty/dawn/src/tint/lang/core/type/abstract_float.cc new file mode 100644 index 000000000..7bc7e7642 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/abstract_float.cc @@ -0,0 +1,49 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/abstract_float.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/math/hash.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::AbstractFloat); + +namespace tint::core::type { + +AbstractFloat::AbstractFloat() : Base(Hash(tint::TypeCode::Of().bits)) {} + +AbstractFloat::~AbstractFloat() = default; + +std::string AbstractFloat::FriendlyName() const { + return "abstract-float"; +} + +AbstractFloat* AbstractFloat::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/abstract_float.h b/3rdparty/dawn/src/tint/lang/core/type/abstract_float.h new file mode 100644 index 000000000..d97afb77f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/abstract_float.h @@ -0,0 +1,57 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_ABSTRACT_FLOAT_H_ +#define SRC_TINT_LANG_CORE_TYPE_ABSTRACT_FLOAT_H_ + +#include + +#include "src/tint/lang/core/type/abstract_numeric.h" + +namespace tint::core::type { + +/// An abstract-float type. +/// @see https://www.w3.org/TR/WGSL/#abstractFloat +class AbstractFloat final : public Castable { + public: + /// Constructor + AbstractFloat(); + + /// Destructor + ~AbstractFloat() override; + + /// @returns the name for this type when printed in diagnostics. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + AbstractFloat* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_ABSTRACT_FLOAT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/abstract_int.cc b/3rdparty/dawn/src/tint/lang/core/type/abstract_int.cc new file mode 100644 index 000000000..bd5189793 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/abstract_int.cc @@ -0,0 +1,49 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/abstract_int.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/math/hash.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::AbstractInt); + +namespace tint::core::type { + +AbstractInt::AbstractInt() : Base(Hash(tint::TypeCode::Of().bits)) {} + +AbstractInt::~AbstractInt() = default; + +std::string AbstractInt::FriendlyName() const { + return "abstract-int"; +} + +AbstractInt* AbstractInt::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/abstract_int.h b/3rdparty/dawn/src/tint/lang/core/type/abstract_int.h new file mode 100644 index 000000000..5c027f673 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/abstract_int.h @@ -0,0 +1,57 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_ABSTRACT_INT_H_ +#define SRC_TINT_LANG_CORE_TYPE_ABSTRACT_INT_H_ + +#include + +#include "src/tint/lang/core/type/abstract_numeric.h" + +namespace tint::core::type { + +/// An abstract-int type. +/// @see https://www.w3.org/TR/WGSL/#abstractint +class AbstractInt final : public Castable { + public: + /// Constructor + AbstractInt(); + + /// Destructor + ~AbstractInt() override; + + /// @returns the name for this type when printed in diagnostics. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + AbstractInt* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_ABSTRACT_INT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.cc b/3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.cc new file mode 100644 index 000000000..819b86cfe --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.cc @@ -0,0 +1,51 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/abstract_numeric.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::AbstractNumeric); + +namespace tint::core::type { + +AbstractNumeric::AbstractNumeric(size_t hash) + : Base(hash, + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }) {} +AbstractNumeric::~AbstractNumeric() = default; + +uint32_t AbstractNumeric::Size() const { + return 0; +} + +uint32_t AbstractNumeric::Align() const { + return 0; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.h b/3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.h new file mode 100644 index 000000000..0bd231b1c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/abstract_numeric.h @@ -0,0 +1,57 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_ABSTRACT_NUMERIC_H_ +#define SRC_TINT_LANG_CORE_TYPE_ABSTRACT_NUMERIC_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// The base class for abstract-int and abstract-float types. +/// @see https://www.w3.org/TR/WGSL/#types-for-creation-time-constants +class AbstractNumeric : public Castable { + public: + /// Constructor + /// @param hash the unique hash of the node + explicit AbstractNumeric(size_t hash); + + /// Destructor + ~AbstractNumeric() override; + + /// @returns 0, as the type is abstract. + uint32_t Size() const override; + + /// @returns 0, as the type is abstract. + uint32_t Align() const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_ABSTRACT_NUMERIC_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/array.cc b/3rdparty/dawn/src/tint/lang/core/type/array.cc new file mode 100644 index 000000000..6299d0a34 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/array.cc @@ -0,0 +1,135 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/array.h" + +#include + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/symbol/symbol_table.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Array); + +namespace tint::core::type { + +namespace { + +core::type::Flags FlagsFrom(const Type* element, const ArrayCount* count) { + core::type::Flags flags; + // Only constant-expression sized arrays are constructible + if (count->Is()) { + if (element->IsConstructible()) { + flags.Add(Flag::kConstructable); + } + if (element->HasCreationFixedFootprint()) { + flags.Add(Flag::kCreationFixedFootprint); + } + } + if (!count->Is()) { + if (element->HasFixedFootprint()) { + flags.Add(Flag::kFixedFootprint); + } + } + if (element->IsHostShareable()) { + flags.Add(Flag::kHostShareable); + } + return flags; +} + +} // namespace + +const char* const Array::kErrExpectedConstantCount = + "array size is an override-expression, when expected a constant-expression.\n" + "Was the SubstituteOverride transform run?"; + +Array::Array(const Type* element, const ArrayCount* count, uint32_t size) + : Base(Hash(tint::TypeCode::Of().bits, count, size), FlagsFrom(element, count)), + element_(element), + count_(count), + size_(size) { + TINT_ASSERT(count_); + TINT_ASSERT(element_); +} + +Array::Array(size_t hash, const Type* element, const ArrayCount* count, uint32_t size) + : Base(hash, FlagsFrom(element, count)), element_(element), count_(count), size_(size) { + TINT_ASSERT(count_); + TINT_ASSERT(element_); +} + +bool Array::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->element_ == element_ && o->count_ == count_ && o->size_ == size_; + } + return false; +} + +std::string Array::FriendlyName() const { + StringStream out; + out << "array<" << element_->FriendlyName(); + + auto count_str = count_->FriendlyName(); + if (!count_str.empty()) { + out << ", " << count_str; + } + + out << ">"; + return out.str(); +} + +uint32_t Array::Size() const { + return size_; +} + +TypeAndCount Array::Elements(const Type* /* type_if_invalid = nullptr */, + uint32_t count_if_invalid /* = 0 */) const { + uint32_t n = count_if_invalid; + if (auto* const_count = count_->As()) { + n = const_count->value; + } + return {element_, n}; +} + +const Type* Array::Element(uint32_t index) const { + if (auto* count = count_->As()) { + return index < count->value ? element_ : nullptr; + } + return element_; +} + +Array* Array::Clone(CloneContext& ctx) const { + auto* elem_ty = element_->Clone(ctx); + auto* count = count_->Clone(ctx); + + return ctx.dst.mgr->Get(elem_ty, count, size_); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/array.h b/3rdparty/dawn/src/tint/lang/core/type/array.h new file mode 100644 index 000000000..8d5832a80 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/array.h @@ -0,0 +1,116 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_ARRAY_H_ +#define SRC_TINT_LANG_CORE_TYPE_ARRAY_H_ + +#include +#include +#include +#include + +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/macros/compiler.h" + +namespace tint::core::type { + +/// Array holds the type information for Array nodes. +class Array : public Castable { + public: + /// An error message string stating that the array count was expected to be a constant + /// expression. Used by multiple writers and transforms. + static const char* const kErrExpectedConstantCount; + + /// Constructor + /// @param element the array element type + /// @param count the number of elements in the array. + /// @param size the byte size of the array. The size will be 0 if the array element count is + /// pipeline overridable. + Array(Type const* element, const ArrayCount* count, uint32_t size); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @return the array element type + Type const* ElemType() const { return element_; } + + /// @returns the number of elements in the array. + const ArrayCount* Count() const { return count_; } + + /// @returns the array count if the count is a const-expression, otherwise returns nullopt. + inline std::optional ConstantCount() const { + if (auto* count = count_->As()) { + return count->value; + } + return std::nullopt; + } + + /// @returns the byte alignment of the array + uint32_t Align() const override { return element_->Align(); } + + /// @returns the byte size of the array + /// @note this may differ from the size of a structure member of this array + /// type, if the member is annotated with the `@size(n)` attribute. + uint32_t Size() const override; + + /// @returns the number of bytes from the start of one element to the start of the next element + uint32_t ImplicitStride() const { return tint::RoundUp(element_->Align(), element_->Size()); } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @copydoc Type::Elements + TypeAndCount Elements(const Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc Type::Element + const Type* Element(uint32_t index) const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Array* Clone(CloneContext& ctx) const override; + + protected: + /// Constructor for subclasses + /// @param hash the immutable hash for the node + /// @param element the array element type + /// @param count the number of elements in the array. + /// @param size the byte size of the array. + Array(size_t hash, Type const* element, const ArrayCount* count, uint32_t size); + + Type const* const element_; + const ArrayCount* count_; + const uint32_t size_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_ARRAY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/array_count.cc b/3rdparty/dawn/src/tint/lang/core/type/array_count.cc new file mode 100644 index 000000000..6049bc933 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/array_count.cc @@ -0,0 +1,76 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/array_count.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::ArrayCount); +TINT_INSTANTIATE_TYPEINFO(tint::core::type::ConstantArrayCount); +TINT_INSTANTIATE_TYPEINFO(tint::core::type::RuntimeArrayCount); + +namespace tint::core::type { + +ArrayCount::ArrayCount(size_t hash) : Base(hash) {} +ArrayCount::~ArrayCount() = default; + +ConstantArrayCount::ConstantArrayCount(uint32_t val) + : Base(static_cast(tint::TypeCode::Of().bits)), value(val) {} +ConstantArrayCount::~ConstantArrayCount() = default; + +bool ConstantArrayCount::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return value == v->value; + } + return false; +} + +std::string ConstantArrayCount::FriendlyName() const { + return std::to_string(value); +} + +ConstantArrayCount* ConstantArrayCount::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(value); +} + +RuntimeArrayCount::RuntimeArrayCount() + : Base(static_cast(tint::TypeCode::Of().bits)) {} +RuntimeArrayCount::~RuntimeArrayCount() = default; + +bool RuntimeArrayCount::Equals(const UniqueNode& other) const { + return other.Is(); +} + +std::string RuntimeArrayCount::FriendlyName() const { + return ""; +} + +RuntimeArrayCount* RuntimeArrayCount::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/array_count.h b/3rdparty/dawn/src/tint/lang/core/type/array_count.h new file mode 100644 index 000000000..74c9eb408 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/array_count.h @@ -0,0 +1,111 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_ARRAY_COUNT_H_ +#define SRC_TINT_LANG_CORE_TYPE_ARRAY_COUNT_H_ + +#include +#include + +#include "src/tint/lang/core/type/clone_context.h" +#include "src/tint/lang/core/type/unique_node.h" +#include "src/tint/utils/symbol/symbol_table.h" + +namespace tint::core::type { + +/// An array count +class ArrayCount : public Castable { + public: + ~ArrayCount() override; + + /// @returns the friendly name for this array count + virtual std::string FriendlyName() const = 0; + + /// @param ctx the clone context + /// @returns a clone of this type + virtual ArrayCount* Clone(CloneContext& ctx) const = 0; + + protected: + /// Constructor + /// @param hash the unique hash of the node + explicit ArrayCount(size_t hash); +}; + +/// The variant of an ArrayCount when the array is a const-expression. +/// Example: +/// ``` +/// const N = 123; +/// type arr = array +/// ``` +class ConstantArrayCount final : public Castable { + public: + /// Constructor + /// @param val the constant-expression value + explicit ConstantArrayCount(uint32_t val); + ~ConstantArrayCount() override; + + /// @param other the other object + /// @returns true if this array count is equal to other + bool Equals(const UniqueNode& other) const override; + + /// @returns the friendly name for this array count + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + ConstantArrayCount* Clone(CloneContext& ctx) const override; + + /// The array count constant-expression value. + uint32_t value; +}; + +/// The variant of an ArrayCount when the array is is runtime-sized. +/// Example: +/// ``` +/// type arr = array +/// ``` +class RuntimeArrayCount final : public Castable { + public: + /// Constructor + RuntimeArrayCount(); + ~RuntimeArrayCount() override; + + /// @param other the other object + /// @returns true if this array count is equal to other + bool Equals(const UniqueNode& other) const override; + + /// @returns the friendly name for this array count + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + RuntimeArrayCount* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_ARRAY_COUNT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/atomic.cc b/3rdparty/dawn/src/tint/lang/core/type/atomic.cc new file mode 100644 index 000000000..d72476d02 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/atomic.cc @@ -0,0 +1,80 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/atomic.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Atomic); + +namespace tint::core::type { + +Atomic::Atomic(const core::type::Type* subtype) + : Base(Hash(tint::TypeCode::Of().bits, subtype), + core::type::Flags{ + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }), + subtype_(subtype) { + TINT_ASSERT(!subtype->Is()); +} + +bool Atomic::Equals(const core::type::UniqueNode& other) const { + if (auto* o = other.As()) { + return o->subtype_ == subtype_; + } + return false; +} + +std::string Atomic::FriendlyName() const { + StringStream out; + out << "atomic<" << subtype_->FriendlyName() << ">"; + return out.str(); +} + +uint32_t Atomic::Size() const { + return subtype_->Size(); +} + +uint32_t Atomic::Align() const { + return subtype_->Align(); +} + +Atomic::~Atomic() = default; + +Atomic* Atomic::Clone(CloneContext& ctx) const { + auto* ty = subtype_->Clone(ctx); + return ctx.dst.mgr->Get(ty); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/atomic.h b/3rdparty/dawn/src/tint/lang/core/type/atomic.h new file mode 100644 index 000000000..ddf335b62 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/atomic.h @@ -0,0 +1,74 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_ATOMIC_H_ +#define SRC_TINT_LANG_CORE_TYPE_ATOMIC_H_ + +#include + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A atomic type. +class Atomic final : public Castable { + public: + /// Constructor + /// @param subtype the atomic type + explicit Atomic(const core::type::Type* subtype); + + /// Destructor + ~Atomic() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const core::type::UniqueNode& other) const override; + + /// @returns the atomic type + const core::type::Type* Type() const { return subtype_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Atomic* Clone(CloneContext& ctx) const override; + + private: + core::type::Type const* const subtype_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_ATOMIC_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/binding_array.cc b/3rdparty/dawn/src/tint/lang/core/type/binding_array.cc new file mode 100644 index 000000000..a8fa53764 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/binding_array.cc @@ -0,0 +1,81 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/binding_array.h" + +#include + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/symbol/symbol_table.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::BindingArray); + +namespace tint::core::type { + +BindingArray::BindingArray(const Type* element, const ArrayCount* count) + : Base(Hash(tint::TypeCode::Of().bits, count), core::type::Flags{}), + element_(element), + count_(count) { + TINT_ASSERT(element_); +} + +bool BindingArray::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->element_ == element_ && o->count_ == count_; + } + return false; +} + +uint32_t BindingArray::Align() const { + return 1; +} + +std::string BindingArray::FriendlyName() const { + StringStream out; + out << "binding_array<" << element_->FriendlyName() << ", " << count_->FriendlyName() << ">"; + return out.str(); +} + +TypeAndCount BindingArray::Elements([[maybe_unused]] const Type*, + [[maybe_unused]] uint32_t count_if_invalid) const { + return {element_, count_->As()->value}; +} + +const Type* BindingArray::Element(uint32_t index) const { + return index < count_->As()->value ? element_ : nullptr; +} + +BindingArray* BindingArray::Clone(CloneContext& ctx) const { + auto* elem_ty = element_->Clone(ctx); + auto* count = count_->Clone(ctx); + return ctx.dst.mgr->Get(elem_ty, count); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/binding_array.h b/3rdparty/dawn/src/tint/lang/core/type/binding_array.h new file mode 100644 index 000000000..93c6df4bd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/binding_array.h @@ -0,0 +1,84 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_BINDING_ARRAY_H_ +#define SRC_TINT_LANG_CORE_TYPE_BINDING_ARRAY_H_ + +#include +#include +#include + +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/macros/compiler.h" + +namespace tint::core::type { + +/// Array holds the type information for BindingArray nodes. +class BindingArray : public Castable { + public: + /// Constructor + /// @param element the array element type + /// @param count the number of elements in the array. + BindingArray(Type const* element, const ArrayCount* count); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @return the array element type + Type const* ElemType() const { return element_; } + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @returns the number of elements in the array. + const ArrayCount* Count() const { return count_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @copydoc Type::Elements + TypeAndCount Elements(const Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc Type::Element + const Type* Element(uint32_t index) const override; + + /// @param ctx the clone context + /// @returns a clone of this type + BindingArray* Clone(CloneContext& ctx) const override; + + private: + Type const* const element_; + const ArrayCount* count_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_BINDING_ARRAY_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/bool.cc b/3rdparty/dawn/src/tint/lang/core/type/bool.cc new file mode 100644 index 000000000..1a86fed28 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/bool.cc @@ -0,0 +1,62 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/bool.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Bool); + +namespace tint::core::type { + +Bool::Bool() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }) {} + +Bool::~Bool() = default; + +std::string Bool::FriendlyName() const { + return "bool"; +} + +uint32_t Bool::Size() const { + return 4; +} + +uint32_t Bool::Align() const { + return 4; +} + +Bool* Bool::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/bool.h b/3rdparty/dawn/src/tint/lang/core/type/bool.h new file mode 100644 index 000000000..670646513 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/bool.h @@ -0,0 +1,73 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_BOOL_H_ +#define SRC_TINT_LANG_CORE_TYPE_BOOL_H_ + +#include + +#include "src/tint/lang/core/type/scalar.h" + +// X11 likes to #define Bool leading to confusing error messages. +// If its defined, undefine it. +#ifdef Bool +#undef Bool +#endif + +namespace tint::core::type { + +/// A boolean type +class Bool final : public Castable { + public: + /// Constructor + Bool(); + + /// Destructor + ~Bool() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. + /// @note: booleans are not host-sharable, but still may exist in workgroup + /// storage. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + /// @note: booleans are not host-sharable, but still may exist in workgroup + /// storage. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Bool* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_BOOL_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/buffer.cc b/3rdparty/dawn/src/tint/lang/core/type/buffer.cc new file mode 100644 index 000000000..44b972b3a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/buffer.cc @@ -0,0 +1,70 @@ +// Copyright 2026 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/buffer.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Buffer); + +namespace tint::core::type { + +Buffer::Buffer(const ArrayCount* size) + : Base(Hash(tint::TypeCode::Of().bits, size), core::type::Flags{Flag::kHostShareable}), + count_(size) {} + +Buffer::~Buffer() = default; + +bool Buffer::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return count_ == v->count_; + } + return false; +} + +uint32_t Buffer::Size() const { + if (auto count = ConstantCount()) { + return count.value(); + } + return 0; +} + +std::string Buffer::FriendlyName() const { + StringStream out; + out << "buffer"; + auto count_str = count_->FriendlyName(); + if (!count_str.empty()) { + out << "<" << count_str << ">"; + } + return out.str(); +} + +Buffer* Buffer::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(count_->Clone(ctx)); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/buffer.h b/3rdparty/dawn/src/tint/lang/core/type/buffer.h new file mode 100644 index 000000000..d78a89b3d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/buffer.h @@ -0,0 +1,81 @@ +// Copyright 2026 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_BUFFER_H_ +#define SRC_TINT_LANG_CORE_TYPE_BUFFER_H_ + +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/core/type/clone_context.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A buffer type +class Buffer : public Castable { + public: + /// Constructor + /// @param size the size of the buffer + explicit Buffer(const ArrayCount* size); + + /// Destructor + ~Buffer() override; + + /// @param other the other node to compare against + /// @returns true if this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + const ArrayCount* Count() const { return count_; } + + /// @returns the buffer size if the count is a const-expression, otherwise returns nullopt. + inline std::optional ConstantCount() const { + if (auto* count = count_->As()) { + return count->value; + } + return std::nullopt; + } + + /// @returns the size of the buffer + uint32_t Size() const override; + + /// @returns the name for this type that closely resembles how it would be declared in WGSL + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Buffer* Clone(CloneContext& ctx) const override; + + private: + const ArrayCount* count_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_BUFFER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/builtin_structs.cc b/3rdparty/dawn/src/tint/lang/core/type/builtin_structs.cc new file mode 100644 index 000000000..47664f0ec --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/builtin_structs.cc @@ -0,0 +1,198 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/builtin_structs.h" + +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/symbol/symbol_table.h" +#include "src/tint/utils/text/string.h" + +namespace tint::core::type { + +/// An array of `modf()` return type names for an argument of `vecN`. +constexpr std::array kModfVecF32Names{ + core::BuiltinType::kModfResultVec2F32, // return type of modf(vec2) + core::BuiltinType::kModfResultVec3F32, // return type of modf(vec3) + core::BuiltinType::kModfResultVec4F32, // return type of modf(vec4) +}; + +/// An array of `modf()` return type names for an argument of `vecN`. +constexpr std::array kModfVecF16Names{ + core::BuiltinType::kModfResultVec2F16, // return type of modf(vec2) + core::BuiltinType::kModfResultVec3F16, // return type of modf(vec3) + core::BuiltinType::kModfResultVec4F16, // return type of modf(vec4) +}; + +/// An array of `modf()` return type names for an argument of `vecN`. +constexpr std::array kModfVecAbstractNames{ + core::BuiltinType::kModfResultVec2Abstract, // return type of modf(vec2) + core::BuiltinType::kModfResultVec3Abstract, // return type of modf(vec3) + core::BuiltinType::kModfResultVec4Abstract, // return type of modf(vec4) +}; + +Struct* CreateModfResult(Manager& types, SymbolTable& symbols, const Type* ty) { + auto build = [&](core::BuiltinType name, const Type* t) { + auto symbol = symbols.Register(tint::ToString(name)); + if (auto* existing = types.Find(symbol, /* is_wgsl_internal */ true)) { + return existing; + } + return types.WgslInternalStruct( + symbol, {{symbols.Register("fract"), t}, {symbols.Register("whole"), t}}); + }; + return Switch( + ty, // + [&](const F32*) { return build(core::BuiltinType::kModfResultF32, ty); }, + [&](const F16*) { return build(core::BuiltinType::kModfResultF16, ty); }, + [&](const AbstractFloat*) { + auto* abstract = build(core::BuiltinType::kModfResultAbstract, ty); + abstract->SetConcreteTypes(tint::Vector{ + build(core::BuiltinType::kModfResultF32, types.f32()), + build(core::BuiltinType::kModfResultF16, types.f16()), + }); + return abstract; + }, + [&](const Vector* vec) { + auto width = vec->Width(); + return Switch( + vec->Type(), // + [&](const F32*) { return build(kModfVecF32Names[width - 2], vec); }, + [&](const F16*) { return build(kModfVecF16Names[width - 2], vec); }, + [&](const AbstractFloat*) { + auto* abstract = build(kModfVecAbstractNames[width - 2], vec); + abstract->SetConcreteTypes(tint::Vector{ + build(kModfVecF32Names[width - 2], types.vec(types.f32(), width)), + build(kModfVecF16Names[width - 2], types.vec(types.f16(), width)), + }); + return abstract; + }, // + TINT_ICE_ON_NO_MATCH); + }, // + TINT_ICE_ON_NO_MATCH); +} + +/// An array of `frexp()` return type names for an argument of `vecN`. +constexpr std::array kFrexpVecF32Names{ + core::BuiltinType::kFrexpResultVec2F32, // return type of frexp(vec2) + core::BuiltinType::kFrexpResultVec3F32, // return type of frexp(vec3) + core::BuiltinType::kFrexpResultVec4F32, // return type of frexp(vec4) +}; + +/// An array of `frexp()` return type names for an argument of `vecN`. +constexpr std::array kFrexpVecF16Names{ + core::BuiltinType::kFrexpResultVec2F16, // return type of frexp(vec2) + core::BuiltinType::kFrexpResultVec3F16, // return type of frexp(vec3) + core::BuiltinType::kFrexpResultVec4F16, // return type of frexp(vec4) +}; + +/// An array of `frexp()` return type names for an argument of `vecN`. +constexpr std::array kFrexpVecAbstractNames{ + core::BuiltinType::kFrexpResultVec2Abstract, // return type of frexp(vec2) + core::BuiltinType::kFrexpResultVec3Abstract, // return type of frexp(vec3) + core::BuiltinType::kFrexpResultVec4Abstract, // return type of frexp(vec4) +}; + +Struct* CreateFrexpResult(Manager& types, SymbolTable& symbols, const Type* ty) { + auto build = [&](core::BuiltinType name, const Type* fract_ty, const Type* exp_ty) { + auto symbol = symbols.Register(tint::ToString(name)); + if (auto* existing = types.Find(symbol, /* is_wgsl_internal */ true)) { + return existing; + } + return types.WgslInternalStruct( + symbol, {{symbols.Register("fract"), fract_ty}, {symbols.Register("exp"), exp_ty}}); + }; + return Switch( + ty, // + [&](const F32*) { return build(core::BuiltinType::kFrexpResultF32, ty, types.i32()); }, + [&](const F16*) { return build(core::BuiltinType::kFrexpResultF16, ty, types.i32()); }, + [&](const AbstractFloat*) { + auto* abstract = build(core::BuiltinType::kFrexpResultAbstract, ty, types.AInt()); + abstract->SetConcreteTypes(tint::Vector{ + build(core::BuiltinType::kFrexpResultF32, types.f32(), types.i32()), + build(core::BuiltinType::kFrexpResultF16, types.f16(), types.i32()), + }); + return abstract; + }, + [&](const Vector* vec) { + auto width = vec->Width(); + return Switch( + vec->Type(), // + [&](const F32*) { + return build(kFrexpVecF32Names[width - 2], ty, types.vec(types.i32(), width)); + }, + [&](const F16*) { + return build(kFrexpVecF16Names[width - 2], ty, types.vec(types.i32(), width)); + }, + [&](const AbstractFloat*) { + auto* vec_f32 = types.vec(types.f32(), width); + auto* vec_f16 = types.vec(types.f16(), width); + auto* vec_i32 = types.vec(types.i32(), width); + auto* vec_ai = types.vec(types.AInt(), width); + auto* abstract = build(kFrexpVecAbstractNames[width - 2], ty, vec_ai); + abstract->SetConcreteTypes(tint::Vector{ + build(kFrexpVecF32Names[width - 2], vec_f32, vec_i32), + build(kFrexpVecF16Names[width - 2], vec_f16, vec_i32), + }); + return abstract; + }, // + TINT_ICE_ON_NO_MATCH); + }, // + TINT_ICE_ON_NO_MATCH); +} + +Struct* CreateAtomicCompareExchangeResult(Manager& types, SymbolTable& symbols, const Type* ty) { + auto build = [&](core::BuiltinType name) { + auto symbol = symbols.Register(tint::ToString(name)); + if (auto* existing = types.Find(symbol, /* is_wgsl_internal */ true)) { + return existing; + } + return types.WgslInternalStruct(symbol, { + {symbols.Register("old_value"), ty}, + {symbols.Register("exchanged"), types.bool_()}, + }); + }; + return Switch( + ty, // + [&](const I32*) { return build(core::BuiltinType::kAtomicCompareExchangeResultI32); }, + [&](const U32*) { return build(core::BuiltinType::kAtomicCompareExchangeResultU32); }, + TINT_ICE_ON_NO_MATCH); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/builtin_structs.h b/3rdparty/dawn/src/tint/lang/core/type/builtin_structs.h new file mode 100644 index 000000000..9f8ec5ec5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/builtin_structs.h @@ -0,0 +1,63 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_BUILTIN_STRUCTS_H_ +#define SRC_TINT_LANG_CORE_TYPE_BUILTIN_STRUCTS_H_ + +// Forward declarations +namespace tint { +class SymbolTable; +} // namespace tint +namespace tint::core::type { +class Manager; +class Struct; +class Type; +} // namespace tint::core::type + +namespace tint::core::type { + +/// @param types the type manager +/// @param symbols the symbol table +/// @param ty the type of the `fract` and `whole` struct members. +/// @returns the builtin struct type for a modf() builtin call. +Struct* CreateModfResult(Manager& types, SymbolTable& symbols, const Type* ty); + +/// @param types the type manager +/// @param symbols the symbol table +/// @param fract the type of the `fract` struct member. +/// @returns the builtin struct type for a frexp() builtin call. +Struct* CreateFrexpResult(Manager& types, SymbolTable& symbols, const Type* fract); + +/// @param types the type manager +/// @param symbols the symbol table +/// @param ty the type of the `old_value` struct member. +/// @returns the builtin struct type for a atomic_compare_exchange() builtin call. +Struct* CreateAtomicCompareExchangeResult(Manager& types, SymbolTable& symbols, const Type* ty); + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_BUILTIN_STRUCTS_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/clone_context.h b/3rdparty/dawn/src/tint/lang/core/type/clone_context.h new file mode 100644 index 000000000..7270cd514 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/clone_context.h @@ -0,0 +1,60 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_CLONE_CONTEXT_H_ +#define SRC_TINT_LANG_CORE_TYPE_CLONE_CONTEXT_H_ + +// Forward Declarations +namespace tint { +class SymbolTable; +} // namespace tint +namespace tint::core::type { +class Manager; +} // namespace tint::core::type + +namespace tint::core::type { + +/// Context information for cloning of types +struct CloneContext { + /// Source information + struct { + /// The source symbol table + const SymbolTable* st; + } src; + + /// Destination information + struct { + /// The destination symbol table + SymbolTable* st; + /// The destination type manger + Manager* mgr; + } dst; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_CLONE_CONTEXT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.cc b/3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.cc new file mode 100644 index 000000000..faa5250ae --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.cc @@ -0,0 +1,68 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/depth_multisampled_texture.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::DepthMultisampledTexture); + +namespace tint::core::type { + +DepthMultisampledTexture::DepthMultisampledTexture(TextureDimension dim) + : Base(Hash(TypeCode::Of().bits, dim), dim) { + TINT_ASSERT(IsValidDimension(dim)); +} + +DepthMultisampledTexture::~DepthMultisampledTexture() = default; + +bool DepthMultisampledTexture::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->Dim() == Dim(); + } + return false; +} + +std::string DepthMultisampledTexture::FriendlyName() const { + StringStream out; + out << "texture_depth_multisampled_" << Dim(); + return out.str(); +} + +DepthMultisampledTexture* DepthMultisampledTexture::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(Dim()); +} + +bool DepthMultisampledTexture::IsValidDimension(TextureDimension dim) { + return dim == TextureDimension::k2d; +} +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.h b/3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.h new file mode 100644 index 000000000..0771f8f51 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/depth_multisampled_texture.h @@ -0,0 +1,66 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_DEPTH_MULTISAMPLED_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_DEPTH_MULTISAMPLED_TEXTURE_H_ + +#include + +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" + +namespace tint::core::type { + +/// A multisampled depth texture type. +class DepthMultisampledTexture final : public Castable { + public: + /// Constructor + /// @param dim the dimensionality of the texture + explicit DepthMultisampledTexture(TextureDimension dim); + + /// Destructor + ~DepthMultisampledTexture() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + DepthMultisampledTexture* Clone(CloneContext& ctx) const override; + + /// @returns true if @p dim is a valid TextureDimension for a DepthMultisampledTexture + static bool IsValidDimension(TextureDimension dim); +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_DEPTH_MULTISAMPLED_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/depth_texture.cc b/3rdparty/dawn/src/tint/lang/core/type/depth_texture.cc new file mode 100644 index 000000000..0df9bc88a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/depth_texture.cc @@ -0,0 +1,70 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/depth_texture.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::DepthTexture); + +namespace tint::core::type { + +DepthTexture::DepthTexture(TextureDimension dim) + : Base(Hash(TypeCode::Of().bits, dim), dim) { + TINT_ASSERT(IsValidDimension(dim)); +} + +DepthTexture::~DepthTexture() = default; + +bool DepthTexture::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->Dim() == Dim(); + } + return false; +} + +std::string DepthTexture::FriendlyName() const { + StringStream out; + out << "texture_depth_" << Dim(); + return out.str(); +} + +DepthTexture* DepthTexture::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(Dim()); +} + +bool DepthTexture::IsValidDimension(TextureDimension dim) { + return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray || + dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/depth_texture.h b/3rdparty/dawn/src/tint/lang/core/type/depth_texture.h new file mode 100644 index 000000000..62171a519 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/depth_texture.h @@ -0,0 +1,66 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_DEPTH_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_DEPTH_TEXTURE_H_ + +#include + +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" + +namespace tint::core::type { + +/// A depth texture type. +class DepthTexture final : public Castable { + public: + /// Constructor + /// @param dim the dimensionality of the texture + explicit DepthTexture(TextureDimension dim); + + /// Destructor + ~DepthTexture() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + DepthTexture* Clone(CloneContext& ctx) const override; + + /// @returns true iff @p dim is a valid TextureDimension for a DepthTexture + static bool IsValidDimension(TextureDimension dim); +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_DEPTH_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/external_texture.cc b/3rdparty/dawn/src/tint/lang/core/type/external_texture.cc new file mode 100644 index 000000000..54ede320a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/external_texture.cc @@ -0,0 +1,55 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/external_texture.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::ExternalTexture); + +namespace tint::core::type { + +ExternalTexture::ExternalTexture() + : Base(static_cast(tint::TypeCode::Of().bits), TextureDimension::k2d) { +} + +ExternalTexture::~ExternalTexture() = default; + +bool ExternalTexture::Equals(const UniqueNode& other) const { + return other.Is(); +} + +std::string ExternalTexture::FriendlyName() const { + return "texture_external"; +} + +ExternalTexture* ExternalTexture::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/external_texture.h b/3rdparty/dawn/src/tint/lang/core/type/external_texture.h new file mode 100644 index 000000000..8a0a23cb9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/external_texture.h @@ -0,0 +1,61 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_EXTERNAL_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_EXTERNAL_TEXTURE_H_ + +#include + +#include "src/tint/lang/core/type/texture.h" + +namespace tint::core::type { + +/// An external texture type +class ExternalTexture final : public Castable { + public: + /// Constructor + ExternalTexture(); + + /// Destructor + ~ExternalTexture() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + ExternalTexture* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_EXTERNAL_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/f16.cc b/3rdparty/dawn/src/tint/lang/core/type/f16.cc new file mode 100644 index 000000000..0ee753dd8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/f16.cc @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/f16.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::F16); + +namespace tint::core::type { + +F16::F16() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }) {} + +F16::~F16() = default; + +std::string F16::FriendlyName() const { + return "f16"; +} + +uint32_t F16::Size() const { + return 2; +} + +uint32_t F16::Align() const { + return 2; +} + +F16* F16::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/f16.h b/3rdparty/dawn/src/tint/lang/core/type/f16.h new file mode 100644 index 000000000..a6650b5b0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/f16.h @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_F16_H_ +#define SRC_TINT_LANG_CORE_TYPE_F16_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// A float 16 type +class F16 final : public Castable { + public: + /// Constructor + F16(); + + /// Destructor + ~F16() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + F16* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_F16_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/f32.cc b/3rdparty/dawn/src/tint/lang/core/type/f32.cc new file mode 100644 index 000000000..a4cba5828 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/f32.cc @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/f32.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::F32); + +namespace tint::core::type { + +F32::F32() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }) {} + +F32::~F32() = default; + +std::string F32::FriendlyName() const { + return "f32"; +} + +uint32_t F32::Size() const { + return 4; +} + +uint32_t F32::Align() const { + return 4; +} + +F32* F32::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/f32.h b/3rdparty/dawn/src/tint/lang/core/type/f32.h new file mode 100644 index 000000000..8aaaf045b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/f32.h @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_F32_H_ +#define SRC_TINT_LANG_CORE_TYPE_F32_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// A float 32 type +class F32 final : public Castable { + public: + /// Constructor + F32(); + + /// Destructor + ~F32() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + F32* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_F32_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/function.cc b/3rdparty/dawn/src/tint/lang/core/type/function.cc new file mode 100644 index 000000000..6b703fe64 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/function.cc @@ -0,0 +1,53 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/function.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Function); + +namespace tint::core::type { + +Function::Function() + : Base(static_cast(tint::TypeCode::Of().bits), core::type::Flags{}) {} + +Function::~Function() = default; + +std::string Function::FriendlyName() const { + return ""; +} + +bool Function::Equals(const UniqueNode& other) const { + return other.Is(); +} + +Function* Function::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/function.h b/3rdparty/dawn/src/tint/lang/core/type/function.h new file mode 100644 index 000000000..75972d5f9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/function.h @@ -0,0 +1,61 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_FUNCTION_H_ +#define SRC_TINT_LANG_CORE_TYPE_FUNCTION_H_ + +#include + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A synthetic type for functions in the IR +class Function final : public Castable { + public: + /// Constructor + Function(); + + /// Destructor + ~Function() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Function* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_FUNCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/i32.cc b/3rdparty/dawn/src/tint/lang/core/type/i32.cc new file mode 100644 index 000000000..4942b48ac --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/i32.cc @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/i32.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::I32); + +namespace tint::core::type { + +I32::I32() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }) {} + +I32::~I32() = default; + +std::string I32::FriendlyName() const { + return "i32"; +} + +uint32_t I32::Size() const { + return 4; +} + +uint32_t I32::Align() const { + return 4; +} + +I32* I32::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/i32.h b/3rdparty/dawn/src/tint/lang/core/type/i32.h new file mode 100644 index 000000000..2093918d4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/i32.h @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_I32_H_ +#define SRC_TINT_LANG_CORE_TYPE_I32_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// A signed int 32 type. +class I32 final : public Castable { + public: + /// Constructor + I32(); + + /// Destructor + ~I32() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + I32* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_I32_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/i8.cc b/3rdparty/dawn/src/tint/lang/core/type/i8.cc new file mode 100644 index 000000000..8ad133e92 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/i8.cc @@ -0,0 +1,50 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/i8.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::I8); + +namespace tint::core::type { + +I8::I8() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }) {} + +I8::~I8() = default; + +I8* I8::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/i8.h b/3rdparty/dawn/src/tint/lang/core/type/i8.h new file mode 100644 index 000000000..ac1184290 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/i8.h @@ -0,0 +1,62 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_I8_H_ +#define SRC_TINT_LANG_CORE_TYPE_I8_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// A signed 8-bit integer type. +class I8 final : public Castable { + public: + /// Constructor + I8(); + + /// Destructor + ~I8() override; + + /// @returns the name for this type that closely resembles how it would be declared in WGSL. + std::string FriendlyName() const override { return "i8"; } + + /// @returns the size in bytes of the type. + uint32_t Size() const override { return 1; } + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override { return 1; } + + /// @param ctx the clone context + /// @returns a clone of this type + I8* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_I8_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/input_attachment.cc b/3rdparty/dawn/src/tint/lang/core/type/input_attachment.cc new file mode 100644 index 000000000..65e05e8ad --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/input_attachment.cc @@ -0,0 +1,66 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/input_attachment.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::InputAttachment); + +namespace tint::core::type { + +InputAttachment::InputAttachment(const type::Type* type) + : Base(Hash(TypeCode::Of().bits, type), TextureDimension::k2d), type_(type) { + TINT_ASSERT(type_); +} + +InputAttachment::~InputAttachment() = default; + +bool InputAttachment::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->type_ == type_; + } + return false; +} + +std::string InputAttachment::FriendlyName() const { + StringStream out; + out << "input_attachment" << "<" << type_->FriendlyName() << ">"; + return out.str(); +} + +InputAttachment* InputAttachment::Clone(CloneContext& ctx) const { + auto* ty = type_->Clone(ctx); + return ctx.dst.mgr->Get(ty); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/input_attachment.h b/3rdparty/dawn/src/tint/lang/core/type/input_attachment.h new file mode 100644 index 000000000..d3648763c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/input_attachment.h @@ -0,0 +1,67 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_INPUT_ATTACHMENT_H_ +#define SRC_TINT_LANG_CORE_TYPE_INPUT_ATTACHMENT_H_ + +#include + +#include "src/tint/lang/core/type/texture.h" + +namespace tint::core::type { + +/// An input attachment type. +class InputAttachment final : public Castable { + public: + /// Constructor + /// @param type the data type of the input attachment + explicit InputAttachment(const type::Type* type); + /// Destructor + ~InputAttachment() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the subtype of the input attachment + const type::Type* Type() const { return type_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + InputAttachment* Clone(CloneContext& ctx) const override; + + private: + const type::Type* type_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_INPUT_ATTACHMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/invalid.cc b/3rdparty/dawn/src/tint/lang/core/type/invalid.cc new file mode 100644 index 000000000..cc929a828 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/invalid.cc @@ -0,0 +1,61 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/invalid.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Invalid); + +namespace tint::core::type { + +Invalid::Invalid() + : Base(static_cast(tint::TypeCode::Of().bits), core::type::Flags{}) {} + +Invalid::~Invalid() = default; + +std::string Invalid::FriendlyName() const { + return ""; +} + +bool Invalid::Equals(const UniqueNode& other) const { + return other.Is(); +} + +uint32_t Invalid::Size() const { + return 0; +} + +uint32_t Invalid::Align() const { + return 0; +} + +Invalid* Invalid::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/invalid.h b/3rdparty/dawn/src/tint/lang/core/type/invalid.h new file mode 100644 index 000000000..4405bf7fa --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/invalid.h @@ -0,0 +1,67 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_INVALID_H_ +#define SRC_TINT_LANG_CORE_TYPE_INVALID_H_ + +#include + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// An invalid type. +class Invalid final : public Castable { + public: + /// Constructor + Invalid(); + + /// Destructor + ~Invalid() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the size in bytes of the type. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Invalid* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_INVALID_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/manager.cc b/3rdparty/dawn/src/tint/lang/core/type/manager.cc new file mode 100644 index 000000000..0ed9c72e2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/manager.cc @@ -0,0 +1,421 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/manager.h" + +#include + +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/function.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/invalid.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u64.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/utils/macros/compiler.h" + +namespace tint::core::type { + +Manager::Manager() = default; + +Manager::Manager(Manager&&) = default; + +Manager& Manager::operator=(Manager&& rhs) = default; + +Manager::~Manager() = default; + +const Type* Manager::SubtypeFor(core::TexelFormat format) { + switch (format) { + case core::TexelFormat::kR8Uint: + case core::TexelFormat::kRg8Uint: + case core::TexelFormat::kRgba8Uint: + case core::TexelFormat::kR16Uint: + case core::TexelFormat::kRg16Uint: + case core::TexelFormat::kRgba16Uint: + case core::TexelFormat::kR32Uint: + case core::TexelFormat::kRg32Uint: + case core::TexelFormat::kRgba32Uint: + case core::TexelFormat::kRgb10A2Uint: { + return u32(); + } + + case core::TexelFormat::kR8Sint: + case core::TexelFormat::kRg8Sint: + case core::TexelFormat::kRgba8Sint: + case core::TexelFormat::kR16Sint: + case core::TexelFormat::kRg16Sint: + case core::TexelFormat::kRgba16Sint: + case core::TexelFormat::kR32Sint: + case core::TexelFormat::kRg32Sint: + case core::TexelFormat::kRgba32Sint: { + return i32(); + } + + case core::TexelFormat::kR8Unorm: + case core::TexelFormat::kR8Snorm: + case core::TexelFormat::kRg8Unorm: + case core::TexelFormat::kRg8Snorm: + case core::TexelFormat::kBgra8Unorm: + case core::TexelFormat::kRgba8Unorm: + case core::TexelFormat::kRgba8Snorm: + case core::TexelFormat::kR16Unorm: + case core::TexelFormat::kR16Snorm: + case core::TexelFormat::kRg16Unorm: + case core::TexelFormat::kRg16Snorm: + case core::TexelFormat::kRgba16Unorm: + case core::TexelFormat::kRgba16Snorm: + case core::TexelFormat::kR16Float: + case core::TexelFormat::kRg16Float: + case core::TexelFormat::kRgba16Float: + case core::TexelFormat::kR32Float: + case core::TexelFormat::kRg32Float: + case core::TexelFormat::kRgba32Float: + case core::TexelFormat::kRgb10A2Unorm: + case core::TexelFormat::kRg11B10Ufloat: { + return f32(); + } + + case core::TexelFormat::kUndefined: + break; + } + + return nullptr; +} + +const core::type::Invalid* Manager::invalid() { + return Get(); +} + +const core::type::Function* Manager::function() { + return Get(); +} + +const core::type::Void* Manager::void_() { + return Get(); +} + +const core::type::Bool* Manager::bool_() { + return Get(); +} + +const core::type::I8* Manager::i8() { + return Get(); +} + +const core::type::I32* Manager::i32() { + return Get(); +} + +const core::type::U8* Manager::u8() { + return Get(); +} + +const core::type::U32* Manager::u32() { + return Get(); +} + +const core::type::U64* Manager::u64() { + return Get(); +} + +const core::type::F32* Manager::f32() { + return Get(); +} + +const core::type::F16* Manager::f16() { + return Get(); +} + +const core::type::AbstractFloat* Manager::AFloat() { + return Get(); +} + +const core::type::AbstractInt* Manager::AInt() { + return Get(); +} + +const core::type::Atomic* Manager::atomic(const core::type::Type* inner) { + return Get(inner); +} + +const core::type::Vector* Manager::packed_vec(const core::type::Type* inner, uint32_t size) { + return Get(inner, size, true); +} + +const core::type::Type* Manager::MatchWidth(const core::type::Type* el_ty, + const core::type::Type* match) { + if (auto* m = match->As()) { + return vec(el_ty, m->Width()); + } + return el_ty; +} + +const core::type::Type* Manager::MatchWidth(const core::type::Type* el_ty, size_t size) { + if (size > 1) { + return vec(el_ty, static_cast(size)); + } + return el_ty; +} + +const core::type::Vector* Manager::vec(const core::type::Type* inner, uint32_t size) { + return Get(inner, size); +} + +const core::type::Vector* Manager::vec2(const core::type::Type* inner) { + return vec(inner, 2); +} + +const core::type::Vector* Manager::vec3(const core::type::Type* inner) { + return vec(inner, 3); +} + +const core::type::Vector* Manager::vec4(const core::type::Type* inner) { + return vec(inner, 4); +} + +const core::type::Vector* Manager::vec2f() { + return vec(f32(), 2); +} +const core::type::Vector* Manager::vec3f() { + return vec(f32(), 3); +} +const core::type::Vector* Manager::vec4f() { + return vec(f32(), 4); +} + +const core::type::Vector* Manager::vec2h() { + return vec(f16(), 2); +} +const core::type::Vector* Manager::vec3h() { + return vec(f16(), 3); +} +const core::type::Vector* Manager::vec4h() { + return vec(f16(), 4); +} + +const core::type::Vector* Manager::vec2i() { + return vec(i32(), 2); +} +const core::type::Vector* Manager::vec3i() { + return vec(i32(), 3); +} +const core::type::Vector* Manager::vec4i() { + return vec(i32(), 4); +} + +const core::type::Vector* Manager::vec2u() { + return vec(u32(), 2); +} +const core::type::Vector* Manager::vec3u() { + return vec(u32(), 3); +} +const core::type::Vector* Manager::vec4u() { + return vec(u32(), 4); +} + +const core::type::SampledTexture* Manager::sampled_texture(TextureDimension dim, + const core::type::Type* type) { + return Get(dim, type); +} + +const core::type::MultisampledTexture* Manager::multisampled_texture(TextureDimension dim, + const core::type::Type* type) { + return Get(dim, type); +} + +const core::type::StorageTexture* Manager::storage_texture(TextureDimension dim, + core::TexelFormat format, + core::Access access) { + const auto* subtype = SubtypeFor(format); + return Get(dim, format, access, subtype); +} + +const core::type::TexelBuffer* Manager::texel_buffer(core::TexelFormat format, + core::Access access) { + const auto* subtype = SubtypeFor(format); + return Get(format, access, subtype); +} + +const core::type::DepthTexture* Manager::depth_texture(TextureDimension dim) { + return Get(dim); +} + +const core::type::DepthMultisampledTexture* Manager::depth_multisampled_texture( + TextureDimension dim) { + return Get(dim); +} + +const core::type::Matrix* Manager::mat(const core::type::Type* inner, + uint32_t cols, + uint32_t rows) { + return Get(vec(inner, rows), cols); +} + +const core::type::Matrix* Manager::mat(const core::type::Vector* column_type, uint32_t cols) { + return Get(column_type, cols); +} + +const core::type::Matrix* Manager::mat2x2(const core::type::Type* inner) { + return mat(inner, 2, 2); +} + +const core::type::Matrix* Manager::mat2x3(const core::type::Type* inner) { + return mat(inner, 2, 3); +} + +const core::type::Matrix* Manager::mat2x4(const core::type::Type* inner) { + return mat(inner, 2, 4); +} + +const core::type::Matrix* Manager::mat3x2(const core::type::Type* inner) { + return mat(inner, 3, 2); +} + +const core::type::Matrix* Manager::mat3x3(const core::type::Type* inner) { + return mat(inner, 3, 3); +} + +const core::type::Matrix* Manager::mat3x4(const core::type::Type* inner) { + return mat(inner, 3, 4); +} + +const core::type::Matrix* Manager::mat4x2(const core::type::Type* inner) { + return mat(inner, 4, 2); +} + +const core::type::Matrix* Manager::mat4x3(const core::type::Type* inner) { + return mat(inner, 4, 3); +} + +const core::type::Matrix* Manager::mat4x4(const core::type::Type* inner) { + return mat(inner, 4, 4); +} + +const core::type::SubgroupMatrix* Manager::subgroup_matrix(SubgroupMatrixKind kind, + const core::type::Type* inner, + uint32_t cols, + uint32_t rows) { + return Get(kind, inner, cols, rows); +} + +const core::type::Buffer* Manager::buffer(uint32_t n) { + return Get(Get(n)); +} + +const core::type::Buffer* Manager::unsized_buffer() { + return Get(Get()); +} + +const core::type::Array* Manager::array(const core::type::Type* elem_ty, uint32_t count) { + uint32_t implicit_stride = tint::RoundUp(elem_ty->Align(), elem_ty->Size()); + + return Get(/* element type */ elem_ty, + /* element count */ Get(count), + /* array size */ count * implicit_stride); +} + +const core::type::Array* Manager::runtime_array(const core::type::Type* elem_ty) { + uint32_t implicit_stride = tint::RoundUp(elem_ty->Align(), elem_ty->Size()); + + return Get( + /* element type */ elem_ty, + /* element count */ Get(), + /* array size */ implicit_stride); +} + +const core::type::BindingArray* Manager::binding_array(const core::type::Type* elem_ty, + uint32_t count) { + return Get(elem_ty, Get(count)); +} + +const core::type::Pointer* Manager::ptr(core::AddressSpace address_space, + const core::type::Type* subtype, + core::Access access /* = core::Access::kUndefined */) { + return Get( + address_space, subtype, + access == core::Access::kUndefined ? DefaultAccessFor(address_space) : access); +} + +const core::type::Reference* Manager::ref(core::AddressSpace address_space, + const core::type::Type* subtype, + core::Access access /* = core::Access::kReadWrite */) { + return Get(address_space, subtype, access); +} + +core::type::Struct* Manager::Struct(Symbol name, VectorRef members) { + auto* existing = Find(name, /* is_wgsl_internal */ false); + TINT_ASSERT(!existing) << "attempting to construct two structs named " << name.NameView(); + + uint32_t max_align = 0u; + for (const auto& m : members) { + max_align = std::max(max_align, m->Align()); + } + + auto& mem = members.Back(); + uint32_t size = std::max(mem->Size(), mem->MinimumRequiredSize()); + return Get(name, std::move(members), + tint::RoundUp(max_align, mem->Offset() + size)); +} + +core::type::Struct* Manager::Struct(Symbol name, + bool is_wgsl_internal, + VectorRef md) { + auto* existing = Find(name, is_wgsl_internal); + TINT_ASSERT(!existing) << "attempting to construct two structs named " << name.NameView(); + + tint::Vector members; + uint32_t current_size = 0u; + uint32_t max_align = 0u; + for (const auto& m : md) { + uint32_t index = static_cast(members.Length()); + uint32_t align = std::max(m.type->Align(), 1u); + uint32_t offset = tint::RoundUp(align, current_size); + members.Push(Get(m.name, m.type, index, offset, align, + m.type->Size(), std::move(m.attributes))); + current_size = offset + m.type->Size(); + max_align = std::max(max_align, align); + } + return Get(name, std::move(members), tint::RoundUp(max_align, current_size), + is_wgsl_internal); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/manager.h b/3rdparty/dawn/src/tint/lang/core/type/manager.h new file mode 100644 index 000000000..cd6cd82c2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/manager.h @@ -0,0 +1,756 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_MANAGER_H_ +#define SRC_TINT_LANG_CORE_TYPE_MANAGER_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/atomic.h" +#include "src/tint/lang/core/type/buffer.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/string.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/subgroup_matrix.h" +#include "src/tint/lang/core/type/texel_buffer.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/unique_node.h" +#include "src/tint/utils/containers/unique_allocator.h" +#include "src/tint/utils/symbol/symbol.h" + +// Forward declarations +namespace tint::core::type { +class AbstractFloat; +class AbstractInt; +class Array; +class BindingArray; +class Bool; +class F16; +class F32; +class Function; +class I8; +class I32; +class Invalid; +class Matrix; +class Pointer; +class Reference; +class SampledTexture; +class StorageTexture; +class U8; +class U32; +class U64; +class Vector; +class Void; +} // namespace tint::core::type + +namespace tint::core::type { + +/// @param space the address space of the memory view +/// @returns the default access control for a memory view with the given address space. +static constexpr inline core::Access DefaultAccessFor(core::AddressSpace space) { + switch (space) { + case core::AddressSpace::kIn: + case core::AddressSpace::kImmediate: + case core::AddressSpace::kUniform: + case core::AddressSpace::kHandle: + return core::Access::kRead; + + case core::AddressSpace::kUndefined: + case core::AddressSpace::kOut: + case core::AddressSpace::kFunction: + case core::AddressSpace::kPixelLocal: + case core::AddressSpace::kPrivate: + case core::AddressSpace::kStorage: + case core::AddressSpace::kWorkgroup: + break; + } + + return core::Access::kReadWrite; +} + +/// The type manager holds all the pointers to the known types. +class Manager final { + public: + /// Iterator is the type returned by begin() and end() + using TypeIterator = BlockAllocator::ConstIterator; + + /// Constructor + Manager(); + + /// Move constructor + Manager(Manager&&); + + /// Move assignment operator + /// @param rhs the Manager to move + /// @return this Manager + Manager& operator=(Manager&& rhs); + + /// Destructor + ~Manager(); + + /// Wrap returns a new Manager created with the types of `inner`. + /// The Manager returned by Wrap is intended to temporarily extend the types + /// of an existing immutable Manager. + /// @warning As the copied types are owned by `inner`, `inner` must not be destructed or + /// assigned while using the returned Manager. + /// TODO(crbug.com/tint/460) - Evaluate whether there are safer alternatives to this + /// function. + /// @param inner the immutable Manager to extend + /// @return the Manager that wraps `inner` + static Manager Wrap(const Manager& inner) { + Manager out; + out.types_.Wrap(inner.types_); + out.unique_nodes_.Wrap(inner.unique_nodes_); + return out; + } + + /// Constructs or returns an existing type, unique node or node + /// @param args the arguments used to construct the type, unique node or node. + /// @tparam T a class deriving from core::type::Node, or a C-like type that's automatically + /// translated to the equivalent type node type. For example `Get()` is equivalent to + /// `Get()` + /// @return a pointer to an instance of `T` with the provided arguments. + /// If `T` derives from UniqueNode and an existing instance of `T` has been constructed, then + /// the same pointer is returned. + template + auto* Get(ARGS&&... args) { + if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (std::is_same_v) { + return Get(std::forward(args)...); + } else if constexpr (core::fluent_types::IsVector) { + return vec(std::forward(args)...); + } else if constexpr (core::fluent_types::IsMatrix) { + return mat(std::forward(args)...); + } else if constexpr (core::fluent_types::IsPointer) { + return ptr(std::forward(args)...); + } else if constexpr (core::fluent_types::IsArray) { + return array(std::forward(args)...); + } else if constexpr (core::fluent_types::IsAtomic) { + return atomic(std::forward(args)...); + } else if constexpr (tint::traits::IsTypeOrDerived) { + return types_.Get(std::forward(args)...); + } else if constexpr (tint::traits::IsTypeOrDerived) { + return unique_nodes_.Get(std::forward(args)...); + } else { + return nodes_.Create(std::forward(args)...); + } + } + + /// @param args the arguments used to create the temporary used for the search. + /// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item + /// was not found. + template >, + typename... ARGS> + auto* Find(ARGS&&... args) const { + return types_.Find(std::forward(args)...); + } + + /// @returns the subtype for a given `format` + const Type* SubtypeFor(core::TexelFormat format); + + /// @returns an invalid type + const core::type::Invalid* invalid(); + + /// @returns an function type + const core::type::Function* function(); + + /// @returns a void type + const core::type::Void* void_(); + + /// @returns a bool type + const core::type::Bool* bool_(); + + /// @returns an i8 type + const core::type::I8* i8(); + + /// @returns an i32 type + const core::type::I32* i32(); + + /// @returns a u8 type + const core::type::U8* u8(); + + /// @returns a u32 type + const core::type::U32* u32(); + + /// @returns a u64 type + const core::type::U64* u64(); + + /// @returns an f32 type + const core::type::F32* f32(); + + /// @returns an f16 type + const core::type::F16* f16(); + + /// @returns a abstract-float type + const core::type::AbstractFloat* AFloat(); + + /// @returns a abstract-int type + const core::type::AbstractInt* AInt(); + + /// @param inner the inner type + /// @returns an atomic type with the element type @p inner + const core::type::Atomic* atomic(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns the atomic type + template + const core::type::Atomic* atomic() { + return atomic(Get()); + } + + /// @param inner the inner type + /// @param size the vector size + /// @returns the vector type + const core::type::Vector* packed_vec(const core::type::Type* inner, uint32_t size); + + /// @param inner the inner type + /// @param size the vector size + /// @returns the vector type + const core::type::Vector* vec(const core::type::Type* inner, uint32_t size); + + /// @param inner the inner type + /// @returns a vec2 type with the element type @p inner + const core::type::Vector* vec2(const core::type::Type* inner); + + /// @param inner the inner type + /// @returns a vec3 type with the element type @p inner + const core::type::Vector* vec3(const core::type::Type* inner); + + /// @param inner the inner type + /// @returns a vec4 type with the element type @p inner + const core::type::Vector* vec4(const core::type::Type* inner); + + /// @returns a vec2 type with the element type f32 + const core::type::Vector* vec2f(); + + /// @returns a vec3 type with the element type f32 + const core::type::Vector* vec3f(); + + /// @returns a vec4 type with the element type f32 + const core::type::Vector* vec4f(); + + /// @returns a vec2 type with the element type f16 + const core::type::Vector* vec2h(); + + /// @returns a vec3 type with the element type f16 + const core::type::Vector* vec3h(); + + /// @returns a vec4 type with the element type f16 + const core::type::Vector* vec4h(); + + /// @returns a vec2 type with the element type i32 + const core::type::Vector* vec2i(); + + /// @returns a vec3 type with the element type i32 + const core::type::Vector* vec3i(); + + /// @returns a vec4 type with the element type i32 + const core::type::Vector* vec4i(); + + /// @returns a vec2 type with the element type u32 + const core::type::Vector* vec2u(); + + /// @returns a vec3 type with the element type u32 + const core::type::Vector* vec3u(); + + /// @returns a vec4 type with the element type u32 + const core::type::Vector* vec4u(); + + /// @param dim the dimensionality of the texture + /// @param type the data type of the sampled texture + /// @returns a sampled texture type with the provided params + const core::type::SampledTexture* sampled_texture(TextureDimension dim, + const core::type::Type* type); + + /// @param dim the dimensionality of the texture + /// @param type the data type of the sampled texture + /// @returns a multisampled texture type with the provided params + const core::type::MultisampledTexture* multisampled_texture(TextureDimension dim, + const core::type::Type* type); + + /// @param dim the dimensionality of the texture + /// @param format the texel format of the texture + /// @param access the access control type of the texture + /// @returns a storage texture type with the provided params + const core::type::StorageTexture* storage_texture(TextureDimension dim, + core::TexelFormat format, + core::Access access); + + /// @param format the texel format of the texel buffer + /// @param access the access control type of the texel buffer + /// @returns a texel buffer type with the provided params + const core::type::TexelBuffer* texel_buffer(core::TexelFormat format, core::Access access); + + /// @param dim the dimensionality of the texture + /// @returns a depth texture type with the provided params + const core::type::DepthTexture* depth_texture(TextureDimension dim); + + /// @param dim the dimensionality of the texture + /// @returns a depth multisampled texture type with the provided params + const core::type::DepthMultisampledTexture* depth_multisampled_texture(TextureDimension dim); + + /// Return a type with element type `el_ty` that has the same number of vector components as + /// `match`. If `match` is scalar just return `el_ty`. + /// @param el_ty the type to extend + /// @param match the type to match the component count of + /// @returns a type with the same number of vector components as `match` + const core::type::Type* MatchWidth(const core::type::Type* el_ty, + const core::type::Type* match); + + // Return a type with element type `el_ty` that has the `size` number of vector components. + // If `size` is 1, just return `el_ty`. + /// @param el_ty the type to extend + /// @param size the component size to match + /// @returns a type with the `size` number of components + const core::type::Type* MatchWidth(const core::type::Type* el_ty, size_t size); + + /// @tparam T the element type + /// @tparam N the vector width + /// @returns the vector type + template + const core::type::Vector* vec() { + TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE); + static_assert(N >= 2 && N <= 4); + switch (N) { + case 2: + return vec2(); + case 3: + return vec3(); + case 4: + return vec4(); + } + return nullptr; // unreachable + TINT_END_DISABLE_WARNING(UNREACHABLE_CODE); + } + + /// @tparam T the element type + /// @returns a vec2 with the element type `T` + template + const core::type::Vector* vec2() { + return vec2(Get()); + } + + /// @tparam T the element type + /// @returns a vec2 with the element type `T` + template + const core::type::Vector* vec3() { + return vec3(Get()); + } + + /// @tparam T the element type + /// @returns a vec2 with the element type `T` + template + const core::type::Vector* vec4() { + return vec4(Get()); + } + + /// @param inner the inner type + /// @param cols the number of columns + /// @param rows the number of rows + /// @returns the matrix type + const core::type::Matrix* mat(const core::type::Type* inner, uint32_t cols, uint32_t rows); + + /// @param column_type the column vector type + /// @param cols the number of columns + /// @returns the matrix type + const core::type::Matrix* mat(const core::type::Vector* column_type, uint32_t cols); + + /// @param inner the inner type + /// @returns a mat2x2 with the element @p inner + const core::type::Matrix* mat2x2(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat2x2 with the element type `T` + template + const core::type::Matrix* mat2x2() { + return mat2x2(Get()); + } + + /// @param inner the inner type + /// @returns a mat2x3 with the element @p inner + const core::type::Matrix* mat2x3(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat2x3 with the element type `T` + template + const core::type::Matrix* mat2x3() { + return mat2x3(Get()); + } + + /// @param inner the inner type + /// @returns a mat2x4 with the element @p inner + const core::type::Matrix* mat2x4(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat2x4 with the element type `T` + template + const core::type::Matrix* mat2x4() { + return mat2x4(Get()); + } + + /// @param inner the inner type + /// @returns a mat3x2 with the element @p inner + const core::type::Matrix* mat3x2(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat3x2 with the element type `T` + template + const core::type::Matrix* mat3x2() { + return mat3x2(Get()); + } + + /// @param inner the inner type + /// @returns a mat3x3 with the element @p inner + const core::type::Matrix* mat3x3(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat3x3 with the element type `T` + template + const core::type::Matrix* mat3x3() { + return mat3x3(Get()); + } + + /// @param inner the inner type + /// @returns a mat3x4 with the element @p inner + const core::type::Matrix* mat3x4(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat3x4 with the element type `T` + template + const core::type::Matrix* mat3x4() { + return mat3x4(Get()); + } + + /// @param inner the inner type + /// @returns a mat4x2 with the element @p inner + const core::type::Matrix* mat4x2(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat4x2 with the element type `T` + template + const core::type::Matrix* mat4x2() { + return mat4x2(Get()); + } + + /// @param inner the inner type + /// @returns a mat4x3 with the element @p inner + const core::type::Matrix* mat4x3(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat4x3 with the element type `T` + template + const core::type::Matrix* mat4x3() { + return mat4x3(Get()); + } + + /// @param inner the inner type + /// @returns a mat4x4 with the element @p inner + const core::type::Matrix* mat4x4(const core::type::Type* inner); + + /// @tparam T the element type + /// @returns a mat4x4 with the element type `T` + template + const core::type::Matrix* mat4x4() { + return mat4x4(Get()); + } + + /// @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 + const core::type::Matrix* mat(uint32_t columns, uint32_t rows) { + return mat(Get(), 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 + const core::type::Matrix* mat() { + return mat(Get(), C, R); + } + + /// @param kind the subgroup matrix kind + /// @param inner the inner type + /// @param cols the number of columns + /// @param rows the number of rows + /// @returns the subgroup_matrix type + const core::type::SubgroupMatrix* subgroup_matrix(SubgroupMatrixKind kind, + const core::type::Type* inner, + uint32_t cols, + uint32_t rows); + + /// @param inner the inner type + /// @param cols the number of columns + /// @param rows the number of rows + /// @returns the subgroup_matrix type + const core::type::SubgroupMatrix* subgroup_matrix_left(const core::type::Type* inner, + uint32_t cols, + uint32_t rows) { + return subgroup_matrix(SubgroupMatrixKind::kLeft, inner, cols, rows); + } + + /// @param inner the inner type + /// @param cols the number of columns + /// @param rows the number of rows + /// @returns the subgroup_matrix type + const core::type::SubgroupMatrix* subgroup_matrix_right(const core::type::Type* inner, + uint32_t cols, + uint32_t rows) { + return subgroup_matrix(SubgroupMatrixKind::kRight, inner, cols, rows); + } + + /// @param inner the inner type + /// @param cols the number of columns + /// @param rows the number of rows + /// @returns the subgroup_matrix type + const core::type::SubgroupMatrix* subgroup_matrix_result(const core::type::Type* inner, + uint32_t cols, + uint32_t rows) { + return subgroup_matrix(SubgroupMatrixKind::kResult, inner, cols, rows); + } + + /// @tparam K the kind of the matrix + /// @tparam T the element type + /// @tparam C the number of columns in the matrix + /// @tparam R the number of rows in the matrix + /// @returns a matrix with the given number of columns and rows + template + const core::type::SubgroupMatrix* subgroup_matrix() { + return subgroup_matrix(K, Get(), C, R); + } + + /// @param n the size of the buffer + /// @returns the buffer + const core::type::Buffer* buffer(uint32_t n); + + /// @returns the unsized buffer + const core::type::Buffer* unsized_buffer(); + + /// @param elem_ty the array element type + /// @param count the array element count + /// @returns the array type + const core::type::Array* array(const core::type::Type* elem_ty, uint32_t count); + + /// @param elem_ty the array element type + /// @returns the runtime array type + const core::type::Array* runtime_array(const core::type::Type* elem_ty); + + /// @returns an array type with the element type `T` and size `N`. + /// @tparam T the element type + /// @tparam N the array length. If zero, then constructs a runtime-sized array. + template + const core::type::Array* array() { + if constexpr (N == 0) { + return runtime_array(Get()); + } else { + return array(Get(), N); + } + } + + /// @param elem_ty the array element type + /// @param count the array element count + /// @returns the array type + const core::type::BindingArray* binding_array(const core::type::Type* elem_ty, uint32_t count); + + /// @param address_space the address space + /// @param subtype the pointer subtype + /// @param access the access settings + /// @returns the pointer type + const core::type::Pointer* ptr(core::AddressSpace address_space, + const core::type::Type* subtype, + core::Access access = core::Access::kUndefined); + + /// @tparam SPACE the address space + /// @tparam T the storage type + /// @tparam ACCESS the access mode + /// @returns the pointer type with the templated address space, storage type and access. + template + const core::type::Pointer* ptr() { + return ptr(SPACE, Get(), 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 + const core::type::Pointer* ptr(const core::type::Type* subtype) { + return ptr(SPACE, subtype, ACCESS); + } + + /// @param address_space the address space + /// @param subtype the reference subtype + /// @param access the access settings + /// @returns the reference type + const core::type::Reference* ref(core::AddressSpace address_space, + const core::type::Type* subtype, + core::Access access = core::Access::kReadWrite); + + /// @tparam SPACE the address space + /// @tparam T the storage type + /// @tparam ACCESS the access mode + /// @returns the reference type with the templated address space, storage type and access. + template + const core::type::Reference* ref() { + return ref(SPACE, Get(), ACCESS); + } + + /// @param subtype the reference subtype + /// @tparam SPACE the address space + /// @tparam ACCESS the access mode + /// @returns the reference type with the templated address space, storage type and access. + template + const core::type::Reference* ref(const core::type::Type* subtype) { + return ref(SPACE, subtype, ACCESS); + } + + /// @returns the sampler type + const core::type::Sampler* sampler() { + return Get(core::type::SamplerKind::kSampler); + } + + /// @returns the comparison sampler type + const core::type::Sampler* comparison_sampler() { + return Get(core::type::SamplerKind::kComparisonSampler); + } + + /// @returns an input attachment type + const core::type::InputAttachment* input_attachment(const core::type::Type* inner) { + return Get(inner); + } + + /// @returns a string type + const core::type::String* String() { return Get(); } + + /// A structure member descriptor. + struct StructMemberDesc { + /// The name of the struct member. + Symbol name; + /// The type of the struct member. + const core::type::Type* type = nullptr; + /// The optional struct member attributes. + core::IOAttributes attributes = {}; + }; + + /// Create a new structure declaration. + /// @param name the name of the structure + /// @param members the list of structure members + /// @note a structure must not already exist with the same name + /// @returns the structure type + core::type::Struct* Struct(Symbol name, VectorRef members); + + /// Create a new structure declaration. + /// @param name the name of the structure + /// @param members the list of structure member descriptors + /// @note a structure must not already exist with the same name + /// @returns the structure type + core::type::Struct* Struct(Symbol name, VectorRef members) { + return Struct(name, /* is_wgsl_internal */ false, + tint::Vector(members)); + } + + /// Create a new structure declaration. + /// @param name the name of the structure + /// @param members the list of structure member descriptors + /// @note a structure must not already exist with the same name + /// @returns the structure type + core::type::Struct* Struct(Symbol name, std::initializer_list members) { + return Struct(name, tint::Vector(members)); + } + + /// Create a new WGSL internal structure declaration. + /// @param name the name of the structure + /// @param members the list of structure member descriptors + /// @note an internal structure must not already exist with the same name + /// @returns the structure type + core::type::Struct* WgslInternalStruct(Symbol name, + std::initializer_list members) { + return Struct(name, /* is_wgsl_internal */ true, + tint::Vector(members)); + } + + /// @returns the external texture type + core::type::ExternalTexture* external_texture() { return Get(); } + + /// @returns an iterator to the beginning of the types + TypeIterator begin() const { return types_.begin(); } + /// @returns an iterator to the end of the types + TypeIterator end() const { return types_.end(); } + + private: + /// Unique types owned by the manager + UniqueAllocator types_; + /// Unique nodes (excluding types) owned by the manager + UniqueAllocator unique_nodes_; + /// Non-unique nodes owned by the manager + BlockAllocator nodes_; + + /// Create a new structure declaration. + /// @param name the name of the structure + /// @param is_wgsl_internal `true` if the structure is internally defined in WGSL + /// @param members the list of structure member descriptors + /// @note a structure must not already exist with the same name + /// @returns the structure type + core::type::Struct* Struct(Symbol name, + bool is_wgsl_internal, + VectorRef members); +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_MANAGER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/matrix.cc b/3rdparty/dawn/src/tint/lang/core/type/matrix.cc new file mode 100644 index 000000000..b53395f33 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/matrix.cc @@ -0,0 +1,100 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/matrix.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Matrix); + +namespace tint::core::type { + +Matrix::Matrix(const Vector* column_type, uint32_t columns) + : Base(Hash(tint::TypeCode::Of().bits, columns, column_type), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }), + subtype_(column_type->Type()), + column_type_(column_type), + rows_(column_type->Width()), + columns_(columns) { + TINT_ASSERT(rows_ > 1); + TINT_ASSERT(rows_ < 5); + TINT_ASSERT(columns_ > 1); + TINT_ASSERT(columns_ < 5); +} + +Matrix::~Matrix() = default; + +bool Matrix::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return v->rows_ == rows_ && v->columns_ == columns_ && v->column_type_ == column_type_; + } + return false; +} + +std::string Matrix::FriendlyName() const { + StringStream out; + out << "mat" << columns_ << "x" << rows_ << "<" << subtype_->FriendlyName() << ">"; + return out.str(); +} + +uint32_t Matrix::Size() const { + return column_type_->Align() * Columns(); +} + +uint32_t Matrix::Align() const { + return column_type_->Align(); +} + +uint32_t Matrix::ColumnStride() const { + return column_type_->Align(); +} + +TypeAndCount Matrix::Elements(const type::Type* /* type_if_invalid = nullptr */, + uint32_t /* count_if_invalid = 0 */) const { + return {column_type_, columns_}; +} + +const Vector* Matrix::Element(uint32_t index) const { + return index < columns_ ? column_type_ : nullptr; +} + +Matrix* Matrix::Clone(CloneContext& ctx) const { + auto* col_ty = column_type_->Clone(ctx); + return ctx.dst.mgr->Get(col_ty, columns_); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/matrix.h b/3rdparty/dawn/src/tint/lang/core/type/matrix.h new file mode 100644 index 000000000..329490b18 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/matrix.h @@ -0,0 +1,101 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_MATRIX_H_ +#define SRC_TINT_LANG_CORE_TYPE_MATRIX_H_ + +#include + +#include "src/tint/lang/core/type/vector.h" + +// Forward declarations +namespace tint::core::type { +class Vector; +} // namespace tint::core::type + +namespace tint::core::type { + +/// A matrix type +class Matrix final : public Castable { + public: + /// Constructor + /// @param column_type the type of a column of the matrix + /// @param columns the number of columns in the matrix + Matrix(const Vector* column_type, uint32_t columns); + + /// Destructor + ~Matrix() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the type of the matrix + const type::Type* Type() const { return subtype_; } + /// @returns the number of rows in the matrix + uint32_t Rows() const { return rows_; } + /// @returns the number of columns in the matrix + uint32_t Columns() const { return columns_; } + + /// @returns the column-vector type of the matrix + const Vector* ColumnType() const { return column_type_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. This may include tail padding. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. This may include tail + /// padding. + uint32_t Align() const override; + + /// @returns the number of bytes between columns of the matrix + uint32_t ColumnStride() const; + + /// @copydoc Type::Elements + TypeAndCount Elements(const type::Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc Type::Element + const Vector* Element(uint32_t index) const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Matrix* Clone(CloneContext& ctx) const override; + + private: + const type::Type* const subtype_; + const Vector* const column_type_; + const uint32_t rows_; + const uint32_t columns_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_MATRIX_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/memory_view.cc b/3rdparty/dawn/src/tint/lang/core/type/memory_view.cc new file mode 100644 index 000000000..6ea0d418f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/memory_view.cc @@ -0,0 +1,50 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/memory_view.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/diagnostic/diagnostic.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::MemoryView); + +namespace tint::core::type { + +MemoryView::MemoryView(size_t hash, + core::AddressSpace address_space, + const Type* store_type, + core::Access access) + : Base(hash, core::type::Flags{}), + store_type_(store_type), + address_space_(address_space), + access_(access) { + TINT_ASSERT(access != core::Access::kUndefined); +} + +MemoryView::~MemoryView() = default; + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/memory_view.h b/3rdparty/dawn/src/tint/lang/core/type/memory_view.h new file mode 100644 index 000000000..a82c9d1cc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/memory_view.h @@ -0,0 +1,71 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_MEMORY_VIEW_H_ +#define SRC_TINT_LANG_CORE_TYPE_MEMORY_VIEW_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// Base class for memory view types: pointers and references +class MemoryView : public Castable { + public: + /// Constructor + /// @param hash the unique hash of the node + /// @param address_space the address space of the memory view + /// @param store_type the store type + /// @param access the resolved access control of the reference + MemoryView(size_t hash, + core::AddressSpace address_space, + const Type* store_type, + core::Access access); + + /// Destructor + ~MemoryView() override; + + /// @returns the store type of the memory view + const Type* StoreType() const { return store_type_; } + + /// @returns the address space of the memory view + core::AddressSpace AddressSpace() const { return address_space_; } + + /// @returns the access control of the memory view + core::Access Access() const { return access_; } + + private: + Type const* const store_type_; + core::AddressSpace const address_space_; + core::Access const access_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_MEMORY_VIEW_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.cc b/3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.cc new file mode 100644 index 000000000..50e41bc42 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.cc @@ -0,0 +1,66 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/multisampled_texture.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::MultisampledTexture); + +namespace tint::core::type { + +MultisampledTexture::MultisampledTexture(TextureDimension dim, const type::Type* type) + : Base(Hash(tint::TypeCode::Of().bits, dim, type), dim), type_(type) { + TINT_ASSERT(type_); +} + +MultisampledTexture::~MultisampledTexture() = default; + +bool MultisampledTexture::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->Dim() == Dim() && o->type_ == type_; + } + return false; +} + +std::string MultisampledTexture::FriendlyName() const { + StringStream out; + out << "texture_multisampled_" << Dim() << "<" << type_->FriendlyName() << ">"; + return out.str(); +} + +MultisampledTexture* MultisampledTexture::Clone(CloneContext& ctx) const { + auto* ty = type_->Clone(ctx); + return ctx.dst.mgr->Get(Dim(), ty); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.h b/3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.h new file mode 100644 index 000000000..190bdaf03 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/multisampled_texture.h @@ -0,0 +1,70 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_MULTISAMPLED_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_MULTISAMPLED_TEXTURE_H_ + +#include + +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" + +namespace tint::core::type { + +/// A multisampled texture type. +class MultisampledTexture final : public Castable { + public: + /// Constructor + /// @param dim the dimensionality of the texture + /// @param type the data type of the multisampled texture + MultisampledTexture(TextureDimension dim, const type::Type* type); + + /// Destructor + ~MultisampledTexture() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the subtype of the sampled texture + const type::Type* Type() const { return type_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + MultisampledTexture* Clone(CloneContext& ctx) const override; + + private: + const type::Type* const type_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_MULTISAMPLED_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/node.cc b/3rdparty/dawn/src/tint/lang/core/type/node.cc new file mode 100644 index 000000000..4d253e798 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/node.cc @@ -0,0 +1,40 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/node.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Node); + +namespace tint::core::type { + +Node::Node() = default; + +Node::Node(const Node&) = default; + +Node::~Node() = default; + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/node.h b/3rdparty/dawn/src/tint/lang/core/type/node.h new file mode 100644 index 000000000..a99bd9fb4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/node.h @@ -0,0 +1,50 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_NODE_H_ +#define SRC_TINT_LANG_CORE_TYPE_NODE_H_ + +#include "src/tint/utils/rtti/castable.h" + +namespace tint::core::type { + +/// Node is the base class for all type nodes +class Node : public Castable { + public: + /// Constructor + Node(); + + /// Copy constructor + Node(const Node&); + + /// Destructor + ~Node() override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_NODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.cc b/3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.cc new file mode 100644 index 000000000..11b279363 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.cc @@ -0,0 +1,38 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/numeric_scalar.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::NumericScalar); + +namespace tint::core::type { + +NumericScalar::NumericScalar(size_t hash, core::type::Flags flags) : Base(hash, flags) {} + +NumericScalar::~NumericScalar() = default; + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.h b/3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.h new file mode 100644 index 000000000..cb751ab9f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/numeric_scalar.h @@ -0,0 +1,51 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_NUMERIC_SCALAR_H_ +#define SRC_TINT_LANG_CORE_TYPE_NUMERIC_SCALAR_H_ + +#include "src/tint/lang/core/type/scalar.h" + +namespace tint::core::type { + +/// Base class for all numeric-scalar types +/// @see https://www.w3.org/TR/WGSL/#scalar-types +class NumericScalar : public Castable { + public: + /// Destructor + ~NumericScalar() override; + + protected: + /// Constructor + /// @param hash the immutable hash for the node + /// @param flags the flags of this type + NumericScalar(size_t hash, core::type::Flags flags); +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_NUMERIC_SCALAR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/pointer.cc b/3rdparty/dawn/src/tint/lang/core/type/pointer.cc new file mode 100644 index 000000000..ff1e3d613 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/pointer.cc @@ -0,0 +1,73 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/pointer.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Pointer); + +namespace tint::core::type { + +Pointer::Pointer(core::AddressSpace address_space, const Type* store_type, core::Access access) + : Base(Hash(tint::TypeCode::Of().bits), address_space, store_type, access) {} + +bool Pointer::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->AddressSpace() == AddressSpace() && o->StoreType() == StoreType() && + o->Access() == Access(); + } + return false; +} + +std::string Pointer::FriendlyName() const { + StringStream out; + out << "ptr<"; + if (AddressSpace() != core::AddressSpace::kUndefined) { + out << AddressSpace() << ", "; + } + out << StoreType()->FriendlyName() << ", " << Access(); + out << ">"; + return out.str(); +} + +Pointer::~Pointer() = default; + +Pointer* Pointer::Clone(CloneContext& ctx) const { + auto* ty = StoreType()->Clone(ctx); + return ctx.dst.mgr->Get(AddressSpace(), ty, Access()); +} + +uint32_t Pointer::Align() const { + return 1; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/pointer.h b/3rdparty/dawn/src/tint/lang/core/type/pointer.h new file mode 100644 index 000000000..11e6335e6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/pointer.h @@ -0,0 +1,66 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_POINTER_H_ +#define SRC_TINT_LANG_CORE_TYPE_POINTER_H_ + +#include + +#include "src/tint/lang/core/type/memory_view.h" +namespace tint::core::type { + +/// A pointer type. +class Pointer final : public Castable { + public: + /// Constructor + /// @param address_space the address space of the pointer + /// @param store_type the pointee type + /// @param access the resolved access control of the reference + Pointer(core::AddressSpace address_space, const Type* store_type, core::Access access); + + /// Destructor + ~Pointer() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Pointer* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_POINTER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/reference.cc b/3rdparty/dawn/src/tint/lang/core/type/reference.cc new file mode 100644 index 000000000..1bb741088 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/reference.cc @@ -0,0 +1,68 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/reference.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Reference); + +namespace tint::core::type { + +Reference::Reference(core::AddressSpace address_space, const Type* store_type, core::Access access) + : Base(Hash(tint::TypeCode::Of().bits), address_space, store_type, access) {} + +bool Reference::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->AddressSpace() == AddressSpace() && o->StoreType() == StoreType() && + o->Access() == Access(); + } + return false; +} + +std::string Reference::FriendlyName() const { + StringStream out; + out << "ref<"; + if (AddressSpace() != core::AddressSpace::kUndefined) { + out << AddressSpace() << ", "; + } + out << StoreType()->FriendlyName() << ", " << Access(); + out << ">"; + return out.str(); +} + +Reference::~Reference() = default; + +Reference* Reference::Clone(CloneContext& ctx) const { + auto* ty = StoreType()->Clone(ctx); + return ctx.dst.mgr->Get(AddressSpace(), ty, Access()); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/reference.h b/3rdparty/dawn/src/tint/lang/core/type/reference.h new file mode 100644 index 000000000..b74593c7d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/reference.h @@ -0,0 +1,64 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_REFERENCE_H_ +#define SRC_TINT_LANG_CORE_TYPE_REFERENCE_H_ + +#include + +#include "src/tint/lang/core/type/memory_view.h" + +namespace tint::core::type { + +/// A reference type. +class Reference final : public Castable { + public: + /// Constructor + /// @param address_space the address space of the reference + /// @param store_type the store type + /// @param access the resolved access control of the reference + Reference(core::AddressSpace address_space, const Type* store_type, core::Access access); + + /// Destructor + ~Reference() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Reference* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_REFERENCE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/resource_type.cc b/3rdparty/dawn/src/tint/lang/core/type/resource_type.cc new file mode 100644 index 000000000..8154e7dc4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/resource_type.cc @@ -0,0 +1,183 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/resource_type.h" + +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::core::type { + +const core::type::Type* ResourceTypeToType(core::type::Manager& ty, ResourceType type) { + switch (type) { + case ResourceType::kTexture1d_f32: + return ty.sampled_texture(core::type::TextureDimension::k1d, ty.f32()); + case ResourceType::kTexture1d_i32: + return ty.sampled_texture(core::type::TextureDimension::k1d, ty.i32()); + case ResourceType::kTexture1d_u32: + return ty.sampled_texture(core::type::TextureDimension::k1d, ty.u32()); + case ResourceType::kTexture2d_f32: + return ty.sampled_texture(core::type::TextureDimension::k2d, ty.f32()); + case ResourceType::kTexture2d_i32: + return ty.sampled_texture(core::type::TextureDimension::k2d, ty.i32()); + case ResourceType::kTexture2d_u32: + return ty.sampled_texture(core::type::TextureDimension::k2d, ty.u32()); + case ResourceType::kTexture2dArray_f32: + return ty.sampled_texture(core::type::TextureDimension::k2dArray, ty.f32()); + case ResourceType::kTexture2dArray_i32: + return ty.sampled_texture(core::type::TextureDimension::k2dArray, ty.i32()); + case ResourceType::kTexture2dArray_u32: + return ty.sampled_texture(core::type::TextureDimension::k2dArray, ty.u32()); + case ResourceType::kTexture3d_f32: + return ty.sampled_texture(core::type::TextureDimension::k3d, ty.f32()); + case ResourceType::kTexture3d_i32: + return ty.sampled_texture(core::type::TextureDimension::k3d, ty.i32()); + case ResourceType::kTexture3d_u32: + return ty.sampled_texture(core::type::TextureDimension::k3d, ty.u32()); + case ResourceType::kTextureCube_f32: + return ty.sampled_texture(core::type::TextureDimension::kCube, ty.f32()); + case ResourceType::kTextureCube_i32: + return ty.sampled_texture(core::type::TextureDimension::kCube, ty.i32()); + case ResourceType::kTextureCube_u32: + return ty.sampled_texture(core::type::TextureDimension::kCube, ty.u32()); + case ResourceType::kTextureCubeArray_f32: + return ty.sampled_texture(core::type::TextureDimension::kCubeArray, ty.f32()); + case ResourceType::kTextureCubeArray_i32: + return ty.sampled_texture(core::type::TextureDimension::kCubeArray, ty.i32()); + case ResourceType::kTextureCubeArray_u32: + return ty.sampled_texture(core::type::TextureDimension::kCubeArray, ty.u32()); + + case ResourceType::kTextureMultisampled2d_f32: + return ty.multisampled_texture(core::type::TextureDimension::k2d, ty.f32()); + case ResourceType::kTextureMultisampled2d_i32: + return ty.multisampled_texture(core::type::TextureDimension::k2d, ty.i32()); + case ResourceType::kTextureMultisampled2d_u32: + return ty.multisampled_texture(core::type::TextureDimension::k2d, ty.u32()); + + case ResourceType::kTextureDepth2d: + return ty.depth_texture(core::type::TextureDimension::k2d); + case ResourceType::kTextureDepth2dArray: + return ty.depth_texture(core::type::TextureDimension::k2dArray); + case ResourceType::kTextureDepthCube: + return ty.depth_texture(core::type::TextureDimension::kCube); + case ResourceType::kTextureDepthCubeArray: + return ty.depth_texture(core::type::TextureDimension::kCubeArray); + case ResourceType::kTextureDepthMultisampled2d: + return ty.depth_multisampled_texture(core::type::TextureDimension::k2d); + + default: + TINT_UNREACHABLE(); + } +} + +ResourceType TypeToResourceType(const core::type::Type* in_type) { + return tint::Switch( + in_type, + [&](const core::type::SampledTexture* sa) { + switch (sa->Dim()) { + case core::type::TextureDimension::k1d: + return tint::Switch( + sa->Type(), + [&](const core::type::F32*) { return ResourceType::kTexture1d_f32; }, + [&](const core::type::I32*) { return ResourceType::kTexture1d_i32; }, + [&](const core::type::U32*) { return ResourceType::kTexture1d_u32; }, + TINT_ICE_ON_NO_MATCH); + case core::type::TextureDimension::k2d: + return tint::Switch( + sa->Type(), + [&](const core::type::F32*) { return ResourceType::kTexture2d_f32; }, + [&](const core::type::I32*) { return ResourceType::kTexture2d_i32; }, + [&](const core::type::U32*) { return ResourceType::kTexture2d_u32; }, + TINT_ICE_ON_NO_MATCH); + case core::type::TextureDimension::k2dArray: + return tint::Switch( + sa->Type(), + [&](const core::type::F32*) { return ResourceType::kTexture2dArray_f32; }, + [&](const core::type::I32*) { return ResourceType::kTexture2dArray_i32; }, + [&](const core::type::U32*) { return ResourceType::kTexture2dArray_u32; }, + TINT_ICE_ON_NO_MATCH); + case core::type::TextureDimension::k3d: + return tint::Switch( + sa->Type(), + [&](const core::type::F32*) { return ResourceType::kTexture3d_f32; }, + [&](const core::type::I32*) { return ResourceType::kTexture3d_i32; }, + [&](const core::type::U32*) { return ResourceType::kTexture3d_u32; }, + TINT_ICE_ON_NO_MATCH); + case core::type::TextureDimension::kCube: + return tint::Switch( + sa->Type(), + [&](const core::type::F32*) { return ResourceType::kTextureCube_f32; }, + [&](const core::type::I32*) { return ResourceType::kTextureCube_i32; }, + [&](const core::type::U32*) { return ResourceType::kTextureCube_u32; }, + TINT_ICE_ON_NO_MATCH); + case core::type::TextureDimension::kCubeArray: + return tint::Switch( + sa->Type(), + [&](const core::type::F32*) { return ResourceType::kTextureCubeArray_f32; }, + [&](const core::type::I32*) { return ResourceType::kTextureCubeArray_i32; }, + [&](const core::type::U32*) { return ResourceType::kTextureCubeArray_u32; }, + TINT_ICE_ON_NO_MATCH); + case core::type::TextureDimension::kNone: + TINT_UNREACHABLE(); + } + }, + [&](const core::type::MultisampledTexture* ms) { + return tint::Switch( + ms->Type(), + [&](const core::type::F32*) { return ResourceType::kTextureMultisampled2d_f32; }, + [&](const core::type::I32*) { return ResourceType::kTextureMultisampled2d_i32; }, + [&](const core::type::U32*) { return ResourceType::kTextureMultisampled2d_u32; }, + TINT_ICE_ON_NO_MATCH); + }, + [&](const core::type::DepthMultisampledTexture*) { + return ResourceType::kTextureDepthMultisampled2d; + }, + [&](const core::type::DepthTexture* de) { + switch (de->Dim()) { + case core::type::TextureDimension::k2d: + return ResourceType::kTextureDepth2d; + case core::type::TextureDimension::k2dArray: + return ResourceType::kTextureDepth2dArray; + case core::type::TextureDimension::kCube: + return ResourceType::kTextureDepthCube; + case core::type::TextureDimension::kCubeArray: + return ResourceType::kTextureDepthCubeArray; + default: + TINT_UNREACHABLE(); + } + }, + TINT_ICE_ON_NO_MATCH); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/resource_type.h b/3rdparty/dawn/src/tint/lang/core/type/resource_type.h new file mode 100644 index 000000000..369a75655 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/resource_type.h @@ -0,0 +1,44 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_RESOURCE_TYPE_H_ +#define SRC_TINT_LANG_CORE_TYPE_RESOURCE_TYPE_H_ + +#include "src/tint/api/common/resource_type.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +// Converts a `in_type` into a resource type +ResourceType TypeToResourceType(const core::type::Type* in_type); + +// Converts a `ResourceType` back into a `core::type::Type` +const core::type::Type* ResourceTypeToType(core::type::Manager& ty, ResourceType type); + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_RESOURCE_TYPE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/sampled_texture.cc b/3rdparty/dawn/src/tint/lang/core/type/sampled_texture.cc new file mode 100644 index 000000000..efea9adde --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/sampled_texture.cc @@ -0,0 +1,66 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/sampled_texture.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::SampledTexture); + +namespace tint::core::type { + +SampledTexture::SampledTexture(TextureDimension dim, const type::Type* type) + : Base(Hash(TypeCode::Of().bits, dim, type), dim), type_(type) { + TINT_ASSERT(type_); +} + +SampledTexture::~SampledTexture() = default; + +bool SampledTexture::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->Dim() == Dim() && o->type_ == type_; + } + return false; +} + +std::string SampledTexture::FriendlyName() const { + StringStream out; + out << "texture_" << Dim() << "<" << type_->FriendlyName() << ">"; + return out.str(); +} + +SampledTexture* SampledTexture::Clone(CloneContext& ctx) const { + auto* ty = type_->Clone(ctx); + return ctx.dst.mgr->Get(Dim(), ty); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/sampled_texture.h b/3rdparty/dawn/src/tint/lang/core/type/sampled_texture.h new file mode 100644 index 000000000..27d55863e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/sampled_texture.h @@ -0,0 +1,70 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_SAMPLED_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_SAMPLED_TEXTURE_H_ + +#include + +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" + +namespace tint::core::type { + +/// A sampled texture type. +class SampledTexture final : public Castable { + public: + /// Constructor + /// @param dim the dimensionality of the texture + /// @param type the data type of the sampled texture + SampledTexture(TextureDimension dim, const type::Type* type); + + /// Destructor + ~SampledTexture() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the subtype of the sampled texture + const type::Type* Type() const { return type_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + SampledTexture* Clone(CloneContext& ctx) const override; + + private: + const type::Type* type_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_SAMPLED_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/sampler.cc b/3rdparty/dawn/src/tint/lang/core/type/sampler.cc new file mode 100644 index 000000000..49d9f50d0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/sampler.cc @@ -0,0 +1,61 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/sampler.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/math/hash.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Sampler); + +namespace tint::core::type { + +Sampler::Sampler(SamplerKind kind) + : Base(Hash(tint::TypeCode::Of().bits, kind), core::type::Flags{}), kind_(kind) {} + +Sampler::~Sampler() = default; + +bool Sampler::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->kind_ == kind_; + } + return false; +} + +uint32_t Sampler::Align() const { + return 1; +} + +std::string Sampler::FriendlyName() const { + return kind_ == SamplerKind::kSampler ? "sampler" : "sampler_comparison"; +} + +Sampler* Sampler::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(kind_); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/sampler.h b/3rdparty/dawn/src/tint/lang/core/type/sampler.h new file mode 100644 index 000000000..9a9473e60 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/sampler.h @@ -0,0 +1,75 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_SAMPLER_H_ +#define SRC_TINT_LANG_CORE_TYPE_SAMPLER_H_ + +#include + +#include "src/tint/lang/core/type/sampler_kind.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A sampler type. +class Sampler final : public Castable { + public: + /// Constructor + /// @param kind the kind of sampler + explicit Sampler(SamplerKind kind); + + /// Destructor + ~Sampler() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the sampler type + SamplerKind Kind() const { return kind_; } + + /// @returns true if this is a comparison sampler + bool IsComparison() const { return kind_ == SamplerKind::kComparisonSampler; } + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Sampler* Clone(CloneContext& ctx) const override; + + private: + SamplerKind const kind_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_SAMPLER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/sampler_kind.cc b/3rdparty/dawn/src/tint/lang/core/type/sampler_kind.cc new file mode 100644 index 000000000..32c614daa --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/sampler_kind.cc @@ -0,0 +1,42 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/sampler_kind.h" + +namespace tint::core::type { + +std::string_view ToString(SamplerKind kind) { + switch (kind) { + case SamplerKind::kSampler: + return "sampler"; + case SamplerKind::kComparisonSampler: + return "comparison_sampler"; + } + return ""; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/sampler_kind.h b/3rdparty/dawn/src/tint/lang/core/type/sampler_kind.h new file mode 100644 index 000000000..6c517b29f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/sampler_kind.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_SAMPLER_KIND_H_ +#define SRC_TINT_LANG_CORE_TYPE_SAMPLER_KIND_H_ + +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::core::type { + +/// The different kinds of samplers +enum class SamplerKind { + /// A regular sampler + kSampler, + /// A comparison sampler + kComparisonSampler +}; + +/// @param kind the enum value +/// @returns the string for the given enum value +std::string_view ToString(enum SamplerKind kind); + +/// @param out the stream to write to +/// @param kind the SamplerKind +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, SamplerKind kind) { + return out << ToString(kind); +} + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_SAMPLER_KIND_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/scalar.cc b/3rdparty/dawn/src/tint/lang/core/type/scalar.cc new file mode 100644 index 000000000..c499ea128 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/scalar.cc @@ -0,0 +1,42 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/scalar.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Scalar); + +namespace tint::core::type { + +Scalar::Scalar(size_t hash, core::type::Flags flags) : Base(hash, flags) {} + +Scalar::~Scalar() = default; + +bool Scalar::Equals(const UniqueNode& other) const { + return &other.TypeInfo() == &TypeInfo(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/scalar.h b/3rdparty/dawn/src/tint/lang/core/type/scalar.h new file mode 100644 index 000000000..e1052bf3a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/scalar.h @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_SCALAR_H_ +#define SRC_TINT_LANG_CORE_TYPE_SCALAR_H_ + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// Base class for all scalar types +/// @see https://www.w3.org/TR/WGSL/#scalar-types +class Scalar : public Castable { + public: + /// Destructor + ~Scalar() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + protected: + /// Constructor + /// @param hash the immutable hash for the node + /// @param flags the flags of this type + Scalar(size_t hash, core::type::Flags flags); +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_SCALAR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/storage_texture.cc b/3rdparty/dawn/src/tint/lang/core/type/storage_texture.cc new file mode 100644 index 000000000..e5044eac3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/storage_texture.cc @@ -0,0 +1,70 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/storage_texture.h" + +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::StorageTexture); + +namespace tint::core::type { + +StorageTexture::StorageTexture(TextureDimension dim, + core::TexelFormat format, + core::Access access, + const type::Type* subtype) + : Base(Hash(tint::TypeCode::Of().bits, dim, format, access), dim), + texel_format_(format), + access_(access), + subtype_(subtype) {} + +StorageTexture::~StorageTexture() = default; + +bool StorageTexture::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->Dim() == Dim() && o->texel_format_ == texel_format_ && o->access_ == access_; + } + return false; +} + +std::string StorageTexture::FriendlyName() const { + StringStream out; + out << "texture_storage_" << Dim() << "<" << texel_format_ << ", " << access_ << ">"; + return out.str(); +} + +StorageTexture* StorageTexture::Clone(CloneContext& ctx) const { + auto* ty = subtype_->Clone(ctx); + return ctx.dst.mgr->Get(Dim(), texel_format_, access_, ty); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/storage_texture.h b/3rdparty/dawn/src/tint/lang/core/type/storage_texture.h new file mode 100644 index 000000000..e11479ea0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/storage_texture.h @@ -0,0 +1,89 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_STORAGE_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_STORAGE_TEXTURE_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" + +// Forward declarations +namespace tint::core::type { +class Manager; +} // namespace tint::core::type + +namespace tint::core::type { + +/// A storage texture type. +class StorageTexture final : public Castable { + public: + /// Constructor + /// @param dim the dimensionality of the texture + /// @param format the texel format of the texture + /// @param access the access control type of the texture + /// @param subtype the storage subtype. + StorageTexture(TextureDimension dim, + core::TexelFormat format, + core::Access access, + const Type* subtype); + + /// Destructor + ~StorageTexture() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the storage subtype + const type::Type* Type() const { return subtype_; } + + /// @returns the texel format + core::TexelFormat TexelFormat() const { return texel_format_; } + + /// @returns the access control + core::Access Access() const { return access_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + StorageTexture* Clone(CloneContext& ctx) const override; + + private: + core::TexelFormat const texel_format_; + core::Access const access_; + const type::Type* const subtype_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_STORAGE_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/string.cc b/3rdparty/dawn/src/tint/lang/core/type/string.cc new file mode 100644 index 000000000..25c372d9d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/string.cc @@ -0,0 +1,56 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/string.h" + +#include + +#include "src/tint/lang/core/type/clone_context.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/unique_node.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/rtti/castable.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::String); + +namespace tint::core::type { + +String::String() : Base(Hash(tint::TypeCode::Of().bits), core::type::Flags{}) {} + +bool String::Equals(const UniqueNode& other) const { + return other.Is(); +} + +std::string String::FriendlyName() const { + return "string"; +} + +String* String::Clone(core::type::CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/string.h b/3rdparty/dawn/src/tint/lang/core/type/string.h new file mode 100644 index 000000000..afb5e762c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/string.h @@ -0,0 +1,57 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_STRING_H_ +#define SRC_TINT_LANG_CORE_TYPE_STRING_H_ + +#include + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// String represents a C-style string, used for print format strings. +class String final : public Castable { + public: + /// Constructor + String(); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the friendly name for this type + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + String* Clone(core::type::CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_STRING_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/struct.cc b/3rdparty/dawn/src/tint/lang/core/type/struct.cc new file mode 100644 index 000000000..728c540b3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/struct.cc @@ -0,0 +1,290 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/struct.h" + +#include +#include +#include +#include +#include +#include + +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/symbol/symbol_table.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Struct); +TINT_INSTANTIATE_TYPEINFO(tint::core::type::StructMember); + +namespace tint::core::type { +namespace { + +Flags FlagsFrom(VectorRef members) { + Flags flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }; + for (auto* member : members) { + if (!member->Type()->IsConstructible()) { + flags.Remove(Flag::kConstructable); + } + if (!member->Type()->HasFixedFootprint()) { + flags.Remove(Flag::kFixedFootprint); + } + if (!member->Type()->HasCreationFixedFootprint()) { + flags.Remove(Flag::kCreationFixedFootprint); + } + if (!member->Type()->IsHostShareable()) { + flags.Remove(Flag::kHostShareable); + } + } + return flags; +} + +} // namespace + +Struct::Struct(Symbol name, bool is_wgsl_internal) + : Base(Hash(tint::TypeCode::Of().bits, name, is_wgsl_internal), type::Flags{}), + name_(name), + members_{}, + size_(0), + is_wgsl_internal_(is_wgsl_internal) {} + +Struct::Struct(Symbol name, + VectorRef members, + uint32_t size, + bool is_wgsl_internal) + : Base(Hash(tint::TypeCode::Of().bits, name, is_wgsl_internal), FlagsFrom(members)), + name_(name), + members_(std::move(members)), + size_(size), + is_wgsl_internal_(is_wgsl_internal) {} + +Struct::~Struct() = default; + +bool Struct::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->name_ == name_; + } + return false; +} + +const StructMember* Struct::FindMember(Symbol name) const { + for (auto* member : members_) { + if (member->Name() == name) { + return member; + } + } + return nullptr; +} + +uint32_t Struct::Align() const { + uint32_t align = 0; + for (auto* mem : members_) { + align = std::max(align, mem->Align()); + } + return align; +} + +uint32_t Struct::Size() const { + return size_; +} + +std::string Struct::FriendlyName() const { + return name_.Name(); +} + +StyledText Struct::Layout() const { + static constexpr auto Code = style::Code + style::NoQuote; + static constexpr auto Comment = style::Comment + style::NoQuote; + static constexpr auto Keyword = style::Keyword + style::NoQuote; + static constexpr auto Type = style::Type + style::NoQuote; + static constexpr auto Variable = style::Variable + style::NoQuote; + static constexpr auto Plain = style::Plain; + + StyledText out; + + auto member_name_of = [&](const StructMember* sm) { return sm->Name().Name(); }; + + if (Members().IsEmpty()) { + return {}; + } + const auto* const last_member = Members().Back(); + const uint32_t last_member_struct_padding_offset = last_member->Offset() + last_member->Size(); + + // Compute max widths to align output + const auto offset_w = static_cast(::log10(last_member_struct_padding_offset)) + 1; + const auto size_w = static_cast(::log10(Size())) + 1; + const auto align_w = static_cast(::log10(Align())) + 1; + + auto pad = [](int n) { return std::string(static_cast(n), ' '); }; + + auto print_struct_begin_line = [&](size_t align, size_t size, std::string struct_name) { + out << Comment("/* ", pad(offset_w), "align(", std::setw(align_w), align, + ") size(", std::setw(size_w), size, ") */") + << Keyword(" struct ") << Type(struct_name) << Code(" {") << Plain("\n"); + }; + + auto print_struct_end_line = [&] { + out << Comment("/* ", pad(offset_w + size_w + align_w), "*/") + << Code(" };"); + }; + + auto print_member_line = [&](size_t offset, size_t align, size_t size, StyledText s) { + out << Comment("/* offset(", std::setw(offset_w), offset, ") align(", std::setw(align_w), + align, ") size(", std::setw(size_w), size, ") */ ") + << s << Plain("\n"); + }; + + print_struct_begin_line(Align(), Size(), UnwrapRef()->FriendlyName()); + + for (size_t i = 0; i < Members().Length(); ++i) { + auto* const m = Members()[i]; + + // Output field alignment padding, if any + auto* const prev_member = (i == 0) ? nullptr : Members()[i - 1]; + if (prev_member) { + uint32_t padding = m->Offset() - (prev_member->Offset() + prev_member->Size()); + if (padding > 0) { + size_t padding_offset = m->Offset() - padding; + print_member_line(padding_offset, 1, padding, + StyledText{} + << Code(" ") + << Comment("// -- implicit field alignment padding --")); + } + } + + // Output member + std::string member_name = member_name_of(m); + print_member_line(m->Offset(), m->Align(), m->Size(), + StyledText{} << Code(" ") << Variable(member_name) << Code(" : ") + << Type(m->Type()->UnwrapRef()->FriendlyName()) + << Code(",")); + } + + // Output struct size padding, if any + uint32_t struct_padding = Size() - last_member_struct_padding_offset; + if (struct_padding > 0) { + print_member_line( + last_member_struct_padding_offset, 1, struct_padding, + StyledText{} << Code(" ") << Comment("// -- implicit struct size padding --")); + } + + print_struct_end_line(); + + return out; +} + +TypeAndCount Struct::Elements(const Type* type_if_invalid /* = nullptr */, + uint32_t /* count_if_invalid = 0 */) const { + return {type_if_invalid, static_cast(members_.Length())}; +} + +const Type* Struct::Element(uint32_t index) const { + return index < members_.Length() ? members_[index]->Type() : nullptr; +} + +uint32_t Struct::SizeNoPadding() const { + if (members_.IsEmpty()) { + return 0; + } + auto& mem = members_.Back(); + return mem->Offset() + mem->Size(); +} + +Struct* Struct::Clone(CloneContext& ctx) const { + auto sym = ctx.dst.st->Register(name_.Name()); + + tint::Vector members; + for (const auto& mem : members_) { + members.Push(mem->Clone(ctx)); + } + return ctx.dst.mgr->Get(sym, members, size_, is_wgsl_internal_); +} + +StructMember::StructMember(Symbol name, + const core::type::Type* type, + uint32_t index, + uint32_t offset, + uint32_t align, + uint32_t size, + const IOAttributes& attributes) + : name_(name), + type_(type), + index_(index), + offset_(offset), + align_(align), + size_(size), + attributes_(attributes) {} + +StructMember::~StructMember() = default; + +uint32_t StructMember::MinimumRequiredSize() const { + auto* ty = type_; + uint32_t array_multiplier = 1; + while (ty->Is()) { + auto* arr = ty->As(); + if (auto* count = arr->Count()->As()) { + array_multiplier *= count->value; + } + + ty = arr->ElemType(); + } + + auto* mat = ty->As(); + if (!mat) { + return type_->Size(); + } + + uint32_t dim = is_row_major_ ? mat->Rows() : mat->Columns(); + auto s = HasMatrixStride() ? matrix_stride_ * dim : mat->Size(); + return (s * array_multiplier); +} + +StructMember* StructMember::Clone(CloneContext& ctx) const { + auto sym = ctx.dst.st->Register(name_.Name()); + auto* ty = type_->Clone(ctx); + auto* member = + ctx.dst.mgr->Get(sym, ty, index_, offset_, align_, size_, attributes_); + + if (is_row_major_) { + member->SetRowMajor(); + } + member->SetMatrixStride(matrix_stride_); + return member; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/struct.h b/3rdparty/dawn/src/tint/lang/core/type/struct.h new file mode 100644 index 000000000..6f99db757 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/struct.h @@ -0,0 +1,295 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_STRUCT_H_ +#define SRC_TINT_LANG_CORE_TYPE_STRUCT_H_ + +#include +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/interpolation.h" +#include "src/tint/lang/core/io_attributes.h" +#include "src/tint/lang/core/type/node.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/symbol/symbol.h" +#include "src/tint/utils/text/styled_text.h" + +// Forward declarations +namespace tint::core::type { +class StructMember; +} // namespace tint::core::type + +namespace tint::core::type { + +/// Metadata to capture how a structure is used in a shader module. +enum class PipelineStageUsage { + kVertexInput, + kVertexOutput, + kFragmentInput, + kFragmentOutput, + kComputeInput, + kComputeOutput, +}; + +/// StructFlag is an enumerator of struct flag bits, used by StructFlags. +enum StructFlag { + /// The structure is a block-decorated structure (for SPIR-V or GLSL). + kBlock, + /// The structure requires explicit layout decorations + kExplicitLayout, +}; + +/// An alias to tint::EnumSet +using StructFlags = tint::EnumSet; + +/// Struct holds the Type information for structures. +class Struct : public Castable { + public: + /// Constructor + /// Note: this constructs an empty structure, which should only be used find a struct with the + /// same name in a type::Manager. + /// @param name the name of the structure + /// @param is_wgsl_internal `true` if the structure is an internally defined structure in WGSL + Struct(Symbol name, bool is_wgsl_internal); + + /// Constructor + /// @param name the name of the structure + /// @param members the structure members + /// @param size the byte size of the structure + /// @param is_wgsl_internal `true` if the structure is an internally defined structure in WGSL + /// alignment padding + Struct(Symbol name, + VectorRef members, + uint32_t size, + bool is_wgsl_internal = false); + + /// Destructor + ~Struct() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name of the structure + Symbol Name() const { return name_; } + + /// Renames the structure + /// @param name the new name for the structure + void SetName(Symbol name) { name_ = name; } + + /// @returns the members of the structure + VectorRef Members() const { return members_; } + + /// @param name the member name to look for + /// @returns the member with the given name, or nullptr if it was not found. + const StructMember* FindMember(Symbol name) const; + + /// @returns the byte alignment of the structure + /// @note this may differ from the alignment of a structure member of this + /// structure type, if the member is annotated with the `@align(n)` + /// attribute. + uint32_t Align() const override; + + /// @returns the byte size of the structure + /// @note this may differ from the size of a structure member of this + /// structure type, if the member is annotated with the `@size(n)` + /// attribute. + uint32_t Size() const override; + + /// @returns the byte size of the members without the end of structure + /// alignment padding + uint32_t SizeNoPadding() const; + + /// @returns the structure flags + core::type::StructFlags StructFlags() const { return struct_flags_; } + + /// Set a structure flag. + /// @param flag the flag to set + void SetStructFlag(StructFlag flag) { struct_flags_.Add(flag); } + + /// Adds the AddressSpace usage to the structure. + /// @param usage the storage usage + void AddUsage(core::AddressSpace usage) { address_space_usage_.Add(usage); } + + /// @returns the set of address space uses of this structure + const Hashset& AddressSpaceUsage() const { return address_space_usage_; } + + /// @param usage the AddressSpace usage type to query + /// @returns true iff this structure has been used as the given address space + bool UsedAs(core::AddressSpace usage) const { return address_space_usage_.Contains(usage); } + + /// Adds the pipeline stage usage to the structure. + /// @param usage the storage usage + void AddUsage(PipelineStageUsage usage) { pipeline_stage_uses_.Add(usage); } + + /// @returns the set of entry point uses of this structure + const Hashset& PipelineStageUses() const { return pipeline_stage_uses_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns a multiline string that describes the layout of this struct, + /// including size and alignment information. + StyledText Layout() const; + + /// @param concrete the conversion-rank ordered concrete versions of this abstract structure. + void SetConcreteTypes(VectorRef concrete) { concrete_types_ = concrete; } + + /// @returns the conversion-rank ordered concrete versions of this abstract structure, or an + /// empty vector if this structure is not abstract. + /// @note only structures returned by builtins may be abstract (e.g. modf, frexp) + VectorRef ConcreteTypes() const { return concrete_types_; } + + /// @copydoc Type::Elements + TypeAndCount Elements(const Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc Type::Element + const Type* Element(uint32_t index) const override; + + /// @returns `true` if this struct is internally defined in WGSL + bool IsWgslInternal() const { return is_wgsl_internal_; } + + /// @param ctx the clone context + /// @returns a clone of this type + Struct* Clone(CloneContext& ctx) const override; + + private: + Symbol name_; + const tint::Vector members_; + const uint32_t size_; + const bool is_wgsl_internal_; + core::type::StructFlags struct_flags_; + Hashset address_space_usage_; + Hashset pipeline_stage_uses_; + tint::Vector concrete_types_; +}; + +/// StructMember holds the type information for structure members. +class StructMember : public Castable { + public: + /// Constructor + /// @param name the name of the structure member + /// @param type the type of the member + /// @param index the index of the member in the structure + /// @param offset the byte offset from the base of the structure + /// @param align the byte alignment of the member + /// @param size the byte size of the member + /// @param attributes the optional attributes + StructMember(Symbol name, + const core::type::Type* type, + uint32_t index, + uint32_t offset, + uint32_t align, + uint32_t size, + const IOAttributes& attributes); + + /// Destructor + ~StructMember() override; + + /// @returns the name of the structure member + Symbol Name() const { return name_; } + + /// Sets the owning structure to `s` + /// @param s the new structure owner + void SetStruct(const Struct* s) { struct_ = s; } + + /// @returns the structure that owns this member + const core::type::Struct* Struct() const { return struct_; } + + /// @returns the type of the member + const core::type::Type* Type() const { return type_; } + + /// @returns the member index + uint32_t Index() const { return index_; } + + /// @returns byte offset from base of structure + uint32_t Offset() const { return offset_; } + + /// @returns the alignment of the member in bytes + uint32_t Align() const { return align_; } + + /// @returns byte size + uint32_t Size() const { return size_; } + + /// @returns the minimum size required for this struct member. + uint32_t MinimumRequiredSize() const; + + /// @returns the optional attributes + const IOAttributes& Attributes() const { return attributes_; } + + /// Sets the interpolation. + /// @param interpolation the optional location interpolation settings + void SetInterpolation(std::optional interpolation) { + attributes_.interpolation = interpolation; + } + + /// Sets the location. + /// @param loc the optional location value + void SetLocation(std::optional loc) { attributes_.location = loc; } + + /// Resets the attributes to empty + void ResetAttributes() { attributes_ = {}; } + + /// Sets this member to be row major + void SetRowMajor() { is_row_major_ = true; } + /// Returns if this member is row major + bool RowMajor() const { return is_row_major_; } + + /// Sets the matrix stride for the member + void SetMatrixStride(uint32_t matrix_stride) { matrix_stride_ = matrix_stride; } + /// Returns true if a matrix stride is set + bool HasMatrixStride() const { return matrix_stride_ > 0; } + /// Returns the matrix stride + uint32_t MatrixStride() const { return matrix_stride_; } + + /// @param ctx the clone context + /// @returns a clone of this struct member + StructMember* Clone(CloneContext& ctx) const; + + private: + const Symbol name_; + const core::type::Struct* struct_; + const core::type::Type* type_; + const uint32_t index_; + const uint32_t offset_; + const uint32_t align_; + const uint32_t size_; + bool is_row_major_ = false; + uint32_t matrix_stride_ = 0; + IOAttributes attributes_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_STRUCT_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.cc b/3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.cc new file mode 100644 index 000000000..cc127221f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.cc @@ -0,0 +1,95 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/subgroup_matrix.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::SubgroupMatrix); + +namespace tint::core::type { + +SubgroupMatrix::SubgroupMatrix(SubgroupMatrixKind kind, + const type::Type* subtype, + uint32_t columns, + uint32_t rows) + : Base(Hash(tint::TypeCode::Of().bits, kind, columns, rows, subtype), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }), + kind_(kind), + subtype_(subtype), + columns_(columns), + rows_(rows) {} + +SubgroupMatrix::~SubgroupMatrix() = default; + +bool SubgroupMatrix::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return v->kind_ == kind_ && v->rows_ == rows_ && v->columns_ == columns_ && + v->subtype_ == subtype_; + } + return false; +} + +uint32_t SubgroupMatrix::Align() const { + return subtype_->Align(); +} + +TypeAndCount SubgroupMatrix::Elements(const type::Type* /* type_if_invalid = nullptr */, + uint32_t /* count_if_invalid = 0 */) const { + return {subtype_, columns_}; +} + +std::string SubgroupMatrix::FriendlyName() const { + StringStream out; + out << "subgroup_matrix_"; + switch (kind_) { + case SubgroupMatrixKind::kLeft: + out << "left"; + break; + case SubgroupMatrixKind::kRight: + out << "right"; + break; + case SubgroupMatrixKind::kResult: + out << "result"; + break; + case SubgroupMatrixKind::kUndefined: + TINT_UNREACHABLE(); + } + out << "<" << subtype_->FriendlyName() << ", " << columns_ << ", " << rows_ << ">"; + return out.str(); +} + +SubgroupMatrix* SubgroupMatrix::Clone(CloneContext& ctx) const { + auto* ty = subtype_->Clone(ctx); + return ctx.dst.mgr->Get(kind_, ty, columns_, rows_); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.h b/3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.h new file mode 100644 index 000000000..0299f2b42 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/subgroup_matrix.h @@ -0,0 +1,93 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_SUBGROUP_MATRIX_H_ +#define SRC_TINT_LANG_CORE_TYPE_SUBGROUP_MATRIX_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/clone_context.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A subgroup_matrix type +class SubgroupMatrix : public Castable { + public: + /// Constructor + /// @param kind the kind of the matrix + /// @param subtype the inner type of the matrix + /// @param columns the number of columns in the matrix + /// @param rows the number of rows in the matrix + SubgroupMatrix(SubgroupMatrixKind kind, const Type* subtype, uint32_t columns, uint32_t rows); + + /// Destructor + ~SubgroupMatrix() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the kind of the matrix + SubgroupMatrixKind Kind() const { return kind_; } + /// @returns the type of the matrix + const type::Type* Type() const { return subtype_; } + /// @returns the number of columns in the matrix + uint32_t Columns() const { return columns_; } + /// @returns the number of rows in the matrix + uint32_t Rows() const { return rows_; } + + /// @copydoc Type::Elements + TypeAndCount Elements(const type::Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc Type::Element + const type::Type* Element(uint32_t) const override { return subtype_; } + + /// @returns the alignment in bytes of the type. This may include tail + /// padding. + uint32_t Align() const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + SubgroupMatrix* Clone(CloneContext& ctx) const override; + + private: + const SubgroupMatrixKind kind_; + const type::Type* const subtype_; + const uint32_t columns_; + const uint32_t rows_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_SUBGROUP_MATRIX_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/texel_buffer.cc b/3rdparty/dawn/src/tint/lang/core/type/texel_buffer.cc new file mode 100644 index 000000000..a8bb8ecdd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/texel_buffer.cc @@ -0,0 +1,68 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/texel_buffer.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::TexelBuffer); + +namespace tint::core::type { + +TexelBuffer::TexelBuffer(core::TexelFormat format, core::Access access, const type::Type* subtype) + : Base(Hash(TypeCode::Of().bits, format, access, subtype), TextureDimension::k1d), + texel_format_(format), + access_(access), + subtype_(subtype) { + TINT_ASSERT(subtype_); +} + +TexelBuffer::~TexelBuffer() = default; + +bool TexelBuffer::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->texel_format_ == texel_format_ && o->access_ == access_ && + o->subtype_ == subtype_; + } + return false; +} + +std::string TexelBuffer::FriendlyName() const { + StringStream out; + out << "texel_buffer<" << texel_format_ << ", " << access_ << ">"; + return out.str(); +} + +TexelBuffer* TexelBuffer::Clone(CloneContext& ctx) const { + auto* ty = subtype_->Clone(ctx); + return ctx.dst.mgr->Get(texel_format_, access_, ty); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/texel_buffer.h b/3rdparty/dawn/src/tint/lang/core/type/texel_buffer.h new file mode 100644 index 000000000..31e9a1a9e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/texel_buffer.h @@ -0,0 +1,84 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_TEXEL_BUFFER_H_ +#define SRC_TINT_LANG_CORE_TYPE_TEXEL_BUFFER_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/texture.h" + +// Forward declarations +namespace tint::core::type { +class Manager; +} // namespace tint::core::type + +namespace tint::core::type { + +/// A texel buffer type. +class TexelBuffer final : public Castable { + public: + /// Constructor + /// @param format the texel format of the texel buffer + /// @param access the access control type of the texel buffer + /// @param subtype the storage subtype. + TexelBuffer(core::TexelFormat format, core::Access access, const Type* subtype); + + /// Destructor + ~TexelBuffer() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the storage subtype + const type::Type* Type() const { return subtype_; } + + /// @returns the texel format + core::TexelFormat TexelFormat() const { return texel_format_; } + + /// @returns the access control + core::Access Access() const { return access_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + TexelBuffer* Clone(CloneContext& ctx) const override; + + private: + core::TexelFormat const texel_format_; + core::Access const access_; + const type::Type* const subtype_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_TEXEL_BUFFER_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/texture.cc b/3rdparty/dawn/src/tint/lang/core/type/texture.cc new file mode 100644 index 000000000..acd271c56 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/texture.cc @@ -0,0 +1,74 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/texture.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Texture); + +namespace tint::core::type { + +Texture::Texture(size_t hash, TextureDimension dim) : Base(hash, core::type::Flags{}), dim_(dim) {} + +Texture::~Texture() = default; + +bool IsTextureArray(core::type::TextureDimension dim) { + switch (dim) { + case core::type::TextureDimension::k2dArray: + case core::type::TextureDimension::kCubeArray: + return true; + case core::type::TextureDimension::k2d: + case core::type::TextureDimension::kNone: + case core::type::TextureDimension::k1d: + case core::type::TextureDimension::k3d: + case core::type::TextureDimension::kCube: + return false; + } + return false; +} + +int NumCoordinateAxes(core::type::TextureDimension dim) { + switch (dim) { + case core::type::TextureDimension::kNone: + return 0; + case core::type::TextureDimension::k1d: + return 1; + case core::type::TextureDimension::k2d: + case core::type::TextureDimension::k2dArray: + return 2; + case core::type::TextureDimension::k3d: + case core::type::TextureDimension::kCube: + case core::type::TextureDimension::kCubeArray: + return 3; + } + return 0; +} + +uint32_t Texture::Align() const { + return 1; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/texture.h b/3rdparty/dawn/src/tint/lang/core/type/texture.h new file mode 100644 index 000000000..1cf6915cb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/texture.h @@ -0,0 +1,76 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_TEXTURE_H_ +#define SRC_TINT_LANG_CORE_TYPE_TEXTURE_H_ + +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A texture type. +class Texture : public Castable { + public: + /// Constructor + /// @param hash the unique hash of the node + /// @param dim the dimensionality of the texture + Texture(size_t hash, TextureDimension dim); + /// Destructor + ~Texture() override; + + /// @returns the texture dimension + TextureDimension Dim() const { return dim_; } + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + private: + TextureDimension const dim_; +}; + +/// @param dim the type::TextureDimension to query +/// @return true if the given type::TextureDimension is an array texture +bool IsTextureArray(core::type::TextureDimension dim); + +/// Returns the number of axes in the coordinate used for accessing +/// the texture, where an access is one of: sampling, fetching, load, +/// or store. +/// None -> 0 +/// 1D -> 1 +/// 2D, 2DArray -> 2 +/// 3D, Cube, CubeArray -> 3 +/// Note: To sample a cube texture, the coordinate has 3 dimensions, +/// but textureDimensions on a cube or cube array returns a 2-element +/// size, representing the (x,y) size of each cube face, in texels. +/// @param dim the type::TextureDimension to query +/// @return number of dimensions in a coordinate for the dimensionality +int NumCoordinateAxes(core::type::TextureDimension dim); + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/texture_dimension.cc b/3rdparty/dawn/src/tint/lang/core/type/texture_dimension.cc new file mode 100644 index 000000000..3371c1e1f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/texture_dimension.cc @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/texture_dimension.h" + +namespace tint::core::type { + +std::string_view ToString(core::type::TextureDimension dim) { + switch (dim) { + case core::type::TextureDimension::kNone: + return "none"; + case core::type::TextureDimension::k1d: + return "1d"; + case core::type::TextureDimension::k2d: + return "2d"; + case core::type::TextureDimension::k2dArray: + return "2d_array"; + case core::type::TextureDimension::k3d: + return "3d"; + case core::type::TextureDimension::kCube: + return "cube"; + case core::type::TextureDimension::kCubeArray: + return "cube_array"; + } + return ""; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/texture_dimension.h b/3rdparty/dawn/src/tint/lang/core/type/texture_dimension.h new file mode 100644 index 000000000..0fb37b731 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/texture_dimension.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_TEXTURE_DIMENSION_H_ +#define SRC_TINT_LANG_CORE_TYPE_TEXTURE_DIMENSION_H_ + +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::core::type { + +/// The dimensionality of the texture +enum class TextureDimension : uint8_t { + /// 1 dimensional texture + k1d, + /// 2 dimensional texture + k2d, + /// 2 dimensional array texture + k2dArray, + /// 3 dimensional texture + k3d, + /// cube texture + kCube, + /// cube array texture + kCubeArray, + /// Invalid texture + kNone, +}; + +/// @param dim the enum value +/// @returns the string for the given enum value +std::string_view ToString(enum type::TextureDimension dim); + +/// @param out the stream to write to +/// @param dim the type::TextureDimension +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, core::type::TextureDimension dim) { + return out << ToString(dim); +} + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_TEXTURE_DIMENSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/type.cc b/3rdparty/dawn/src/tint/lang/core/type/type.cc new file mode 100644 index 000000000..5b3d7724d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/type.cc @@ -0,0 +1,299 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/type.h" + +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/texel_buffer.h" +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/u64.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/rtti/switch.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Type); + +namespace tint::core::type { + +Type::Type(size_t hash, core::type::Flags flags) : Base(hash), flags_(flags) { + if (IsConstructible()) { + TINT_ASSERT(HasCreationFixedFootprint()); + } +} + +Type::~Type() = default; + +const Type* Type::UnwrapPtr() const { + auto* type = this; + while (auto* ptr = type->As()) { + type = ptr->StoreType(); + } + return type; +} + +const Type* Type::UnwrapRef() const { + auto* type = this; + if (auto* ref = type->As()) { + type = ref->StoreType(); + } + return type; +} + +const Type* Type::UnwrapPtrOrRef() const { + auto* type = UnwrapPtr(); + if (type != this) { + return type; + } + return UnwrapRef(); +} + +uint32_t Type::Size() const { + return 0; +} + +uint32_t Type::Align() const { + return 0; +} + +bool Type::IsScalar() const { + return IsFloatScalar() || IsIntegerScalar() || IsAnyOf(); +} + +bool Type::IsFloatScalar() const { + return IsAnyOf(); +} + +bool Type::IsFloatMatrix() const { + return Is([](const Matrix* m) { return m->Type()->IsFloatScalar(); }); +} + +bool Type::IsFloatVector() const { + return Is([](const Vector* v) { return v->Type()->IsFloatScalar(); }); +} + +bool Type::IsFloatScalarOrVector() const { + return IsFloatScalar() || IsFloatVector(); +} + +bool Type::IsIntegerScalar() const { + return IsAnyOf(); +} + +bool Type::IsIntegerVector() const { + return Is([](const Vector* v) { return v->Type()->IsIntegerScalar(); }); +} + +bool Type::IsSignedIntegerScalar() const { + return IsAnyOf(); +} + +bool Type::IsUnsignedIntegerScalar() const { + return IsAnyOf(); +} + +bool Type::IsSignedIntegerVector() const { + return Is([](const Vector* v) { return v->Type()->IsSignedIntegerScalar(); }); +} + +bool Type::IsUnsignedIntegerVector() const { + return Is([](const Vector* v) { return v->Type()->IsUnsignedIntegerScalar(); }); +} + +bool Type::IsUnsignedIntegerScalarOrVector() const { + return IsUnsignedIntegerScalar() || IsUnsignedIntegerVector(); +} + +bool Type::IsSignedIntegerScalarOrVector() const { + return IsSignedIntegerScalar() || IsSignedIntegerVector(); +} + +bool Type::IsIntegerScalarOrVector() const { + return IsUnsignedIntegerScalarOrVector() || IsSignedIntegerScalarOrVector(); +} + +bool Type::IsAbstractScalarOrVector() const { + return Is() || Is([](const Vector* v) { return v->Type()->Is(); }); +} + +bool Type::IsBoolVector() const { + return Is([](const Vector* v) { return v->Type()->Is(); }); +} + +bool Type::IsBoolScalarOrVector() const { + return Is() || IsBoolVector(); +} + +bool Type::IsNumericScalarOrVector() const { + return Is() || + Is([](const Vector* v) { return v->Type()->Is(); }); +} + +bool Type::IsHandle() const { + if (IsAnyOf()) { + return true; + } + if (auto* binding_array = As()) { + return binding_array->ElemType()->IsHandle(); + } + return false; +} + +bool Type::IsAbstract() const { + return Switch( + this, // + [&](const AbstractNumeric*) { return true; }, + [&](const Vector* v) { return v->Type()->IsAbstract(); }, + [&](const Matrix* m) { return m->Type()->IsAbstract(); }, + [&](const Array* a) { return a->ElemType()->IsAbstract(); }, + [&](const Struct* s) { + for (auto* m : s->Members()) { + if (m->Type()->IsAbstract()) { + return true; + } + } + return false; + }); +} + +uint32_t Type::ConversionRank(const Type* from, const Type* to) { + if (from->UnwrapRef() == to) { + return 0; + } + return Switch( + from, + [&](const AbstractFloat*) { + return Switch( + to, // + [&](const F32*) { return 1; }, // + [&](const F16*) { return 2; }, // + [&](Default) { return kNoConversion; }); + }, + [&](const AbstractInt*) { + return Switch( + to, // + [&](const I32*) { return 3; }, // + [&](const U32*) { return 4; }, // + [&](const AbstractFloat*) { return 5; }, // + [&](const F32*) { return 6; }, // + [&](const F16*) { return 7; }, // + [&](Default) { return kNoConversion; }); + }, + [&](const Vector* from_vec) { + if (auto* to_vec = to->As()) { + if (from_vec->Width() == to_vec->Width()) { + return ConversionRank(from_vec->Type(), to_vec->Type()); + } + } + return kNoConversion; + }, + [&](const Matrix* from_mat) { + if (auto* to_mat = to->As()) { + if (from_mat->Columns() == to_mat->Columns() && + from_mat->Rows() == to_mat->Rows()) { + return ConversionRank(from_mat->Type(), to_mat->Type()); + } + } + return kNoConversion; + }, + [&](const Array* from_arr) { + if (auto* to_arr = to->As()) { + if (from_arr->Count() == to_arr->Count()) { + return ConversionRank(from_arr->ElemType(), to_arr->ElemType()); + } + } + return kNoConversion; + }, + [&](const Struct* from_str) { + auto concrete_tys = from_str->ConcreteTypes(); + for (size_t i = 0; i < concrete_tys.Length(); i++) { + if (concrete_tys[i] == to) { + return static_cast(i + 1); + } + } + return kNoConversion; + }, + [&](Default) { return kNoConversion; }); +} + +TypeAndCount Type::Elements(const Type* type_if_invalid /* = nullptr */, + uint32_t count_if_invalid /* = 0 */) const { + return {type_if_invalid, count_if_invalid}; +} + +const Type* Type::Element(uint32_t /* index */) const { + return nullptr; +} + +const Type* Type::DeepestElement() const { + const Type* ty = this; + while (true) { + auto [el, n] = ty->Elements(); + if (!el) { + return ty; + } + ty = el; + } +} + +const Type* Type::Common(VectorRef types) { + const auto count = types.Length(); + if (count == 0) { + return nullptr; + } + const auto* common = types[0]; + for (size_t i = 1; i < count; i++) { + auto* ty = types[i]; + if (ty == common) { + continue; // ty == common + } + if (Type::ConversionRank(ty, common) != Type::kNoConversion) { + continue; // ty can be converted to common. + } + if (Type::ConversionRank(common, ty) != Type::kNoConversion) { + common = ty; // common can be converted to ty. + continue; + } + return nullptr; // Conversion is not valid. + } + return common; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/type.h b/3rdparty/dawn/src/tint/lang/core/type/type.h new file mode 100644 index 000000000..e5c1d947e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/type.h @@ -0,0 +1,274 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_TYPE_H_ +#define SRC_TINT_LANG_CORE_TYPE_TYPE_H_ + +#include +#include + +#include "src/tint/lang/core/type/clone_context.h" +#include "src/tint/lang/core/type/unique_node.h" +#include "src/tint/utils/containers/enum_set.h" +#include "src/tint/utils/containers/vector.h" + +// Forward declarations +namespace tint { +class ProgramBuilder; +class SymbolTable; +} // namespace tint +namespace tint::core::type { +class Type; +} // namespace tint::core::type + +namespace tint::core::type { + +/// Flag is an enumerator of type flag bits, used by Flags. +enum Flag { + /// Type is constructable. + /// @see https://gpuweb.github.io/gpuweb/wgsl/#constructible-types + kConstructable, + /// Type has a creation-fixed footprint. + /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types + kCreationFixedFootprint, + /// Type has a fixed footprint. + /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types + kFixedFootprint, + /// Type is host-shareable. + /// @see https://www.w3.org/TR/WGSL/#host-shareable + kHostShareable, +}; + +/// An alias to tint::EnumSet +using Flags = tint::EnumSet; + +/// TypeAndCount holds a type and count +struct TypeAndCount { + /// The type + const Type* type = nullptr; + /// The count + uint32_t count = 0; +}; + +/// Equality operator. +/// @param lhs the LHS TypeAndCount +/// @param rhs the RHS TypeAndCount +/// @returns true if the two TypeAndCounts have the same type and count +inline bool operator==(TypeAndCount lhs, TypeAndCount rhs) { + return lhs.type == rhs.type && lhs.count == rhs.count; +} + +/// Base class for a type in the system +class Type : public Castable { + public: + /// Destructor + ~Type() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + virtual std::string FriendlyName() const = 0; + + /// @returns the inner most pointee type if this is a pointer, `this` + /// otherwise + const Type* UnwrapPtr() const; + + /// @returns the inner type if this is a reference, `this` otherwise + const Type* UnwrapRef() const; + + /// @returns the inner type if this is a pointer or a reference, `this` otherwise + const Type* UnwrapPtrOrRef() const; + + /// @returns the size in bytes of the type. This may include tail padding. + /// @note opaque types will return a size of 0. + virtual uint32_t Size() const; + + /// @returns the alignment in bytes of the type. This may include tail + /// padding. + /// @note opaque types will return a size of 0. + virtual uint32_t Align() const; + + /// @param ctx the clone context + /// @returns a clone of this type created in the provided context + virtual Type* Clone(CloneContext& ctx) const = 0; + + /// @returns the flags on the type + core::type::Flags Flags() { return flags_; } + + /// @returns true if type is constructable + /// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types + inline bool IsConstructible() const { return flags_.Contains(Flag::kConstructable); } + + /// @returns true has a creation-fixed footprint. + /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types + inline bool HasCreationFixedFootprint() const { + return flags_.Contains(Flag::kCreationFixedFootprint); + } + + /// @returns true has a fixed footprint. + /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types + inline bool HasFixedFootprint() const { return flags_.Contains(Flag::kFixedFootprint); } + + /// @returns true if type is host-shareable + /// https://www.w3.org/TR/WGSL/#host-shareable + inline bool IsHostShareable() const { return flags_.Contains(Flag::kHostShareable); } + + /// @returns true if the type is a scalar + bool IsScalar() const; + /// @returns true if this type is a float scalar + bool IsFloatScalar() const; + /// @returns true if this type is a float matrix + bool IsFloatMatrix() const; + /// @returns true if this type is a float vector + bool IsFloatVector() const; + /// @returns true if this type is a float scalar or vector + bool IsFloatScalarOrVector() const; + /// @returns true if this type is an integer scalar + bool IsIntegerScalar() const; + /// @returns true if this type is a integer vector + bool IsIntegerVector() const; + /// @returns true if this type is an integer scalar or vector + bool IsIntegerScalarOrVector() const; + /// @returns true if this type is a signed integer scalar + bool IsSignedIntegerScalar() const; + /// @returns true if this type is a signed integer vector + bool IsSignedIntegerVector() const; + /// @returns true if this type is a signed scalar or vector + bool IsSignedIntegerScalarOrVector() const; + /// @returns true if this type is an unsigned integer scalar + bool IsUnsignedIntegerScalar() const; + /// @returns true if this type is an unsigned vector + bool IsUnsignedIntegerVector() const; + /// @returns true if this type is an unsigned scalar or vector + bool IsUnsignedIntegerScalarOrVector() const; + /// @returns true if this type is an abstract integer scalar or vector + bool IsAbstractScalarOrVector() const; + /// @returns true if this type is boolean scalar or vector + bool IsBoolScalarOrVector() const; + /// @returns true if this type is boolean vector + bool IsBoolVector() const; + /// @returns true if this type is a numeric scale or vector + bool IsNumericScalarOrVector() const; + /// @returns true if this type is a handle type + virtual bool IsHandle() const; + /// @returns true if this type is an abstract type. It could be a numeric directly or an + /// abstract container which holds an abstract numeric + bool IsAbstract() const; + + /// kNoConversion is returned from ConversionRank() when the implicit conversion is not + /// permitted. + static constexpr uint32_t kNoConversion = 0xffffffffu; + + /// ConversionRank returns the implicit conversion rank when attempting to convert `from` to + /// `to`. Lower ranks are preferred over higher ranks. + /// @param from the source type + /// @param to the destination type + /// @returns the rank value for converting from type `from` to type `to`, or #kNoConversion if + /// the implicit conversion is not allowed. + /// @see https://www.w3.org/TR/WGSL/#conversion-rank + static uint32_t ConversionRank(const Type* from, const Type* to); + + /// @param type_if_invalid the type to return if this type has no child elements. + /// @param count_if_invalid the count to return if this type has no child elements, or the + /// number is unbounded. + /// @returns The child element type and the number of child elements held by this type. + /// If this type has no child element types, then @p invalid is returned. + /// If this type can hold a mix of different elements types (like a Struct), then + /// `[type_if_invalid, N]` is returned, where `N` is the number of elements. + /// If this type is unbounded in size (e.g. runtime sized arrays), then the returned count will + /// equal `count_if_invalid`. + /// + /// Examples: + /// * Elements() of `array, 5>` returns `[vec3, 5]`. + /// * Elements() of `array` returns `[f32, count_if_invalid]`. + /// * Elements() of `struct S { a : f32, b : i32 }` returns `[count_if_invalid, 2]`. + /// * Elements() of `struct S { a : i32, b : i32 }` also returns `[count_if_invalid, 2]`. + virtual TypeAndCount Elements(const Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const; + + /// @param index the i'th element index to return + /// @returns The child element with the given index, or nullptr if the element does not exist. + /// + /// Examples: + /// * Element(1) of `mat3x2` returns `vec2`. + /// * Element(1) of `array, 5>` returns `vec3`. + /// * Element(0) of `struct S { a : f32, b : i32 }` returns `f32`. + /// * Element(0) of `f32` returns `nullptr`. + /// * Element(3) of `vec3` returns `nullptr`. + /// * Element(3) of `struct S { a : f32, b : i32 }` returns `nullptr`. + virtual const Type* Element(uint32_t index) const; + + /// @returns the most deeply nested element of the type. For non-composite types, + /// DeepestElement() will return this type. Examples: + /// * Element() of `f32` returns `f32`. + /// * Element() of `vec3` returns `f32`. + /// * Element() of `mat3x2` returns `f32`. + /// * Element() of `array, 5>` returns `f32`. + /// * Element() of `struct S { a : f32, b : i32 }` returns `S`. + const Type* DeepestElement() const; + + /// @param types the list of types + /// @returns the lowest-ranking type that all types in `types` can be implicitly converted to, + /// or nullptr if there is no consistent common type across all types in `types`. + /// @see https://www.w3.org/TR/WGSL/#conversion-rank + static const Type* Common(VectorRef types); + + protected: + /// Constructor + /// @param hash the immutable hash for the node + /// @param flags the flags of this type + Type(size_t hash, core::type::Flags flags); + + /// The flags of this type. + const core::type::Flags flags_; +}; + +} // namespace tint::core::type + +namespace std { + +/// std::hash specialization for tint::core::type::Type +template <> +struct hash { + /// @param type the type to obtain a hash from + /// @returns the hash of the type + size_t operator()(const tint::core::type::Type& type) const { return type.unique_hash; } +}; + +/// std::equal_to specialization for tint::core::type::Type +template <> +struct equal_to { + /// @param a the first type to compare + /// @param b the second type to compare + /// @returns true if the two types are equal + bool operator()(const tint::core::type::Type& a, const tint::core::type::Type& b) const { + return a.Equals(b); + } +}; + +} // namespace std + +#endif // SRC_TINT_LANG_CORE_TYPE_TYPE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/u32.cc b/3rdparty/dawn/src/tint/lang/core/type/u32.cc new file mode 100644 index 000000000..c1b2910e5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/u32.cc @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/u32.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::U32); + +namespace tint::core::type { + +U32::U32() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + Flag::kHostShareable, + }) {} + +U32::~U32() = default; + +std::string U32::FriendlyName() const { + return "u32"; +} + +uint32_t U32::Size() const { + return 4; +} + +uint32_t U32::Align() const { + return 4; +} + +U32* U32::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/u32.h b/3rdparty/dawn/src/tint/lang/core/type/u32.h new file mode 100644 index 000000000..e83065961 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/u32.h @@ -0,0 +1,63 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_U32_H_ +#define SRC_TINT_LANG_CORE_TYPE_U32_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// A unsigned int 32 type. +class U32 final : public Castable { + public: + /// Constructor + U32(); + + /// Destructor + ~U32() override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the size in bytes of the type. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + U32* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_U32_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/u64.cc b/3rdparty/dawn/src/tint/lang/core/type/u64.cc new file mode 100644 index 000000000..cffb24822 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/u64.cc @@ -0,0 +1,50 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/u64.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::U64); + +namespace tint::core::type { + +U64::U64() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }) {} + +U64::~U64() = default; + +U64* U64::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/u64.h b/3rdparty/dawn/src/tint/lang/core/type/u64.h new file mode 100644 index 000000000..474bd22ad --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/u64.h @@ -0,0 +1,62 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_U64_H_ +#define SRC_TINT_LANG_CORE_TYPE_U64_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// An unsigned 64-bit integer type. +class U64 final : public Castable { + public: + /// Constructor + U64(); + + /// Destructor + ~U64() override; + + /// @returns the name for this type that closely resembles how it would be declared in WGSL. + std::string FriendlyName() const override { return "u64"; } + + /// @returns the size in bytes of the type. + uint32_t Size() const override { return 8; } + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override { return 8; } + + /// @param ctx the clone context + /// @returns a clone of this type + U64* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_U64_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/u8.cc b/3rdparty/dawn/src/tint/lang/core/type/u8.cc new file mode 100644 index 000000000..36dd4cd1f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/u8.cc @@ -0,0 +1,50 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/u8.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::U8); + +namespace tint::core::type { + +U8::U8() + : Base(static_cast(tint::TypeCode::Of().bits), + core::type::Flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }) {} + +U8::~U8() = default; + +U8* U8::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/u8.h b/3rdparty/dawn/src/tint/lang/core/type/u8.h new file mode 100644 index 000000000..ea94b3890 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/u8.h @@ -0,0 +1,62 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_U8_H_ +#define SRC_TINT_LANG_CORE_TYPE_U8_H_ + +#include + +#include "src/tint/lang/core/type/numeric_scalar.h" + +namespace tint::core::type { + +/// An unsigned 8-bit integer type. +class U8 final : public Castable { + public: + /// Constructor + U8(); + + /// Destructor + ~U8() override; + + /// @returns the name for this type that closely resembles how it would be declared in WGSL. + std::string FriendlyName() const override { return "u8"; } + + /// @returns the size in bytes of the type. + uint32_t Size() const override { return 1; } + + /// @returns the alignment in bytes of the type. + uint32_t Align() const override { return 1; } + + /// @param ctx the clone context + /// @returns a clone of this type + U8* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_U8_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/unique_node.cc b/3rdparty/dawn/src/tint/lang/core/type/unique_node.cc new file mode 100644 index 000000000..2ff0e1020 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/unique_node.cc @@ -0,0 +1,36 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/unique_node.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::UniqueNode); + +namespace tint::core::type { + +UniqueNode::~UniqueNode() = default; + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/unique_node.h b/3rdparty/dawn/src/tint/lang/core/type/unique_node.h new file mode 100644 index 000000000..d16d032ec --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/unique_node.h @@ -0,0 +1,84 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_UNIQUE_NODE_H_ +#define SRC_TINT_LANG_CORE_TYPE_UNIQUE_NODE_H_ + +#include + +#include "src/tint/lang/core/type/node.h" + +namespace tint::core::type { + +/// UniqueNode is the base class for objects that are de-duplicated by the Manager. +/// Deduplication is achieved by comparing a temporary object to the set of existing objects, using +/// Hash() and Equals(). If an existing object is found, then the pointer to that object is +/// returned, otherwise a new object is constructed, added to the Manager's set and returned. +class UniqueNode : public Castable { + public: + /// Constructor + /// @param hash the immutable hash for the node + inline explicit UniqueNode(size_t hash) : unique_hash(hash) {} + + /// Destructor + ~UniqueNode() override; + + /// @param other the other node to compare this node against + /// @returns true if the this node is equal to @p other + virtual bool Equals(const UniqueNode& other) const = 0; + + /// the immutable hash for the node + const size_t unique_hash; +}; + +} // namespace tint::core::type + +namespace std { + +/// std::hash specialization for tint::core::type::UniqueNode +template <> +struct hash { + /// @param node the unique node to obtain a hash from + /// @returns the hash of the node + size_t operator()(const tint::core::type::UniqueNode& node) const { return node.unique_hash; } +}; + +/// std::equal_to specialization for tint::core::type::UniqueNode +template <> +struct equal_to { + /// @param a the first unique node to compare + /// @param b the second unique node to compare + /// @returns true if the two nodes are equal + bool operator()(const tint::core::type::UniqueNode& a, + const tint::core::type::UniqueNode& b) const { + return &a == &b || a.Equals(b); + } +}; + +} // namespace std + +#endif // SRC_TINT_LANG_CORE_TYPE_UNIQUE_NODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/vector.cc b/3rdparty/dawn/src/tint/lang/core/type/vector.cc new file mode 100644 index 000000000..5662735e8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/vector.cc @@ -0,0 +1,113 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/vector.h" + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Vector); + +namespace tint::core::type { + +namespace { + +core::type::Flags FlagsFrom(const Type* element) { + core::type::Flags flags{ + Flag::kConstructable, + Flag::kCreationFixedFootprint, + Flag::kFixedFootprint, + }; + if (element->IsHostShareable()) { + flags.Add(Flag::kHostShareable); + } + return flags; +} + +} // namespace + +Vector::Vector(type::Type const* subtype, uint32_t width, bool packed /* = false */) + : Base(Hash(tint::TypeCode::Of().bits, width, subtype, packed), FlagsFrom(subtype)), + subtype_(subtype), + width_(width), + packed_(packed) { + TINT_ASSERT(width_ > 1); + TINT_ASSERT(width_ < 5); +} + +Vector::~Vector() = default; + +bool Vector::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return v->width_ == width_ && v->subtype_ == subtype_ && v->packed_ == packed_; + } + return false; +} + +std::string Vector::FriendlyName() const { + StringStream out; + if (packed_) { + out << "__packed_"; + } + out << "vec" << width_ << "<" << subtype_->FriendlyName() << ">"; + return out.str(); +} + +uint32_t Vector::Size() const { + return subtype_->Size() * width_; +} + +uint32_t Vector::Align() const { + switch (width_) { + case 2: + return subtype_->Size() * 2; + case 3: + return subtype_->Size() * (packed_ ? 1 : 4); + case 4: + return subtype_->Size() * 4; + } + return 0; // Unreachable +} + +Vector* Vector::Clone(CloneContext& ctx) const { + auto* subtype = subtype_->Clone(ctx); + return ctx.dst.mgr->Get(subtype, width_, packed_); +} + +TypeAndCount Vector::Elements(const type::Type* /* type_if_invalid = nullptr */, + uint32_t /* count_if_invalid = 0 */) const { + return {subtype_, width_}; +} + +const Type* Vector::Element(uint32_t index) const { + return index < width_ ? subtype_ : nullptr; +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/vector.h b/3rdparty/dawn/src/tint/lang/core/type/vector.h new file mode 100644 index 000000000..e84109cca --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/vector.h @@ -0,0 +1,99 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_VECTOR_H_ +#define SRC_TINT_LANG_CORE_TYPE_VECTOR_H_ + +#include + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A vector type. +class Vector : public Castable { + public: + /// Constructor + /// @param subtype the vector element type + /// @param size the number of elements in the vector + /// @param packed the optional 'packed' modifier + Vector(Type const* subtype, uint32_t size, bool packed = false); + + /// Destructor + ~Vector() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the type of the vector elements + const type::Type* Type() const { return subtype_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @returns the number of elements in the vector + uint32_t Width() const { return width_; } + + /// @returns the size in bytes of the type. This may include tail padding. + uint32_t Size() const override; + + /// @returns the alignment in bytes of the type. This may include tail padding. + uint32_t Align() const override; + + /// @returns `true` if this vector is packed, false otherwise + bool Packed() const { return packed_; } + + /// @param width the width of the vector + /// @returns the size in bytes of a vector of the given width. + static uint32_t SizeOf(uint32_t width); + + /// @param width the width of the vector + /// @returns the alignment in bytes of a vector of the given width. + static uint32_t AlignOf(uint32_t width); + + /// @copydoc Type::Elements + TypeAndCount Elements(const type::Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc Type::Element + const type::Type* Element(uint32_t index) const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Vector* Clone(CloneContext& ctx) const override; + + private: + type::Type const* const subtype_; + const uint32_t width_; + const bool packed_; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_VECTOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/type/void.cc b/3rdparty/dawn/src/tint/lang/core/type/void.cc new file mode 100644 index 000000000..7e1fbf21c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/void.cc @@ -0,0 +1,52 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/type/void.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::core::type::Void); + +namespace tint::core::type { + +Void::Void() : Base(static_cast(tint::TypeCode::Of().bits), core::type::Flags{}) {} + +Void::~Void() = default; + +bool Void::Equals(const UniqueNode& other) const { + return other.Is(); +} + +std::string Void::FriendlyName() const { + return "void"; +} + +Void* Void::Clone(CloneContext& ctx) const { + return ctx.dst.mgr->Get(); +} + +} // namespace tint::core::type diff --git a/3rdparty/dawn/src/tint/lang/core/type/void.h b/3rdparty/dawn/src/tint/lang/core/type/void.h new file mode 100644 index 000000000..024a45802 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/type/void.h @@ -0,0 +1,61 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_TYPE_VOID_H_ +#define SRC_TINT_LANG_CORE_TYPE_VOID_H_ + +#include + +#include "src/tint/lang/core/type/type.h" + +namespace tint::core::type { + +/// A void type +class Void final : public Castable { + public: + /// Constructor + Void(); + + /// Destructor + ~Void() override; + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + Void* Clone(CloneContext& ctx) const override; +}; + +} // namespace tint::core::type + +#endif // SRC_TINT_LANG_CORE_TYPE_VOID_H_ diff --git a/3rdparty/dawn/src/tint/lang/core/unary_op.cc b/3rdparty/dawn/src/tint/lang/core/unary_op.cc new file mode 100644 index 000000000..4744f2b15 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/unary_op.cc @@ -0,0 +1,47 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/core/unary_op.h" + +namespace tint::core { + +std::string_view ToString(UnaryOp value) { + switch (value) { + case UnaryOp::kAddressOf: + return "&"; + case UnaryOp::kComplement: + return "~"; + case UnaryOp::kIndirection: + return "*"; + case UnaryOp::kNegation: + return "-"; + case UnaryOp::kNot: + return "!"; + } + return ""; +} +} // namespace tint::core diff --git a/3rdparty/dawn/src/tint/lang/core/unary_op.h b/3rdparty/dawn/src/tint/lang/core/unary_op.h new file mode 100644 index 000000000..b1bab65fb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/core/unary_op.h @@ -0,0 +1,60 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_CORE_UNARY_OP_H_ +#define SRC_TINT_LANG_CORE_UNARY_OP_H_ + +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::core { + +/// The unary op +enum class UnaryOp { + kAddressOf, // &EXPR + kComplement, // ~EXPR + kIndirection, // *EXPR + kNegation, // -EXPR + kNot, // !EXPR +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(UnaryOp value); + +/// @param out the stream to write to +/// @param value the UnaryOp +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, UnaryOp value) { + return out << ToString(value); +} + +} // namespace tint::core + +#endif // SRC_TINT_LANG_CORE_UNARY_OP_H_ diff --git a/3rdparty/dawn/src/tint/lang/null/writer/common/options.cc b/3rdparty/dawn/src/tint/lang/null/writer/common/options.cc new file mode 100644 index 000000000..203b7e377 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/common/options.cc @@ -0,0 +1,40 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/null/writer/common/options.h" + +namespace tint::null::writer { + +Options::Options() = default; + +Options::~Options() = default; + +Options::Options(const Options&) = default; + +Options& Options::operator=(const Options&) = default; + +} // namespace tint::null::writer diff --git a/3rdparty/dawn/src/tint/lang/null/writer/common/options.h b/3rdparty/dawn/src/tint/lang/null/writer/common/options.h new file mode 100644 index 000000000..b3d9f0dea --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/common/options.h @@ -0,0 +1,64 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_NULL_WRITER_COMMON_OPTIONS_H_ +#define SRC_TINT_LANG_NULL_WRITER_COMMON_OPTIONS_H_ + +#include + +#include "src/tint/api/common/substitute_overrides_config.h" +#include "src/tint/utils/reflection.h" + +namespace tint::null::writer { + +/// Configuration options used for Null generator. +struct Options { + /// Constructor + Options(); + /// Destructor + ~Options(); + /// Copy constructor + Options(const Options&); + /// Copy assignment + /// @returns this Options + Options& operator=(const Options&); + + /// The entry point name to emit + std::string entry_point_name = {}; + + // Substitute Overrides + SubstituteOverridesConfig substitute_overrides_config = {}; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(Options, entry_point_name, substitute_overrides_config); + TINT_REFLECT_EQUALS(Options); + TINT_REFLECT_HASH_CODE(Options); +}; + +} // namespace tint::null::writer + +#endif // SRC_TINT_LANG_NULL_WRITER_COMMON_OPTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/null/writer/common/output.cc b/3rdparty/dawn/src/tint/lang/null/writer/common/output.cc new file mode 100644 index 000000000..d8c0b825d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/common/output.cc @@ -0,0 +1,40 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/null/writer/common/output.h" + +namespace tint::null::writer { + +Output::Output() = default; + +Output::~Output() = default; + +Output::Output(const Output&) = default; + +Output& Output::operator=(const Output&) = default; + +} // namespace tint::null::writer diff --git a/3rdparty/dawn/src/tint/lang/null/writer/common/output.h b/3rdparty/dawn/src/tint/lang/null/writer/common/output.h new file mode 100644 index 000000000..90f5b7ded --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/common/output.h @@ -0,0 +1,70 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_NULL_WRITER_COMMON_OUTPUT_H_ +#define SRC_TINT_LANG_NULL_WRITER_COMMON_OUTPUT_H_ + +#include +#include + +namespace tint::null::writer { + +/// The output produced by Null writer +struct Output { + /// Constructor + Output(); + + /// Destructor + ~Output(); + + /// Copy constructor + Output(const Output&); + + /// Copy assignment + /// @returns this + Output& operator=(const Output&); + + /// Workgroup size information + struct WorkgroupInfo { + /// The x-component + uint32_t x = 0; + /// The y-component + uint32_t y = 0; + /// The z-component + uint32_t z = 0; + + /// The needed workgroup storage size + size_t storage_size = 0; + }; + + /// The workgroup size information, if the entry point was a compute shader + WorkgroupInfo workgroup_info{}; +}; + +} // namespace tint::null::writer + +#endif // SRC_TINT_LANG_NULL_WRITER_COMMON_OUTPUT_H_ diff --git a/3rdparty/dawn/src/tint/lang/null/writer/raise/raise.cc b/3rdparty/dawn/src/tint/lang/null/writer/raise/raise.cc new file mode 100644 index 000000000..7e95ce0eb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/raise/raise.cc @@ -0,0 +1,43 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/null/writer/raise/raise.h" + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/transform/single_entry_point.h" +#include "src/tint/lang/core/ir/transform/substitute_overrides.h" + +namespace tint::null::writer { + +Result Raise(core::ir::Module& module, const Options& options) { + TINT_CHECK_RESULT(core::ir::transform::SingleEntryPoint(module, options.entry_point_name)); + TINT_CHECK_RESULT( + core::ir::transform::SubstituteOverrides(module, options.substitute_overrides_config)); + return Success; +} + +} // namespace tint::null::writer diff --git a/3rdparty/dawn/src/tint/lang/null/writer/raise/raise.h b/3rdparty/dawn/src/tint/lang/null/writer/raise/raise.h new file mode 100644 index 000000000..c166764ea --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/raise/raise.h @@ -0,0 +1,49 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_NULL_WRITER_RAISE_RAISE_H_ +#define SRC_TINT_LANG_NULL_WRITER_RAISE_RAISE_H_ + +#include "src/tint/lang/null/writer/common/options.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::null::writer { + +/// Run the `Raise` transform of an IR module for the Null backend. +/// @param module the core IR module to raise to Null dialect +/// @param options the printer options +/// @returns success or failure +Result Raise(core::ir::Module& module, const Options& options); + +} // namespace tint::null::writer + +#endif // SRC_TINT_LANG_NULL_WRITER_RAISE_RAISE_H_ diff --git a/3rdparty/dawn/src/tint/lang/null/writer/writer.cc b/3rdparty/dawn/src/tint/lang/null/writer/writer.cc new file mode 100644 index 000000000..980f3046c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/writer.cc @@ -0,0 +1,54 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/null/writer/writer.h" + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/reflection.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/null/writer/raise/raise.h" + +namespace tint::null::writer { + +Result Generate(core::ir::Module& ir, const Options& options) { + Output output; + + // Raise from core-dialect + TINT_CHECK_RESULT(Raise(ir, options)); + + TINT_CHECK_RESULT_UNWRAP(wg_info, GetWorkgroupInfo(ir)); + output.workgroup_info = { + .x = wg_info.x, + .y = wg_info.y, + .z = wg_info.z, + .storage_size = wg_info.storage_size, + }; + + return output; +} + +} // namespace tint::null::writer diff --git a/3rdparty/dawn/src/tint/lang/null/writer/writer.h b/3rdparty/dawn/src/tint/lang/null/writer/writer.h new file mode 100644 index 000000000..f6011c6b1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/null/writer/writer.h @@ -0,0 +1,51 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_NULL_WRITER_WRITER_H_ +#define SRC_TINT_LANG_NULL_WRITER_WRITER_H_ + +#include "src/tint/lang/null/writer/common/options.h" +#include "src/tint/lang/null/writer/common/output.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::null::writer { + +/// Run generator for the Null backend, according to a set of configuration options. +/// The result will contain the supplementary information, or failure. +/// @param ir the IR module +/// @param options the configuration options to use +/// @returns the supplementary information, or failure +Result Generate(core::ir::Module& ir, const Options& options); + +} // namespace tint::null::writer + +#endif // SRC_TINT_LANG_NULL_WRITER_WRITER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/builtin_fn.cc b/3rdparty/dawn/src/tint/lang/spirv/builtin_fn.cc new file mode 100644 index 000000000..180f0fab4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/builtin_fn.cc @@ -0,0 +1,397 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/spirv/builtin_fn.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include "src/tint/lang/spirv/builtin_fn.h" + +namespace tint::spirv { + +const char* str(BuiltinFn i) { + switch (i) { + case BuiltinFn::kNone: + return ""; + case BuiltinFn::kArrayLength: + return "array_length"; + case BuiltinFn::kAtomicLoad: + return "atomic_load"; + case BuiltinFn::kAtomicStore: + return "atomic_store"; + case BuiltinFn::kAtomicExchange: + return "atomic_exchange"; + case BuiltinFn::kAtomicCompareExchange: + return "atomic_compare_exchange"; + case BuiltinFn::kAtomicIAdd: + return "atomic_i_add"; + case BuiltinFn::kAtomicISub: + return "atomic_i_sub"; + case BuiltinFn::kAtomicSMax: + return "atomic_s_max"; + case BuiltinFn::kAtomicSMin: + return "atomic_s_min"; + case BuiltinFn::kAtomicUMax: + return "atomic_u_max"; + case BuiltinFn::kAtomicUMin: + return "atomic_u_min"; + case BuiltinFn::kAtomicAnd: + return "atomic_and"; + case BuiltinFn::kAtomicOr: + return "atomic_or"; + case BuiltinFn::kAtomicXor: + return "atomic_xor"; + case BuiltinFn::kAtomicIIncrement: + return "atomic_i_increment"; + case BuiltinFn::kAtomicIDecrement: + return "atomic_i_decrement"; + case BuiltinFn::kDot: + return "dot"; + case BuiltinFn::kImageDrefGather: + return "image_dref_gather"; + case BuiltinFn::kImageFetch: + return "image_fetch"; + case BuiltinFn::kImageGather: + return "image_gather"; + case BuiltinFn::kImageQuerySize: + return "image_query_size"; + case BuiltinFn::kImageQuerySizeLod: + return "image_query_size_lod"; + case BuiltinFn::kImageQueryLevels: + return "image_query_levels"; + case BuiltinFn::kImageQuerySamples: + return "image_query_samples"; + case BuiltinFn::kImageRead: + return "image_read"; + case BuiltinFn::kImageSampleImplicitLod: + return "image_sample_implicit_lod"; + case BuiltinFn::kImageSampleProjImplicitLod: + return "image_sample_proj_implicit_lod"; + case BuiltinFn::kImageSampleProjDrefImplicitLod: + return "image_sample_proj_dref_implicit_lod"; + case BuiltinFn::kImageSampleExplicitLod: + return "image_sample_explicit_lod"; + case BuiltinFn::kImageSampleProjExplicitLod: + return "image_sample_proj_explicit_lod"; + case BuiltinFn::kImageSampleProjDrefExplicitLod: + return "image_sample_proj_dref_explicit_lod"; + case BuiltinFn::kImageSampleDrefImplicitLod: + return "image_sample_dref_implicit_lod"; + case BuiltinFn::kImageSampleDrefExplicitLod: + return "image_sample_dref_explicit_lod"; + case BuiltinFn::kImageWrite: + return "image_write"; + case BuiltinFn::kOpImage: + return "op_image"; + case BuiltinFn::kOpSampledImage: + return "op_sampled_image"; + case BuiltinFn::kMatrixTimesMatrix: + return "matrix_times_matrix"; + case BuiltinFn::kMatrixTimesScalar: + return "matrix_times_scalar"; + case BuiltinFn::kMatrixTimesVector: + return "matrix_times_vector"; + case BuiltinFn::kSelect: + return "select"; + case BuiltinFn::kVectorTimesMatrix: + return "vector_times_matrix"; + case BuiltinFn::kVectorTimesScalar: + return "vector_times_scalar"; + case BuiltinFn::kNormalize: + return "normalize"; + case BuiltinFn::kInverse: + return "inverse"; + case BuiltinFn::kSign: + return "sign"; + case BuiltinFn::kAbs: + return "abs"; + case BuiltinFn::kSMax: + return "s_max"; + case BuiltinFn::kSMin: + return "s_min"; + case BuiltinFn::kSClamp: + return "s_clamp"; + case BuiltinFn::kUMax: + return "u_max"; + case BuiltinFn::kUMin: + return "u_min"; + case BuiltinFn::kUClamp: + return "u_clamp"; + case BuiltinFn::kFindILsb: + return "find_i_lsb"; + case BuiltinFn::kFindSMsb: + return "find_s_msb"; + case BuiltinFn::kFindUMsb: + return "find_u_msb"; + case BuiltinFn::kRefract: + return "refract"; + case BuiltinFn::kReflect: + return "reflect"; + case BuiltinFn::kFaceForward: + return "face_forward"; + case BuiltinFn::kLdexp: + return "ldexp"; + case BuiltinFn::kModf: + return "modf"; + case BuiltinFn::kFrexp: + return "frexp"; + case BuiltinFn::kBitCount: + return "bit_count"; + case BuiltinFn::kBitFieldInsert: + return "bit_field_insert"; + case BuiltinFn::kBitFieldSExtract: + return "bit_field_s_extract"; + case BuiltinFn::kBitFieldUExtract: + return "bit_field_u_extract"; + case BuiltinFn::kAdd: + return "add"; + case BuiltinFn::kSub: + return "sub"; + case BuiltinFn::kMul: + return "mul"; + case BuiltinFn::kSDiv: + return "s_div"; + case BuiltinFn::kSMod: + return "s_mod"; + case BuiltinFn::kSGreaterThan: + return "s_greater_than"; + case BuiltinFn::kSGreaterThanEqual: + return "s_greater_than_equal"; + case BuiltinFn::kSLessThan: + return "s_less_than"; + case BuiltinFn::kSLessThanEqual: + return "s_less_than_equal"; + case BuiltinFn::kUGreaterThan: + return "u_greater_than"; + case BuiltinFn::kUGreaterThanEqual: + return "u_greater_than_equal"; + case BuiltinFn::kULessThan: + return "u_less_than"; + case BuiltinFn::kULessThanEqual: + return "u_less_than_equal"; + case BuiltinFn::kConvertFToS: + return "convert_f_to_s"; + case BuiltinFn::kConvertSToF: + return "convert_s_to_f"; + case BuiltinFn::kConvertUToF: + return "convert_u_to_f"; + case BuiltinFn::kSConvert: + return "s_convert"; + case BuiltinFn::kUConvert: + return "u_convert"; + case BuiltinFn::kBitwiseAnd: + return "bitwise_and"; + case BuiltinFn::kBitwiseOr: + return "bitwise_or"; + case BuiltinFn::kBitwiseXor: + return "bitwise_xor"; + case BuiltinFn::kEqual: + return "equal"; + case BuiltinFn::kNotEqual: + return "not_equal"; + case BuiltinFn::kShiftLeftLogical: + return "shift_left_logical"; + case BuiltinFn::kShiftRightLogical: + return "shift_right_logical"; + case BuiltinFn::kShiftRightArithmetic: + return "shift_right_arithmetic"; + case BuiltinFn::kNot: + return "not"; + case BuiltinFn::kSNegate: + return "s_negate"; + case BuiltinFn::kFMod: + return "f_mod"; + case BuiltinFn::kOuterProduct: + return "outer_product"; + case BuiltinFn::kSDot: + return "s_dot"; + case BuiltinFn::kUDot: + return "u_dot"; + case BuiltinFn::kCooperativeMatrixLoad: + return "cooperative_matrix_load"; + case BuiltinFn::kCooperativeMatrixStore: + return "cooperative_matrix_store"; + case BuiltinFn::kCooperativeMatrixMulAdd: + return "cooperative_matrix_mul_add"; + case BuiltinFn::kGroupNonUniformBroadcast: + return "group_non_uniform_broadcast"; + case BuiltinFn::kGroupNonUniformBroadcastFirst: + return "group_non_uniform_broadcast_first"; + case BuiltinFn::kGroupNonUniformQuadBroadcast: + return "group_non_uniform_quad_broadcast"; + case BuiltinFn::kGroupNonUniformQuadSwap: + return "group_non_uniform_quad_swap"; + case BuiltinFn::kGroupNonUniformShuffle: + return "group_non_uniform_shuffle"; + case BuiltinFn::kGroupNonUniformShuffleXor: + return "group_non_uniform_shuffle_xor"; + case BuiltinFn::kGroupNonUniformShuffleDown: + return "group_non_uniform_shuffle_down"; + case BuiltinFn::kGroupNonUniformShuffleUp: + return "group_non_uniform_shuffle_up"; + case BuiltinFn::kGroupNonUniformSMin: + return "group_non_uniform_s_min"; + case BuiltinFn::kGroupNonUniformSMax: + return "group_non_uniform_s_max"; + } + return ""; +} + +tint::core::ir::Instruction::Accesses GetSideEffects(BuiltinFn fn) { + switch (fn) { + case BuiltinFn::kAtomicLoad: + case BuiltinFn::kImageDrefGather: + case BuiltinFn::kImageFetch: + case BuiltinFn::kImageGather: + case BuiltinFn::kImageRead: + case BuiltinFn::kImageSampleImplicitLod: + case BuiltinFn::kImageSampleExplicitLod: + case BuiltinFn::kImageSampleProjImplicitLod: + case BuiltinFn::kImageSampleProjExplicitLod: + case BuiltinFn::kImageSampleDrefImplicitLod: + case BuiltinFn::kImageSampleDrefExplicitLod: + case BuiltinFn::kImageSampleProjDrefImplicitLod: + case BuiltinFn::kImageSampleProjDrefExplicitLod: + case BuiltinFn::kOpImage: + case BuiltinFn::kOpSampledImage: + case BuiltinFn::kCooperativeMatrixLoad: + return core::ir::Instruction::Accesses{core::ir::Instruction::Access::kLoad}; + + case BuiltinFn::kImageWrite: + case BuiltinFn::kModf: + case BuiltinFn::kFrexp: + case BuiltinFn::kCooperativeMatrixStore: + return core::ir::Instruction::Accesses{core::ir::Instruction::Access::kStore}; + + case BuiltinFn::kAtomicAnd: + case BuiltinFn::kAtomicCompareExchange: + case BuiltinFn::kAtomicExchange: + case BuiltinFn::kAtomicIAdd: + case BuiltinFn::kAtomicISub: + case BuiltinFn::kAtomicOr: + case BuiltinFn::kAtomicSMax: + case BuiltinFn::kAtomicSMin: + case BuiltinFn::kAtomicStore: + case BuiltinFn::kAtomicUMax: + case BuiltinFn::kAtomicUMin: + case BuiltinFn::kAtomicXor: + case BuiltinFn::kAtomicIIncrement: + case BuiltinFn::kAtomicIDecrement: + return core::ir::Instruction::Accesses{core::ir::Instruction::Access::kLoad, core::ir::Instruction::Access::kStore}; + + case BuiltinFn::kArrayLength: + case BuiltinFn::kDot: + case BuiltinFn::kImageQuerySize: + case BuiltinFn::kImageQuerySizeLod: + case BuiltinFn::kImageQueryLevels: + case BuiltinFn::kImageQuerySamples: + case BuiltinFn::kMatrixTimesMatrix: + case BuiltinFn::kMatrixTimesScalar: + case BuiltinFn::kMatrixTimesVector: + case BuiltinFn::kSelect: + case BuiltinFn::kVectorTimesMatrix: + case BuiltinFn::kVectorTimesScalar: + case BuiltinFn::kSDot: + case BuiltinFn::kUDot: + case BuiltinFn::kNone: + case BuiltinFn::kNormalize: + case BuiltinFn::kInverse: + case BuiltinFn::kSign: + case BuiltinFn::kAbs: + case BuiltinFn::kSMax: + case BuiltinFn::kSMin: + case BuiltinFn::kSClamp: + case BuiltinFn::kUMax: + case BuiltinFn::kUMin: + case BuiltinFn::kUClamp: + case BuiltinFn::kFindILsb: + case BuiltinFn::kFindSMsb: + case BuiltinFn::kFindUMsb: + case BuiltinFn::kRefract: + case BuiltinFn::kReflect: + case BuiltinFn::kFaceForward: + case BuiltinFn::kLdexp: + case BuiltinFn::kCooperativeMatrixMulAdd: + case BuiltinFn::kBitCount: + case BuiltinFn::kBitFieldInsert: + case BuiltinFn::kBitFieldSExtract: + case BuiltinFn::kBitFieldUExtract: + case BuiltinFn::kAdd: + case BuiltinFn::kSub: + case BuiltinFn::kMul: + case BuiltinFn::kSDiv: + case BuiltinFn::kSMod: + case BuiltinFn::kConvertFToS: + case BuiltinFn::kConvertSToF: + case BuiltinFn::kConvertUToF: + case BuiltinFn::kBitwiseAnd: + case BuiltinFn::kBitwiseOr: + case BuiltinFn::kBitwiseXor: + case BuiltinFn::kEqual: + case BuiltinFn::kNotEqual: + case BuiltinFn::kSGreaterThan: + case BuiltinFn::kSGreaterThanEqual: + case BuiltinFn::kSLessThan: + case BuiltinFn::kSLessThanEqual: + case BuiltinFn::kUGreaterThan: + case BuiltinFn::kUGreaterThanEqual: + case BuiltinFn::kULessThan: + case BuiltinFn::kULessThanEqual: + case BuiltinFn::kShiftLeftLogical: + case BuiltinFn::kShiftRightLogical: + case BuiltinFn::kShiftRightArithmetic: + case BuiltinFn::kNot: + case BuiltinFn::kSNegate: + case BuiltinFn::kFMod: + case BuiltinFn::kOuterProduct: + case BuiltinFn::kGroupNonUniformBroadcast: + case BuiltinFn::kGroupNonUniformBroadcastFirst: + case BuiltinFn::kGroupNonUniformShuffle: + case BuiltinFn::kGroupNonUniformShuffleXor: + case BuiltinFn::kGroupNonUniformShuffleDown: + case BuiltinFn::kGroupNonUniformShuffleUp: + case BuiltinFn::kGroupNonUniformQuadBroadcast: + case BuiltinFn::kGroupNonUniformQuadSwap: + case BuiltinFn::kGroupNonUniformSMin: + case BuiltinFn::kGroupNonUniformSMax: + case BuiltinFn::kSConvert: + case BuiltinFn::kUConvert: + break; + } + return core::ir::Instruction::Accesses{}; +} + +} // namespace tint::spirv + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/spirv/builtin_fn.h b/3rdparty/dawn/src/tint/lang/spirv/builtin_fn.h new file mode 100644 index 000000000..d7cd68e71 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/builtin_fn.h @@ -0,0 +1,186 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/spirv/builtin_fn.h.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SRC_TINT_LANG_SPIRV_BUILTIN_FN_H_ +#define SRC_TINT_LANG_SPIRV_BUILTIN_FN_H_ + +// clang-format off + +#include +#include + +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/lang/core/ir/call.h" + +// \cond DO_NOT_DOCUMENT +namespace tint::spirv { + +/// Enumerator of all builtin functions +enum class BuiltinFn : uint8_t { + kArrayLength, + kAtomicLoad, + kAtomicStore, + kAtomicExchange, + kAtomicCompareExchange, + kAtomicIAdd, + kAtomicISub, + kAtomicSMax, + kAtomicSMin, + kAtomicUMax, + kAtomicUMin, + kAtomicAnd, + kAtomicOr, + kAtomicXor, + kAtomicIIncrement, + kAtomicIDecrement, + kDot, + kImageDrefGather, + kImageFetch, + kImageGather, + kImageQuerySize, + kImageQuerySizeLod, + kImageQueryLevels, + kImageQuerySamples, + kImageRead, + kImageSampleImplicitLod, + kImageSampleProjImplicitLod, + kImageSampleProjDrefImplicitLod, + kImageSampleExplicitLod, + kImageSampleProjExplicitLod, + kImageSampleProjDrefExplicitLod, + kImageSampleDrefImplicitLod, + kImageSampleDrefExplicitLod, + kImageWrite, + kOpImage, + kOpSampledImage, + kMatrixTimesMatrix, + kMatrixTimesScalar, + kMatrixTimesVector, + kSelect, + kVectorTimesMatrix, + kVectorTimesScalar, + kNormalize, + kInverse, + kSign, + kAbs, + kSMax, + kSMin, + kSClamp, + kUMax, + kUMin, + kUClamp, + kFindILsb, + kFindSMsb, + kFindUMsb, + kRefract, + kReflect, + kFaceForward, + kLdexp, + kModf, + kFrexp, + kBitCount, + kBitFieldInsert, + kBitFieldSExtract, + kBitFieldUExtract, + kAdd, + kSub, + kMul, + kSDiv, + kSMod, + kSGreaterThan, + kSGreaterThanEqual, + kSLessThan, + kSLessThanEqual, + kUGreaterThan, + kUGreaterThanEqual, + kULessThan, + kULessThanEqual, + kConvertFToS, + kConvertSToF, + kConvertUToF, + kSConvert, + kUConvert, + kBitwiseAnd, + kBitwiseOr, + kBitwiseXor, + kEqual, + kNotEqual, + kShiftLeftLogical, + kShiftRightLogical, + kShiftRightArithmetic, + kNot, + kSNegate, + kFMod, + kOuterProduct, + kSDot, + kUDot, + kCooperativeMatrixLoad, + kCooperativeMatrixStore, + kCooperativeMatrixMulAdd, + kGroupNonUniformBroadcast, + kGroupNonUniformBroadcastFirst, + kGroupNonUniformQuadBroadcast, + kGroupNonUniformQuadSwap, + kGroupNonUniformShuffle, + kGroupNonUniformShuffleXor, + kGroupNonUniformShuffleDown, + kGroupNonUniformShuffleUp, + kGroupNonUniformSMin, + kGroupNonUniformSMax, + kNone, +}; + +/// @returns the name of the builtin function type. The spelling, including +/// case, matches the name in the WGSL spec. +const char* str(BuiltinFn i); + +/// Emits the name of the builtin function type. The spelling, including case, +/// matches the name in the WGSL spec. +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, BuiltinFn i) { + return o << str(i); +} + +/// @returns access restrictions for a function +tint::core::ir::Instruction::Accesses GetSideEffects(BuiltinFn fn); + +} // namespace tint::spirv +// \endcond + +// clang-format on + +#endif // SRC_TINT_LANG_SPIRV_BUILTIN_FN_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/intrinsic/data.cc b/3rdparty/dawn/src/tint/lang/spirv/intrinsic/data.cc new file mode 100644 index 000000000..15ae68e5a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/intrinsic/data.cc @@ -0,0 +1,12709 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/spirv/intrinsic/data.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include +#include + +#include "src/tint/lang/core/intrinsic/type_matchers.h" +#include "src/tint/lang/spirv/intrinsic/dialect.h" +#include "src/tint/lang/spirv/intrinsic/type_matchers.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::spirv::intrinsic { + +using namespace tint::core::intrinsic; // NOLINT(build/namespaces) + +namespace { + +using ConstEvalFunctionIndex = tint::core::intrinsic::ConstEvalFunctionIndex; +using IntrinsicInfo = tint::core::intrinsic::IntrinsicInfo; +using MatcherIndicesIndex = tint::core::intrinsic::MatcherIndicesIndex; +using MatchState = tint::core::intrinsic::MatchState; +using Number = tint::core::intrinsic::Number; +using NumberMatcher = tint::core::intrinsic::NumberMatcher; +using NumberMatcherIndex = tint::core::intrinsic::NumberMatcherIndex; +using OverloadFlag = tint::core::intrinsic::OverloadFlag; +using OverloadFlags = tint::core::intrinsic::OverloadFlags; +using OverloadIndex = tint::core::intrinsic::OverloadIndex; +using OverloadInfo = tint::core::intrinsic::OverloadInfo; +using ParameterIndex = tint::core::intrinsic::ParameterIndex; +using ParameterInfo = tint::core::intrinsic::ParameterInfo; +using StringStream = tint::StringStream; +using TemplateIndex = tint::core::intrinsic::TemplateIndex; +using Type = tint::core::type::Type; +using TypeMatcher = tint::core::intrinsic::TypeMatcher; +using TypeMatcherIndex = tint::core::intrinsic::TypeMatcherIndex; + +template +using TemplateNumberMatcher = tint::core::intrinsic::TemplateNumberMatcher; + +template +using TemplateTypeMatcher = tint::core::intrinsic::TemplateTypeMatcher; + +/// TypeMatcher for 'type bool' +constexpr TypeMatcher kBoolMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchBool(state, ty)) { + return nullptr; + } + return BuildBool(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("bool"); + } +}; + + +/// TypeMatcher for 'type f32' +constexpr TypeMatcher kF32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchF32(state, ty)) { + return nullptr; + } + return BuildF32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("f32"); + } +}; + + +/// TypeMatcher for 'type f16' +constexpr TypeMatcher kF16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchF16(state, ty)) { + return nullptr; + } + return BuildF16(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("f16"); + } +}; + + +/// TypeMatcher for 'type i32' +constexpr TypeMatcher kI32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchI32(state, ty)) { + return nullptr; + } + return BuildI32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("i32"); + } +}; + + +/// TypeMatcher for 'type u32' +constexpr TypeMatcher kU32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchU32(state, ty)) { + return nullptr; + } + return BuildU32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("u32"); + } +}; + + +/// TypeMatcher for 'type i8' +constexpr TypeMatcher kI8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchI8(state, ty)) { + return nullptr; + } + return BuildI8(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("i8"); + } +}; + + +/// TypeMatcher for 'type u8' +constexpr TypeMatcher kU8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchU8(state, ty)) { + return nullptr; + } + return BuildU8(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("u8"); + } +}; + + +/// TypeMatcher for 'type vec2' +constexpr TypeMatcher kVec2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec3' +constexpr TypeMatcher kVec3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec4' +constexpr TypeMatcher kVec4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x2' +constexpr TypeMatcher kMat2X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x3' +constexpr TypeMatcher kMat2X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x4' +constexpr TypeMatcher kMat2X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x2' +constexpr TypeMatcher kMat3X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x3' +constexpr TypeMatcher kMat3X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x4' +constexpr TypeMatcher kMat3X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x2' +constexpr TypeMatcher kMat4X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x3' +constexpr TypeMatcher kMat4X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x4' +constexpr TypeMatcher kMat4X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec' +constexpr TypeMatcher kVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("vec", N, "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat' +constexpr TypeMatcher kMatMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + Number M = Number::invalid; + const Type* T = nullptr; + if (!MatchMat(state, ty, N, M, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + M = state.Num(M); + if (!M.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat(state, ty, N, M, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText M; + state->PrintNum(M);StyledText T; + state->PrintType(T); + out << style::Type("mat", N, "x", M, "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type atomic' +constexpr TypeMatcher kAtomicMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchAtomic(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildAtomic(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("atomic", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type sampler' +constexpr TypeMatcher kSamplerMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchSampler(state, ty)) { + return nullptr; + } + return BuildSampler(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("sampler"); + } +}; + + +/// TypeMatcher for 'type sampler_comparison' +constexpr TypeMatcher kSamplerComparisonMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchSamplerComparison(state, ty)) { + return nullptr; + } + return BuildSamplerComparison(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("sampler_comparison"); + } +}; + + +/// TypeMatcher for 'type ptr' +constexpr TypeMatcher kPtrMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number A = Number::invalid; + if (!MatchPtr(state, ty, S, T, A)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildPtr(state, ty, S, T, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText A; + state->PrintNum(A); + out << style::Type("ptr", "<", S, ", ", T, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type struct_with_runtime_array' +constexpr TypeMatcher kStructWithRuntimeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchStructWithRuntimeArray(state, ty)) { + return nullptr; + } + return BuildStructWithRuntimeArray(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("struct_with_runtime_array"); + } +}; + + +/// TypeMatcher for 'type image' +constexpr TypeMatcher kImageMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + Number D = Number::invalid; + Number E = Number::invalid; + Number R = Number::invalid; + Number M = Number::invalid; + Number S = Number::invalid; + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchImage(state, ty, T, D, E, R, M, S, F, A)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + D = state.Num(D); + if (!D.IsValid()) { + return nullptr; + } + E = state.Num(E); + if (!E.IsValid()) { + return nullptr; + } + R = state.Num(R); + if (!R.IsValid()) { + return nullptr; + } + M = state.Num(M); + if (!M.IsValid()) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildImage(state, ty, T, D, E, R, M, S, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T);StyledText D; + state->PrintNum(D);StyledText E; + state->PrintNum(E);StyledText R; + state->PrintNum(R);StyledText M; + state->PrintNum(M);StyledText S; + state->PrintNum(S);StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("image", "<", T, ", ", D, ", ", E, ", ", R, ", ", M, ", ", S, ", ", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type sampled_image' +constexpr TypeMatcher kSampledImageMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchSampledImage(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildSampledImage(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("sampled_image", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type subgroup_matrix' +constexpr TypeMatcher kSubgroupMatrixMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number C = Number::invalid; + Number R = Number::invalid; + if (!MatchSubgroupMatrix(state, ty, S, T, C, R)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + C = state.Num(C); + if (!C.IsValid()) { + return nullptr; + } + R = state.Num(R); + if (!R.IsValid()) { + return nullptr; + } + return BuildSubgroupMatrix(state, ty, S, T, C, R); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText C; + state->PrintNum(C);StyledText R; + state->PrintNum(R); + out << style::Type("subgroup_matrix", "<", S, ", ", T, ", ", C, ", ", R, ">"); + } +}; + + +/// TypeMatcher for 'match f32_f16' +constexpr TypeMatcher kF32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu32' +constexpr TypeMatcher kIu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fiu32' +constexpr TypeMatcher kFiu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fiu32_f16' +constexpr TypeMatcher kFiu32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar' +constexpr TypeMatcher kScalarMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu32_iu8' +constexpr TypeMatcher kIu32Iu8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(", "); kI8Matcher.print(nullptr, out); out << style::Plain(" or "); kU8Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu8' +constexpr TypeMatcher kIu8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI8Matcher.print(nullptr, out); out << style::Plain(" or "); kU8Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match samplers' +constexpr TypeMatcher kSamplersMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchSampler(state, ty)) { + return BuildSampler(state, ty); + } + if (MatchSamplerComparison(state, ty)) { + return BuildSamplerComparison(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kSamplerMatcher.print(nullptr, out); out << style::Plain(" or "); kSamplerComparisonMatcher.print(nullptr, out);} +}; + +/// EnumMatcher for 'match storage' +constexpr NumberMatcher kStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::AddressSpace::kStorage)) { + return Number(static_cast(core::AddressSpace::kStorage)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match workgroup_or_storage' +constexpr NumberMatcher kWorkgroupOrStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kWorkgroup: + case core::AddressSpace::kStorage: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("workgroup")<< style::Plain(" or ") << style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match function_private_workgroup_storage' +constexpr NumberMatcher kFunctionPrivateWorkgroupStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kFunction: + case core::AddressSpace::kPrivate: + case core::AddressSpace::kWorkgroup: + case core::AddressSpace::kStorage: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("function")<< style::Plain(", ") << style::Enum("private")<< style::Plain(", ") << style::Enum("workgroup")<< style::Plain(" or ") << style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match f32_texel_format' +constexpr NumberMatcher kF32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Unorm: + case core::TexelFormat::kR8Snorm: + case core::TexelFormat::kRg8Unorm: + case core::TexelFormat::kRg8Snorm: + case core::TexelFormat::kBgra8Unorm: + case core::TexelFormat::kRgba8Unorm: + case core::TexelFormat::kRgba8Snorm: + case core::TexelFormat::kR16Unorm: + case core::TexelFormat::kR16Snorm: + case core::TexelFormat::kRg16Unorm: + case core::TexelFormat::kRg16Snorm: + case core::TexelFormat::kRgba16Unorm: + case core::TexelFormat::kRgba16Snorm: + case core::TexelFormat::kR16Float: + case core::TexelFormat::kRg16Float: + case core::TexelFormat::kRgba16Float: + case core::TexelFormat::kR32Float: + case core::TexelFormat::kRg32Float: + case core::TexelFormat::kRgba32Float: + case core::TexelFormat::kRgb10A2Unorm: + case core::TexelFormat::kRg11B10Ufloat: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8unorm")<< style::Plain(", ") << style::Enum("r8snorm")<< style::Plain(", ") << style::Enum("rg8unorm")<< style::Plain(", ") << style::Enum("rg8snorm")<< style::Plain(", ") << style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("r16unorm")<< style::Plain(", ") << style::Enum("r16snorm")<< style::Plain(", ") << style::Enum("rg16unorm")<< style::Plain(", ") << style::Enum("rg16snorm")<< style::Plain(", ") << style::Enum("rgba16unorm")<< style::Plain(", ") << style::Enum("rgba16snorm")<< style::Plain(", ") << style::Enum("r16float")<< style::Plain(", ") << style::Enum("rg16float")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(", ") << style::Enum("rgba32float")<< style::Plain(", ") << style::Enum("rgb10a2unorm")<< style::Plain(" or ") << style::Enum("rg11b10ufloat"); + } +}; + +/// EnumMatcher for 'match i32_texel_format' +constexpr NumberMatcher kI32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Sint: + case core::TexelFormat::kRg8Sint: + case core::TexelFormat::kRgba8Sint: + case core::TexelFormat::kR16Sint: + case core::TexelFormat::kRg16Sint: + case core::TexelFormat::kRgba16Sint: + case core::TexelFormat::kR32Sint: + case core::TexelFormat::kRg32Sint: + case core::TexelFormat::kRgba32Sint: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8sint")<< style::Plain(", ") << style::Enum("rg8sint")<< style::Plain(", ") << style::Enum("rgba8sint")<< style::Plain(", ") << style::Enum("r16sint")<< style::Plain(", ") << style::Enum("rg16sint")<< style::Plain(", ") << style::Enum("rgba16sint")<< style::Plain(", ") << style::Enum("r32sint")<< style::Plain(", ") << style::Enum("rg32sint")<< style::Plain(" or ") << style::Enum("rgba32sint"); + } +}; + +/// EnumMatcher for 'match u32_texel_format' +constexpr NumberMatcher kU32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Uint: + case core::TexelFormat::kRg8Uint: + case core::TexelFormat::kR16Uint: + case core::TexelFormat::kRg16Uint: + case core::TexelFormat::kRgba8Uint: + case core::TexelFormat::kRgba16Uint: + case core::TexelFormat::kR32Uint: + case core::TexelFormat::kRg32Uint: + case core::TexelFormat::kRgba32Uint: + case core::TexelFormat::kRgb10A2Uint: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8uint")<< style::Plain(", ") << style::Enum("rg8uint")<< style::Plain(", ") << style::Enum("r16uint")<< style::Plain(", ") << style::Enum("rg16uint")<< style::Plain(", ") << style::Enum("rgba8uint")<< style::Plain(", ") << style::Enum("rgba16uint")<< style::Plain(", ") << style::Enum("r32uint")<< style::Plain(", ") << style::Enum("rg32uint")<< style::Plain(", ") << style::Enum("rgba32uint")<< style::Plain(" or ") << style::Enum("rgb10a2uint"); + } +}; + +/// EnumMatcher for 'match read_write' +constexpr NumberMatcher kReadWriteMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kReadWrite)) { + return Number(static_cast(core::Access::kReadWrite)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match readable' +constexpr NumberMatcher kReadableMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::Access::kRead: + case core::Access::kReadWrite: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read")<< style::Plain(" or ") << style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match writable' +constexpr NumberMatcher kWritableMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::Access::kWrite: + case core::Access::kReadWrite: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("write")<< style::Plain(" or ") << style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match dim_1d' +constexpr NumberMatcher kDim1DMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Dim::kD1)) { + return Number(static_cast(spirv::type::Dim::kD1)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("d1"); + } +}; + +/// EnumMatcher for 'match dim_2d' +constexpr NumberMatcher kDim2DMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Dim::kD2)) { + return Number(static_cast(spirv::type::Dim::kD2)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("d2"); + } +}; + +/// EnumMatcher for 'match dim_3d' +constexpr NumberMatcher kDim3DMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Dim::kD3)) { + return Number(static_cast(spirv::type::Dim::kD3)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("d3"); + } +}; + +/// EnumMatcher for 'match dim_cube' +constexpr NumberMatcher kDimCubeMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Dim::kCube)) { + return Number(static_cast(spirv::type::Dim::kCube)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Cube"); + } +}; + +/// EnumMatcher for 'match dim_buffer' +constexpr NumberMatcher kDimBufferMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Dim::kBuffer)) { + return Number(static_cast(spirv::type::Dim::kBuffer)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Buffer"); + } +}; + +/// EnumMatcher for 'match dim_subpass' +constexpr NumberMatcher kDimSubpassMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Dim::kSubpassData)) { + return Number(static_cast(spirv::type::Dim::kSubpassData)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("SubpassData"); + } +}; + +/// EnumMatcher for 'match dim_1d_2d_3d_or_cube' +constexpr NumberMatcher kDim1D2D3DOrCubeMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case spirv::type::Dim::kD1: + case spirv::type::Dim::kD2: + case spirv::type::Dim::kD3: + case spirv::type::Dim::kCube: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("d1")<< style::Plain(", ") << style::Enum("d2")<< style::Plain(", ") << style::Enum("d3")<< style::Plain(" or ") << style::Enum("Cube"); + } +}; + +/// EnumMatcher for 'match single_sampled' +constexpr NumberMatcher kSingleSampledMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Multisampled::kSingleSampled)) { + return Number(static_cast(spirv::type::Multisampled::kSingleSampled)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("SingleSampled"); + } +}; + +/// EnumMatcher for 'match multi_sampled' +constexpr NumberMatcher kMultiSampledMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Multisampled::kMultisampled)) { + return Number(static_cast(spirv::type::Multisampled::kMultisampled)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Multisampled"); + } +}; + +/// EnumMatcher for 'match is_depth' +constexpr NumberMatcher kIsDepthMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Depth::kDepth)) { + return Number(static_cast(spirv::type::Depth::kDepth)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Depth"); + } +}; + +/// EnumMatcher for 'match non_depth' +constexpr NumberMatcher kNonDepthMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case spirv::type::Depth::kNotDepth: + case spirv::type::Depth::kUnknown: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("NotDepth")<< style::Plain(" or ") << style::Enum("Unknown"); + } +}; + +/// EnumMatcher for 'match any_depth' +constexpr NumberMatcher kAnyDepthMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case spirv::type::Depth::kDepth: + case spirv::type::Depth::kNotDepth: + case spirv::type::Depth::kUnknown: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Depth")<< style::Plain(", ") << style::Enum("NotDepth")<< style::Plain(" or ") << style::Enum("Unknown"); + } +}; + +/// EnumMatcher for 'match is_arrayed' +constexpr NumberMatcher kIsArrayedMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Arrayed::kArrayed)) { + return Number(static_cast(spirv::type::Arrayed::kArrayed)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Arrayed"); + } +}; + +/// EnumMatcher for 'match non_arrayed' +constexpr NumberMatcher kNonArrayedMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Arrayed::kNonArrayed)) { + return Number(static_cast(spirv::type::Arrayed::kNonArrayed)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("NonArrayed"); + } +}; + +/// EnumMatcher for 'match any_arrayed' +constexpr NumberMatcher kAnyArrayedMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case spirv::type::Arrayed::kArrayed: + case spirv::type::Arrayed::kNonArrayed: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("Arrayed")<< style::Plain(" or ") << style::Enum("NonArrayed"); + } +}; + +/// EnumMatcher for 'match sampling_compatible' +constexpr NumberMatcher kSamplingCompatibleMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Sampled::kSamplingCompatible)) { + return Number(static_cast(spirv::type::Sampled::kSamplingCompatible)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("SamplingCompatible"); + } +}; + +/// EnumMatcher for 'match rw_op_compatible' +constexpr NumberMatcher kRwOpCompatibleMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(spirv::type::Sampled::kReadWriteOpCompatible)) { + return Number(static_cast(spirv::type::Sampled::kReadWriteOpCompatible)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("ReadWriteOpCompatible"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_left' +constexpr NumberMatcher kSubgroupMatrixKindLeftMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kLeft)) { + return Number(static_cast(core::SubgroupMatrixKind::kLeft)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("left"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_right' +constexpr NumberMatcher kSubgroupMatrixKindRightMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kRight)) { + return Number(static_cast(core::SubgroupMatrixKind::kRight)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("right"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_result' +constexpr NumberMatcher kSubgroupMatrixKindResultMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kResult)) { + return Number(static_cast(core::SubgroupMatrixKind::kResult)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("result"); + } +}; + +/// Type and number matchers + +/// The template types, types, and type matchers +constexpr TypeMatcher kTypeMatchers[] = { + /* [0] */ TemplateTypeMatcher<0>::matcher, + /* [1] */ TemplateTypeMatcher<1>::matcher, + /* [2] */ TemplateTypeMatcher<2>::matcher, + /* [3] */ TemplateTypeMatcher<3>::matcher, + /* [4] */ TemplateTypeMatcher<4>::matcher, + /* [5] */ TemplateTypeMatcher<5>::matcher, + /* [6] */ TemplateTypeMatcher<6>::matcher, + /* [7] */ kBoolMatcher, + /* [8] */ kF32Matcher, + /* [9] */ kF16Matcher, + /* [10] */ kI32Matcher, + /* [11] */ kU32Matcher, + /* [12] */ kI8Matcher, + /* [13] */ kU8Matcher, + /* [14] */ kVec2Matcher, + /* [15] */ kVec3Matcher, + /* [16] */ kVec4Matcher, + /* [17] */ kMat2X2Matcher, + /* [18] */ kMat2X3Matcher, + /* [19] */ kMat2X4Matcher, + /* [20] */ kMat3X2Matcher, + /* [21] */ kMat3X3Matcher, + /* [22] */ kMat3X4Matcher, + /* [23] */ kMat4X2Matcher, + /* [24] */ kMat4X3Matcher, + /* [25] */ kMat4X4Matcher, + /* [26] */ kVecMatcher, + /* [27] */ kMatMatcher, + /* [28] */ kAtomicMatcher, + /* [29] */ kSamplerMatcher, + /* [30] */ kSamplerComparisonMatcher, + /* [31] */ kPtrMatcher, + /* [32] */ kStructWithRuntimeArrayMatcher, + /* [33] */ kImageMatcher, + /* [34] */ kSampledImageMatcher, + /* [35] */ kSubgroupMatrixMatcher, + /* [36] */ kF32F16Matcher, + /* [37] */ kIu32Matcher, + /* [38] */ kFiu32Matcher, + /* [39] */ kFiu32F16Matcher, + /* [40] */ kScalarMatcher, + /* [41] */ kIu32Iu8Matcher, + /* [42] */ kIu8Matcher, + /* [43] */ kSamplersMatcher, +}; + +/// The template numbers, and number matchers +constexpr NumberMatcher kNumberMatchers[] = { + /* [0] */ TemplateNumberMatcher<0>::matcher, + /* [1] */ TemplateNumberMatcher<1>::matcher, + /* [2] */ TemplateNumberMatcher<2>::matcher, + /* [3] */ TemplateNumberMatcher<3>::matcher, + /* [4] */ TemplateNumberMatcher<4>::matcher, + /* [5] */ TemplateNumberMatcher<5>::matcher, + /* [6] */ TemplateNumberMatcher<6>::matcher, + /* [7] */ kStorageMatcher, + /* [8] */ kWorkgroupOrStorageMatcher, + /* [9] */ kFunctionPrivateWorkgroupStorageMatcher, + /* [10] */ kF32TexelFormatMatcher, + /* [11] */ kI32TexelFormatMatcher, + /* [12] */ kU32TexelFormatMatcher, + /* [13] */ kReadWriteMatcher, + /* [14] */ kReadableMatcher, + /* [15] */ kWritableMatcher, + /* [16] */ kDim1DMatcher, + /* [17] */ kDim2DMatcher, + /* [18] */ kDim3DMatcher, + /* [19] */ kDimCubeMatcher, + /* [20] */ kDimBufferMatcher, + /* [21] */ kDimSubpassMatcher, + /* [22] */ kDim1D2D3DOrCubeMatcher, + /* [23] */ kSingleSampledMatcher, + /* [24] */ kMultiSampledMatcher, + /* [25] */ kIsDepthMatcher, + /* [26] */ kNonDepthMatcher, + /* [27] */ kAnyDepthMatcher, + /* [28] */ kIsArrayedMatcher, + /* [29] */ kNonArrayedMatcher, + /* [30] */ kAnyArrayedMatcher, + /* [31] */ kSamplingCompatibleMatcher, + /* [32] */ kRwOpCompatibleMatcher, + /* [33] */ kSubgroupMatrixKindLeftMatcher, + /* [34] */ kSubgroupMatrixKindRightMatcher, + /* [35] */ kSubgroupMatrixKindResultMatcher, +}; + +constexpr MatcherIndex kMatcherIndices[] = { + /* [0] */ MatcherIndex(34), + /* [1] */ MatcherIndex(33), + /* [2] */ MatcherIndex(8), + /* [3] */ MatcherIndex(17), + /* [4] */ MatcherIndex(27), + /* [5] */ MatcherIndex(29), + /* [6] */ MatcherIndex(23), + /* [7] */ MatcherIndex(31), + /* [8] */ MatcherIndex(0), + /* [9] */ MatcherIndex(14), + /* [10] */ MatcherIndex(8), + /* [11] */ MatcherIndex(34), + /* [12] */ MatcherIndex(33), + /* [13] */ MatcherIndex(8), + /* [14] */ MatcherIndex(17), + /* [15] */ MatcherIndex(27), + /* [16] */ MatcherIndex(28), + /* [17] */ MatcherIndex(23), + /* [18] */ MatcherIndex(31), + /* [19] */ MatcherIndex(0), + /* [20] */ MatcherIndex(14), + /* [21] */ MatcherIndex(2), + /* [22] */ MatcherIndex(34), + /* [23] */ MatcherIndex(33), + /* [24] */ MatcherIndex(8), + /* [25] */ MatcherIndex(19), + /* [26] */ MatcherIndex(27), + /* [27] */ MatcherIndex(29), + /* [28] */ MatcherIndex(23), + /* [29] */ MatcherIndex(31), + /* [30] */ MatcherIndex(0), + /* [31] */ MatcherIndex(14), + /* [32] */ MatcherIndex(1), + /* [33] */ MatcherIndex(34), + /* [34] */ MatcherIndex(33), + /* [35] */ MatcherIndex(8), + /* [36] */ MatcherIndex(19), + /* [37] */ MatcherIndex(27), + /* [38] */ MatcherIndex(28), + /* [39] */ MatcherIndex(23), + /* [40] */ MatcherIndex(31), + /* [41] */ MatcherIndex(0), + /* [42] */ MatcherIndex(14), + /* [43] */ MatcherIndex(0), + /* [44] */ MatcherIndex(34), + /* [45] */ MatcherIndex(33), + /* [46] */ MatcherIndex(0), + /* [47] */ MatcherIndex(17), + /* [48] */ MatcherIndex(26), + /* [49] */ MatcherIndex(29), + /* [50] */ MatcherIndex(23), + /* [51] */ MatcherIndex(31), + /* [52] */ MatcherIndex(2), + /* [53] */ MatcherIndex(14), + /* [54] */ MatcherIndex(34), + /* [55] */ MatcherIndex(33), + /* [56] */ MatcherIndex(0), + /* [57] */ MatcherIndex(17), + /* [58] */ MatcherIndex(26), + /* [59] */ MatcherIndex(29), + /* [60] */ MatcherIndex(23), + /* [61] */ MatcherIndex(31), + /* [62] */ MatcherIndex(3), + /* [63] */ MatcherIndex(14), + /* [64] */ MatcherIndex(34), + /* [65] */ MatcherIndex(33), + /* [66] */ MatcherIndex(0), + /* [67] */ MatcherIndex(17), + /* [68] */ MatcherIndex(26), + /* [69] */ MatcherIndex(28), + /* [70] */ MatcherIndex(23), + /* [71] */ MatcherIndex(31), + /* [72] */ MatcherIndex(2), + /* [73] */ MatcherIndex(14), + /* [74] */ MatcherIndex(34), + /* [75] */ MatcherIndex(33), + /* [76] */ MatcherIndex(0), + /* [77] */ MatcherIndex(17), + /* [78] */ MatcherIndex(26), + /* [79] */ MatcherIndex(28), + /* [80] */ MatcherIndex(23), + /* [81] */ MatcherIndex(31), + /* [82] */ MatcherIndex(3), + /* [83] */ MatcherIndex(14), + /* [84] */ MatcherIndex(34), + /* [85] */ MatcherIndex(33), + /* [86] */ MatcherIndex(0), + /* [87] */ MatcherIndex(19), + /* [88] */ MatcherIndex(26), + /* [89] */ MatcherIndex(29), + /* [90] */ MatcherIndex(23), + /* [91] */ MatcherIndex(31), + /* [92] */ MatcherIndex(2), + /* [93] */ MatcherIndex(14), + /* [94] */ MatcherIndex(34), + /* [95] */ MatcherIndex(33), + /* [96] */ MatcherIndex(0), + /* [97] */ MatcherIndex(19), + /* [98] */ MatcherIndex(26), + /* [99] */ MatcherIndex(28), + /* [100] */ MatcherIndex(23), + /* [101] */ MatcherIndex(31), + /* [102] */ MatcherIndex(2), + /* [103] */ MatcherIndex(14), + /* [104] */ MatcherIndex(34), + /* [105] */ MatcherIndex(33), + /* [106] */ MatcherIndex(8), + /* [107] */ MatcherIndex(17), + /* [108] */ MatcherIndex(25), + /* [109] */ MatcherIndex(29), + /* [110] */ MatcherIndex(23), + /* [111] */ MatcherIndex(31), + /* [112] */ MatcherIndex(1), + /* [113] */ MatcherIndex(14), + /* [114] */ MatcherIndex(34), + /* [115] */ MatcherIndex(33), + /* [116] */ MatcherIndex(8), + /* [117] */ MatcherIndex(17), + /* [118] */ MatcherIndex(25), + /* [119] */ MatcherIndex(29), + /* [120] */ MatcherIndex(23), + /* [121] */ MatcherIndex(31), + /* [122] */ MatcherIndex(2), + /* [123] */ MatcherIndex(14), + /* [124] */ MatcherIndex(34), + /* [125] */ MatcherIndex(33), + /* [126] */ MatcherIndex(8), + /* [127] */ MatcherIndex(17), + /* [128] */ MatcherIndex(25), + /* [129] */ MatcherIndex(28), + /* [130] */ MatcherIndex(23), + /* [131] */ MatcherIndex(31), + /* [132] */ MatcherIndex(1), + /* [133] */ MatcherIndex(14), + /* [134] */ MatcherIndex(34), + /* [135] */ MatcherIndex(33), + /* [136] */ MatcherIndex(8), + /* [137] */ MatcherIndex(17), + /* [138] */ MatcherIndex(25), + /* [139] */ MatcherIndex(28), + /* [140] */ MatcherIndex(23), + /* [141] */ MatcherIndex(31), + /* [142] */ MatcherIndex(2), + /* [143] */ MatcherIndex(14), + /* [144] */ MatcherIndex(34), + /* [145] */ MatcherIndex(33), + /* [146] */ MatcherIndex(8), + /* [147] */ MatcherIndex(19), + /* [148] */ MatcherIndex(25), + /* [149] */ MatcherIndex(29), + /* [150] */ MatcherIndex(23), + /* [151] */ MatcherIndex(31), + /* [152] */ MatcherIndex(1), + /* [153] */ MatcherIndex(14), + /* [154] */ MatcherIndex(34), + /* [155] */ MatcherIndex(33), + /* [156] */ MatcherIndex(8), + /* [157] */ MatcherIndex(19), + /* [158] */ MatcherIndex(25), + /* [159] */ MatcherIndex(28), + /* [160] */ MatcherIndex(23), + /* [161] */ MatcherIndex(31), + /* [162] */ MatcherIndex(1), + /* [163] */ MatcherIndex(14), + /* [164] */ MatcherIndex(34), + /* [165] */ MatcherIndex(33), + /* [166] */ MatcherIndex(0), + /* [167] */ MatcherIndex(16), + /* [168] */ MatcherIndex(26), + /* [169] */ MatcherIndex(29), + /* [170] */ MatcherIndex(23), + /* [171] */ MatcherIndex(31), + /* [172] */ MatcherIndex(1), + /* [173] */ MatcherIndex(14), + /* [174] */ MatcherIndex(34), + /* [175] */ MatcherIndex(33), + /* [176] */ MatcherIndex(0), + /* [177] */ MatcherIndex(17), + /* [178] */ MatcherIndex(26), + /* [179] */ MatcherIndex(29), + /* [180] */ MatcherIndex(23), + /* [181] */ MatcherIndex(31), + /* [182] */ MatcherIndex(1), + /* [183] */ MatcherIndex(14), + /* [184] */ MatcherIndex(34), + /* [185] */ MatcherIndex(33), + /* [186] */ MatcherIndex(0), + /* [187] */ MatcherIndex(17), + /* [188] */ MatcherIndex(26), + /* [189] */ MatcherIndex(28), + /* [190] */ MatcherIndex(23), + /* [191] */ MatcherIndex(31), + /* [192] */ MatcherIndex(1), + /* [193] */ MatcherIndex(14), + /* [194] */ MatcherIndex(34), + /* [195] */ MatcherIndex(33), + /* [196] */ MatcherIndex(0), + /* [197] */ MatcherIndex(18), + /* [198] */ MatcherIndex(26), + /* [199] */ MatcherIndex(29), + /* [200] */ MatcherIndex(23), + /* [201] */ MatcherIndex(31), + /* [202] */ MatcherIndex(1), + /* [203] */ MatcherIndex(14), + /* [204] */ MatcherIndex(34), + /* [205] */ MatcherIndex(33), + /* [206] */ MatcherIndex(0), + /* [207] */ MatcherIndex(18), + /* [208] */ MatcherIndex(26), + /* [209] */ MatcherIndex(29), + /* [210] */ MatcherIndex(23), + /* [211] */ MatcherIndex(31), + /* [212] */ MatcherIndex(2), + /* [213] */ MatcherIndex(14), + /* [214] */ MatcherIndex(34), + /* [215] */ MatcherIndex(33), + /* [216] */ MatcherIndex(0), + /* [217] */ MatcherIndex(19), + /* [218] */ MatcherIndex(26), + /* [219] */ MatcherIndex(29), + /* [220] */ MatcherIndex(23), + /* [221] */ MatcherIndex(31), + /* [222] */ MatcherIndex(1), + /* [223] */ MatcherIndex(14), + /* [224] */ MatcherIndex(34), + /* [225] */ MatcherIndex(33), + /* [226] */ MatcherIndex(0), + /* [227] */ MatcherIndex(19), + /* [228] */ MatcherIndex(26), + /* [229] */ MatcherIndex(28), + /* [230] */ MatcherIndex(23), + /* [231] */ MatcherIndex(31), + /* [232] */ MatcherIndex(1), + /* [233] */ MatcherIndex(14), + /* [234] */ MatcherIndex(34), + /* [235] */ MatcherIndex(33), + /* [236] */ MatcherIndex(8), + /* [237] */ MatcherIndex(17), + /* [238] */ MatcherIndex(25), + /* [239] */ MatcherIndex(29), + /* [240] */ MatcherIndex(23), + /* [241] */ MatcherIndex(31), + /* [242] */ MatcherIndex(0), + /* [243] */ MatcherIndex(14), + /* [244] */ MatcherIndex(34), + /* [245] */ MatcherIndex(33), + /* [246] */ MatcherIndex(8), + /* [247] */ MatcherIndex(19), + /* [248] */ MatcherIndex(25), + /* [249] */ MatcherIndex(29), + /* [250] */ MatcherIndex(23), + /* [251] */ MatcherIndex(31), + /* [252] */ MatcherIndex(0), + /* [253] */ MatcherIndex(14), + /* [254] */ MatcherIndex(34), + /* [255] */ MatcherIndex(33), + /* [256] */ MatcherIndex(8), + /* [257] */ MatcherIndex(17), + /* [258] */ MatcherIndex(25), + /* [259] */ MatcherIndex(28), + /* [260] */ MatcherIndex(23), + /* [261] */ MatcherIndex(31), + /* [262] */ MatcherIndex(0), + /* [263] */ MatcherIndex(14), + /* [264] */ MatcherIndex(34), + /* [265] */ MatcherIndex(33), + /* [266] */ MatcherIndex(8), + /* [267] */ MatcherIndex(19), + /* [268] */ MatcherIndex(25), + /* [269] */ MatcherIndex(28), + /* [270] */ MatcherIndex(23), + /* [271] */ MatcherIndex(31), + /* [272] */ MatcherIndex(0), + /* [273] */ MatcherIndex(14), + /* [274] */ MatcherIndex(34), + /* [275] */ MatcherIndex(33), + /* [276] */ MatcherIndex(8), + /* [277] */ MatcherIndex(17), + /* [278] */ MatcherIndex(27), + /* [279] */ MatcherIndex(29), + /* [280] */ MatcherIndex(23), + /* [281] */ MatcherIndex(31), + /* [282] */ MatcherIndex(1), + /* [283] */ MatcherIndex(14), + /* [284] */ MatcherIndex(34), + /* [285] */ MatcherIndex(33), + /* [286] */ MatcherIndex(8), + /* [287] */ MatcherIndex(17), + /* [288] */ MatcherIndex(27), + /* [289] */ MatcherIndex(28), + /* [290] */ MatcherIndex(23), + /* [291] */ MatcherIndex(31), + /* [292] */ MatcherIndex(1), + /* [293] */ MatcherIndex(14), + /* [294] */ MatcherIndex(33), + /* [295] */ MatcherIndex(0), + /* [296] */ MatcherIndex(16), + /* [297] */ MatcherIndex(26), + /* [298] */ MatcherIndex(29), + /* [299] */ MatcherIndex(23), + /* [300] */ MatcherIndex(31), + /* [301] */ MatcherIndex(2), + /* [302] */ MatcherIndex(14), + /* [303] */ MatcherIndex(33), + /* [304] */ MatcherIndex(0), + /* [305] */ MatcherIndex(17), + /* [306] */ MatcherIndex(26), + /* [307] */ MatcherIndex(29), + /* [308] */ MatcherIndex(24), + /* [309] */ MatcherIndex(31), + /* [310] */ MatcherIndex(2), + /* [311] */ MatcherIndex(14), + /* [312] */ MatcherIndex(33), + /* [313] */ MatcherIndex(8), + /* [314] */ MatcherIndex(17), + /* [315] */ MatcherIndex(25), + /* [316] */ MatcherIndex(29), + /* [317] */ MatcherIndex(24), + /* [318] */ MatcherIndex(31), + /* [319] */ MatcherIndex(1), + /* [320] */ MatcherIndex(14), + /* [321] */ MatcherIndex(33), + /* [322] */ MatcherIndex(0), + /* [323] */ MatcherIndex(16), + /* [324] */ MatcherIndex(26), + /* [325] */ MatcherIndex(29), + /* [326] */ MatcherIndex(23), + /* [327] */ MatcherIndex(31), + /* [328] */ MatcherIndex(3), + /* [329] */ MatcherIndex(14), + /* [330] */ MatcherIndex(33), + /* [331] */ MatcherIndex(0), + /* [332] */ MatcherIndex(18), + /* [333] */ MatcherIndex(26), + /* [334] */ MatcherIndex(29), + /* [335] */ MatcherIndex(23), + /* [336] */ MatcherIndex(31), + /* [337] */ MatcherIndex(3), + /* [338] */ MatcherIndex(14), + /* [339] */ MatcherIndex(33), + /* [340] */ MatcherIndex(0), + /* [341] */ MatcherIndex(17), + /* [342] */ MatcherIndex(26), + /* [343] */ MatcherIndex(29), + /* [344] */ MatcherIndex(24), + /* [345] */ MatcherIndex(31), + /* [346] */ MatcherIndex(3), + /* [347] */ MatcherIndex(14), + /* [348] */ MatcherIndex(33), + /* [349] */ MatcherIndex(8), + /* [350] */ MatcherIndex(17), + /* [351] */ MatcherIndex(25), + /* [352] */ MatcherIndex(29), + /* [353] */ MatcherIndex(24), + /* [354] */ MatcherIndex(31), + /* [355] */ MatcherIndex(2), + /* [356] */ MatcherIndex(14), + /* [357] */ MatcherIndex(33), + /* [358] */ MatcherIndex(1), + /* [359] */ MatcherIndex(16), + /* [360] */ MatcherIndex(26), + /* [361] */ MatcherIndex(29), + /* [362] */ MatcherIndex(23), + /* [363] */ MatcherIndex(32), + /* [364] */ MatcherIndex(2), + /* [365] */ MatcherIndex(3), + /* [366] */ MatcherIndex(33), + /* [367] */ MatcherIndex(1), + /* [368] */ MatcherIndex(20), + /* [369] */ MatcherIndex(26), + /* [370] */ MatcherIndex(29), + /* [371] */ MatcherIndex(23), + /* [372] */ MatcherIndex(32), + /* [373] */ MatcherIndex(2), + /* [374] */ MatcherIndex(3), + /* [375] */ MatcherIndex(33), + /* [376] */ MatcherIndex(1), + /* [377] */ MatcherIndex(17), + /* [378] */ MatcherIndex(26), + /* [379] */ MatcherIndex(29), + /* [380] */ MatcherIndex(23), + /* [381] */ MatcherIndex(32), + /* [382] */ MatcherIndex(2), + /* [383] */ MatcherIndex(3), + /* [384] */ MatcherIndex(33), + /* [385] */ MatcherIndex(1), + /* [386] */ MatcherIndex(17), + /* [387] */ MatcherIndex(26), + /* [388] */ MatcherIndex(28), + /* [389] */ MatcherIndex(23), + /* [390] */ MatcherIndex(32), + /* [391] */ MatcherIndex(2), + /* [392] */ MatcherIndex(3), + /* [393] */ MatcherIndex(33), + /* [394] */ MatcherIndex(1), + /* [395] */ MatcherIndex(18), + /* [396] */ MatcherIndex(26), + /* [397] */ MatcherIndex(29), + /* [398] */ MatcherIndex(23), + /* [399] */ MatcherIndex(32), + /* [400] */ MatcherIndex(2), + /* [401] */ MatcherIndex(3), + /* [402] */ MatcherIndex(33), + /* [403] */ MatcherIndex(1), + /* [404] */ MatcherIndex(19), + /* [405] */ MatcherIndex(26), + /* [406] */ MatcherIndex(29), + /* [407] */ MatcherIndex(23), + /* [408] */ MatcherIndex(32), + /* [409] */ MatcherIndex(2), + /* [410] */ MatcherIndex(3), + /* [411] */ MatcherIndex(33), + /* [412] */ MatcherIndex(1), + /* [413] */ MatcherIndex(19), + /* [414] */ MatcherIndex(26), + /* [415] */ MatcherIndex(28), + /* [416] */ MatcherIndex(23), + /* [417] */ MatcherIndex(32), + /* [418] */ MatcherIndex(2), + /* [419] */ MatcherIndex(3), + /* [420] */ MatcherIndex(33), + /* [421] */ MatcherIndex(1), + /* [422] */ MatcherIndex(17), + /* [423] */ MatcherIndex(26), + /* [424] */ MatcherIndex(29), + /* [425] */ MatcherIndex(24), + /* [426] */ MatcherIndex(2), + /* [427] */ MatcherIndex(3), + /* [428] */ MatcherIndex(4), + /* [429] */ MatcherIndex(33), + /* [430] */ MatcherIndex(8), + /* [431] */ MatcherIndex(17), + /* [432] */ MatcherIndex(25), + /* [433] */ MatcherIndex(29), + /* [434] */ MatcherIndex(23), + /* [435] */ MatcherIndex(32), + /* [436] */ MatcherIndex(1), + /* [437] */ MatcherIndex(2), + /* [438] */ MatcherIndex(33), + /* [439] */ MatcherIndex(8), + /* [440] */ MatcherIndex(17), + /* [441] */ MatcherIndex(25), + /* [442] */ MatcherIndex(28), + /* [443] */ MatcherIndex(23), + /* [444] */ MatcherIndex(32), + /* [445] */ MatcherIndex(1), + /* [446] */ MatcherIndex(2), + /* [447] */ MatcherIndex(33), + /* [448] */ MatcherIndex(8), + /* [449] */ MatcherIndex(19), + /* [450] */ MatcherIndex(25), + /* [451] */ MatcherIndex(29), + /* [452] */ MatcherIndex(23), + /* [453] */ MatcherIndex(32), + /* [454] */ MatcherIndex(1), + /* [455] */ MatcherIndex(2), + /* [456] */ MatcherIndex(33), + /* [457] */ MatcherIndex(8), + /* [458] */ MatcherIndex(19), + /* [459] */ MatcherIndex(25), + /* [460] */ MatcherIndex(28), + /* [461] */ MatcherIndex(23), + /* [462] */ MatcherIndex(32), + /* [463] */ MatcherIndex(1), + /* [464] */ MatcherIndex(2), + /* [465] */ MatcherIndex(33), + /* [466] */ MatcherIndex(8), + /* [467] */ MatcherIndex(17), + /* [468] */ MatcherIndex(25), + /* [469] */ MatcherIndex(29), + /* [470] */ MatcherIndex(24), + /* [471] */ MatcherIndex(1), + /* [472] */ MatcherIndex(2), + /* [473] */ MatcherIndex(3), + /* [474] */ MatcherIndex(33), + /* [475] */ MatcherIndex(1), + /* [476] */ MatcherIndex(16), + /* [477] */ MatcherIndex(26), + /* [478] */ MatcherIndex(29), + /* [479] */ MatcherIndex(23), + /* [480] */ MatcherIndex(3), + /* [481] */ MatcherIndex(4), + /* [482] */ MatcherIndex(5), + /* [483] */ MatcherIndex(33), + /* [484] */ MatcherIndex(1), + /* [485] */ MatcherIndex(20), + /* [486] */ MatcherIndex(26), + /* [487] */ MatcherIndex(29), + /* [488] */ MatcherIndex(23), + /* [489] */ MatcherIndex(3), + /* [490] */ MatcherIndex(4), + /* [491] */ MatcherIndex(5), + /* [492] */ MatcherIndex(33), + /* [493] */ MatcherIndex(1), + /* [494] */ MatcherIndex(17), + /* [495] */ MatcherIndex(26), + /* [496] */ MatcherIndex(29), + /* [497] */ MatcherIndex(23), + /* [498] */ MatcherIndex(3), + /* [499] */ MatcherIndex(4), + /* [500] */ MatcherIndex(5), + /* [501] */ MatcherIndex(33), + /* [502] */ MatcherIndex(1), + /* [503] */ MatcherIndex(17), + /* [504] */ MatcherIndex(26), + /* [505] */ MatcherIndex(28), + /* [506] */ MatcherIndex(23), + /* [507] */ MatcherIndex(3), + /* [508] */ MatcherIndex(4), + /* [509] */ MatcherIndex(5), + /* [510] */ MatcherIndex(33), + /* [511] */ MatcherIndex(1), + /* [512] */ MatcherIndex(18), + /* [513] */ MatcherIndex(26), + /* [514] */ MatcherIndex(29), + /* [515] */ MatcherIndex(23), + /* [516] */ MatcherIndex(3), + /* [517] */ MatcherIndex(4), + /* [518] */ MatcherIndex(5), + /* [519] */ MatcherIndex(33), + /* [520] */ MatcherIndex(1), + /* [521] */ MatcherIndex(19), + /* [522] */ MatcherIndex(26), + /* [523] */ MatcherIndex(29), + /* [524] */ MatcherIndex(23), + /* [525] */ MatcherIndex(3), + /* [526] */ MatcherIndex(4), + /* [527] */ MatcherIndex(5), + /* [528] */ MatcherIndex(33), + /* [529] */ MatcherIndex(1), + /* [530] */ MatcherIndex(19), + /* [531] */ MatcherIndex(26), + /* [532] */ MatcherIndex(28), + /* [533] */ MatcherIndex(23), + /* [534] */ MatcherIndex(3), + /* [535] */ MatcherIndex(4), + /* [536] */ MatcherIndex(5), + /* [537] */ MatcherIndex(33), + /* [538] */ MatcherIndex(8), + /* [539] */ MatcherIndex(17), + /* [540] */ MatcherIndex(25), + /* [541] */ MatcherIndex(29), + /* [542] */ MatcherIndex(23), + /* [543] */ MatcherIndex(2), + /* [544] */ MatcherIndex(3), + /* [545] */ MatcherIndex(4), + /* [546] */ MatcherIndex(33), + /* [547] */ MatcherIndex(8), + /* [548] */ MatcherIndex(17), + /* [549] */ MatcherIndex(25), + /* [550] */ MatcherIndex(28), + /* [551] */ MatcherIndex(23), + /* [552] */ MatcherIndex(2), + /* [553] */ MatcherIndex(3), + /* [554] */ MatcherIndex(4), + /* [555] */ MatcherIndex(33), + /* [556] */ MatcherIndex(8), + /* [557] */ MatcherIndex(19), + /* [558] */ MatcherIndex(25), + /* [559] */ MatcherIndex(29), + /* [560] */ MatcherIndex(23), + /* [561] */ MatcherIndex(2), + /* [562] */ MatcherIndex(3), + /* [563] */ MatcherIndex(4), + /* [564] */ MatcherIndex(33), + /* [565] */ MatcherIndex(8), + /* [566] */ MatcherIndex(19), + /* [567] */ MatcherIndex(25), + /* [568] */ MatcherIndex(28), + /* [569] */ MatcherIndex(23), + /* [570] */ MatcherIndex(2), + /* [571] */ MatcherIndex(3), + /* [572] */ MatcherIndex(4), + /* [573] */ MatcherIndex(33), + /* [574] */ MatcherIndex(1), + /* [575] */ MatcherIndex(22), + /* [576] */ MatcherIndex(2), + /* [577] */ MatcherIndex(3), + /* [578] */ MatcherIndex(23), + /* [579] */ MatcherIndex(4), + /* [580] */ MatcherIndex(5), + /* [581] */ MatcherIndex(6), + /* [582] */ MatcherIndex(33), + /* [583] */ MatcherIndex(1), + /* [584] */ MatcherIndex(17), + /* [585] */ MatcherIndex(2), + /* [586] */ MatcherIndex(3), + /* [587] */ MatcherIndex(24), + /* [588] */ MatcherIndex(4), + /* [589] */ MatcherIndex(5), + /* [590] */ MatcherIndex(6), + /* [591] */ MatcherIndex(33), + /* [592] */ MatcherIndex(8), + /* [593] */ MatcherIndex(16), + /* [594] */ MatcherIndex(26), + /* [595] */ MatcherIndex(29), + /* [596] */ MatcherIndex(23), + /* [597] */ MatcherIndex(32), + /* [598] */ MatcherIndex(0), + /* [599] */ MatcherIndex(1), + /* [600] */ MatcherIndex(33), + /* [601] */ MatcherIndex(8), + /* [602] */ MatcherIndex(20), + /* [603] */ MatcherIndex(26), + /* [604] */ MatcherIndex(29), + /* [605] */ MatcherIndex(23), + /* [606] */ MatcherIndex(32), + /* [607] */ MatcherIndex(0), + /* [608] */ MatcherIndex(1), + /* [609] */ MatcherIndex(33), + /* [610] */ MatcherIndex(10), + /* [611] */ MatcherIndex(16), + /* [612] */ MatcherIndex(26), + /* [613] */ MatcherIndex(29), + /* [614] */ MatcherIndex(23), + /* [615] */ MatcherIndex(32), + /* [616] */ MatcherIndex(0), + /* [617] */ MatcherIndex(1), + /* [618] */ MatcherIndex(33), + /* [619] */ MatcherIndex(10), + /* [620] */ MatcherIndex(20), + /* [621] */ MatcherIndex(26), + /* [622] */ MatcherIndex(29), + /* [623] */ MatcherIndex(23), + /* [624] */ MatcherIndex(32), + /* [625] */ MatcherIndex(0), + /* [626] */ MatcherIndex(1), + /* [627] */ MatcherIndex(33), + /* [628] */ MatcherIndex(11), + /* [629] */ MatcherIndex(16), + /* [630] */ MatcherIndex(26), + /* [631] */ MatcherIndex(29), + /* [632] */ MatcherIndex(23), + /* [633] */ MatcherIndex(32), + /* [634] */ MatcherIndex(0), + /* [635] */ MatcherIndex(1), + /* [636] */ MatcherIndex(33), + /* [637] */ MatcherIndex(11), + /* [638] */ MatcherIndex(20), + /* [639] */ MatcherIndex(26), + /* [640] */ MatcherIndex(29), + /* [641] */ MatcherIndex(23), + /* [642] */ MatcherIndex(32), + /* [643] */ MatcherIndex(0), + /* [644] */ MatcherIndex(1), + /* [645] */ MatcherIndex(33), + /* [646] */ MatcherIndex(8), + /* [647] */ MatcherIndex(17), + /* [648] */ MatcherIndex(26), + /* [649] */ MatcherIndex(29), + /* [650] */ MatcherIndex(23), + /* [651] */ MatcherIndex(32), + /* [652] */ MatcherIndex(0), + /* [653] */ MatcherIndex(1), + /* [654] */ MatcherIndex(33), + /* [655] */ MatcherIndex(10), + /* [656] */ MatcherIndex(17), + /* [657] */ MatcherIndex(26), + /* [658] */ MatcherIndex(29), + /* [659] */ MatcherIndex(23), + /* [660] */ MatcherIndex(32), + /* [661] */ MatcherIndex(0), + /* [662] */ MatcherIndex(1), + /* [663] */ MatcherIndex(33), + /* [664] */ MatcherIndex(11), + /* [665] */ MatcherIndex(17), + /* [666] */ MatcherIndex(26), + /* [667] */ MatcherIndex(29), + /* [668] */ MatcherIndex(23), + /* [669] */ MatcherIndex(32), + /* [670] */ MatcherIndex(0), + /* [671] */ MatcherIndex(1), + /* [672] */ MatcherIndex(33), + /* [673] */ MatcherIndex(8), + /* [674] */ MatcherIndex(17), + /* [675] */ MatcherIndex(26), + /* [676] */ MatcherIndex(28), + /* [677] */ MatcherIndex(23), + /* [678] */ MatcherIndex(32), + /* [679] */ MatcherIndex(0), + /* [680] */ MatcherIndex(1), + /* [681] */ MatcherIndex(33), + /* [682] */ MatcherIndex(10), + /* [683] */ MatcherIndex(17), + /* [684] */ MatcherIndex(26), + /* [685] */ MatcherIndex(28), + /* [686] */ MatcherIndex(23), + /* [687] */ MatcherIndex(32), + /* [688] */ MatcherIndex(0), + /* [689] */ MatcherIndex(1), + /* [690] */ MatcherIndex(33), + /* [691] */ MatcherIndex(11), + /* [692] */ MatcherIndex(17), + /* [693] */ MatcherIndex(26), + /* [694] */ MatcherIndex(28), + /* [695] */ MatcherIndex(23), + /* [696] */ MatcherIndex(32), + /* [697] */ MatcherIndex(0), + /* [698] */ MatcherIndex(1), + /* [699] */ MatcherIndex(33), + /* [700] */ MatcherIndex(8), + /* [701] */ MatcherIndex(18), + /* [702] */ MatcherIndex(26), + /* [703] */ MatcherIndex(29), + /* [704] */ MatcherIndex(23), + /* [705] */ MatcherIndex(32), + /* [706] */ MatcherIndex(0), + /* [707] */ MatcherIndex(1), + /* [708] */ MatcherIndex(33), + /* [709] */ MatcherIndex(10), + /* [710] */ MatcherIndex(18), + /* [711] */ MatcherIndex(26), + /* [712] */ MatcherIndex(29), + /* [713] */ MatcherIndex(23), + /* [714] */ MatcherIndex(32), + /* [715] */ MatcherIndex(0), + /* [716] */ MatcherIndex(1), + /* [717] */ MatcherIndex(33), + /* [718] */ MatcherIndex(11), + /* [719] */ MatcherIndex(18), + /* [720] */ MatcherIndex(26), + /* [721] */ MatcherIndex(29), + /* [722] */ MatcherIndex(23), + /* [723] */ MatcherIndex(32), + /* [724] */ MatcherIndex(0), + /* [725] */ MatcherIndex(1), + /* [726] */ MatcherIndex(33), + /* [727] */ MatcherIndex(1), + /* [728] */ MatcherIndex(21), + /* [729] */ MatcherIndex(26), + /* [730] */ MatcherIndex(29), + /* [731] */ MatcherIndex(23), + /* [732] */ MatcherIndex(32), + /* [733] */ MatcherIndex(0), + /* [734] */ MatcherIndex(3), + /* [735] */ MatcherIndex(33), + /* [736] */ MatcherIndex(8), + /* [737] */ MatcherIndex(16), + /* [738] */ MatcherIndex(26), + /* [739] */ MatcherIndex(29), + /* [740] */ MatcherIndex(23), + /* [741] */ MatcherIndex(32), + /* [742] */ MatcherIndex(10), + /* [743] */ MatcherIndex(15), + /* [744] */ MatcherIndex(8), + /* [745] */ MatcherIndex(33), + /* [746] */ MatcherIndex(8), + /* [747] */ MatcherIndex(20), + /* [748] */ MatcherIndex(26), + /* [749] */ MatcherIndex(29), + /* [750] */ MatcherIndex(23), + /* [751] */ MatcherIndex(32), + /* [752] */ MatcherIndex(10), + /* [753] */ MatcherIndex(15), + /* [754] */ MatcherIndex(1), + /* [755] */ MatcherIndex(33), + /* [756] */ MatcherIndex(10), + /* [757] */ MatcherIndex(16), + /* [758] */ MatcherIndex(26), + /* [759] */ MatcherIndex(29), + /* [760] */ MatcherIndex(23), + /* [761] */ MatcherIndex(32), + /* [762] */ MatcherIndex(11), + /* [763] */ MatcherIndex(15), + /* [764] */ MatcherIndex(0), + /* [765] */ MatcherIndex(33), + /* [766] */ MatcherIndex(10), + /* [767] */ MatcherIndex(20), + /* [768] */ MatcherIndex(26), + /* [769] */ MatcherIndex(29), + /* [770] */ MatcherIndex(23), + /* [771] */ MatcherIndex(32), + /* [772] */ MatcherIndex(11), + /* [773] */ MatcherIndex(15), + /* [774] */ MatcherIndex(2), + /* [775] */ MatcherIndex(33), + /* [776] */ MatcherIndex(11), + /* [777] */ MatcherIndex(16), + /* [778] */ MatcherIndex(26), + /* [779] */ MatcherIndex(29), + /* [780] */ MatcherIndex(23), + /* [781] */ MatcherIndex(32), + /* [782] */ MatcherIndex(12), + /* [783] */ MatcherIndex(15), + /* [784] */ MatcherIndex(33), + /* [785] */ MatcherIndex(11), + /* [786] */ MatcherIndex(20), + /* [787] */ MatcherIndex(26), + /* [788] */ MatcherIndex(29), + /* [789] */ MatcherIndex(23), + /* [790] */ MatcherIndex(32), + /* [791] */ MatcherIndex(12), + /* [792] */ MatcherIndex(15), + /* [793] */ MatcherIndex(33), + /* [794] */ MatcherIndex(8), + /* [795] */ MatcherIndex(17), + /* [796] */ MatcherIndex(26), + /* [797] */ MatcherIndex(29), + /* [798] */ MatcherIndex(23), + /* [799] */ MatcherIndex(32), + /* [800] */ MatcherIndex(10), + /* [801] */ MatcherIndex(15), + /* [802] */ MatcherIndex(33), + /* [803] */ MatcherIndex(10), + /* [804] */ MatcherIndex(17), + /* [805] */ MatcherIndex(26), + /* [806] */ MatcherIndex(29), + /* [807] */ MatcherIndex(23), + /* [808] */ MatcherIndex(32), + /* [809] */ MatcherIndex(11), + /* [810] */ MatcherIndex(15), + /* [811] */ MatcherIndex(33), + /* [812] */ MatcherIndex(11), + /* [813] */ MatcherIndex(17), + /* [814] */ MatcherIndex(26), + /* [815] */ MatcherIndex(29), + /* [816] */ MatcherIndex(23), + /* [817] */ MatcherIndex(32), + /* [818] */ MatcherIndex(12), + /* [819] */ MatcherIndex(15), + /* [820] */ MatcherIndex(33), + /* [821] */ MatcherIndex(8), + /* [822] */ MatcherIndex(17), + /* [823] */ MatcherIndex(26), + /* [824] */ MatcherIndex(28), + /* [825] */ MatcherIndex(23), + /* [826] */ MatcherIndex(32), + /* [827] */ MatcherIndex(10), + /* [828] */ MatcherIndex(15), + /* [829] */ MatcherIndex(33), + /* [830] */ MatcherIndex(10), + /* [831] */ MatcherIndex(17), + /* [832] */ MatcherIndex(26), + /* [833] */ MatcherIndex(28), + /* [834] */ MatcherIndex(23), + /* [835] */ MatcherIndex(32), + /* [836] */ MatcherIndex(11), + /* [837] */ MatcherIndex(15), + /* [838] */ MatcherIndex(33), + /* [839] */ MatcherIndex(11), + /* [840] */ MatcherIndex(17), + /* [841] */ MatcherIndex(26), + /* [842] */ MatcherIndex(28), + /* [843] */ MatcherIndex(23), + /* [844] */ MatcherIndex(32), + /* [845] */ MatcherIndex(12), + /* [846] */ MatcherIndex(15), + /* [847] */ MatcherIndex(33), + /* [848] */ MatcherIndex(8), + /* [849] */ MatcherIndex(18), + /* [850] */ MatcherIndex(26), + /* [851] */ MatcherIndex(29), + /* [852] */ MatcherIndex(23), + /* [853] */ MatcherIndex(32), + /* [854] */ MatcherIndex(10), + /* [855] */ MatcherIndex(15), + /* [856] */ MatcherIndex(33), + /* [857] */ MatcherIndex(10), + /* [858] */ MatcherIndex(18), + /* [859] */ MatcherIndex(26), + /* [860] */ MatcherIndex(29), + /* [861] */ MatcherIndex(23), + /* [862] */ MatcherIndex(32), + /* [863] */ MatcherIndex(11), + /* [864] */ MatcherIndex(15), + /* [865] */ MatcherIndex(33), + /* [866] */ MatcherIndex(11), + /* [867] */ MatcherIndex(18), + /* [868] */ MatcherIndex(26), + /* [869] */ MatcherIndex(29), + /* [870] */ MatcherIndex(23), + /* [871] */ MatcherIndex(32), + /* [872] */ MatcherIndex(12), + /* [873] */ MatcherIndex(15), + /* [874] */ MatcherIndex(33), + /* [875] */ MatcherIndex(1), + /* [876] */ MatcherIndex(16), + /* [877] */ MatcherIndex(26), + /* [878] */ MatcherIndex(29), + /* [879] */ MatcherIndex(23), + /* [880] */ MatcherIndex(31), + /* [881] */ MatcherIndex(2), + /* [882] */ MatcherIndex(14), + /* [883] */ MatcherIndex(33), + /* [884] */ MatcherIndex(1), + /* [885] */ MatcherIndex(17), + /* [886] */ MatcherIndex(26), + /* [887] */ MatcherIndex(30), + /* [888] */ MatcherIndex(23), + /* [889] */ MatcherIndex(31), + /* [890] */ MatcherIndex(2), + /* [891] */ MatcherIndex(14), + /* [892] */ MatcherIndex(33), + /* [893] */ MatcherIndex(1), + /* [894] */ MatcherIndex(18), + /* [895] */ MatcherIndex(26), + /* [896] */ MatcherIndex(29), + /* [897] */ MatcherIndex(23), + /* [898] */ MatcherIndex(31), + /* [899] */ MatcherIndex(2), + /* [900] */ MatcherIndex(14), + /* [901] */ MatcherIndex(33), + /* [902] */ MatcherIndex(1), + /* [903] */ MatcherIndex(19), + /* [904] */ MatcherIndex(26), + /* [905] */ MatcherIndex(30), + /* [906] */ MatcherIndex(23), + /* [907] */ MatcherIndex(31), + /* [908] */ MatcherIndex(2), + /* [909] */ MatcherIndex(14), + /* [910] */ MatcherIndex(33), + /* [911] */ MatcherIndex(8), + /* [912] */ MatcherIndex(17), + /* [913] */ MatcherIndex(25), + /* [914] */ MatcherIndex(30), + /* [915] */ MatcherIndex(23), + /* [916] */ MatcherIndex(31), + /* [917] */ MatcherIndex(1), + /* [918] */ MatcherIndex(14), + /* [919] */ MatcherIndex(33), + /* [920] */ MatcherIndex(8), + /* [921] */ MatcherIndex(19), + /* [922] */ MatcherIndex(25), + /* [923] */ MatcherIndex(30), + /* [924] */ MatcherIndex(23), + /* [925] */ MatcherIndex(31), + /* [926] */ MatcherIndex(1), + /* [927] */ MatcherIndex(14), + /* [928] */ MatcherIndex(33), + /* [929] */ MatcherIndex(1), + /* [930] */ MatcherIndex(16), + /* [931] */ MatcherIndex(26), + /* [932] */ MatcherIndex(29), + /* [933] */ MatcherIndex(23), + /* [934] */ MatcherIndex(31), + /* [935] */ MatcherIndex(3), + /* [936] */ MatcherIndex(14), + /* [937] */ MatcherIndex(33), + /* [938] */ MatcherIndex(1), + /* [939] */ MatcherIndex(17), + /* [940] */ MatcherIndex(26), + /* [941] */ MatcherIndex(30), + /* [942] */ MatcherIndex(23), + /* [943] */ MatcherIndex(31), + /* [944] */ MatcherIndex(3), + /* [945] */ MatcherIndex(14), + /* [946] */ MatcherIndex(33), + /* [947] */ MatcherIndex(1), + /* [948] */ MatcherIndex(18), + /* [949] */ MatcherIndex(26), + /* [950] */ MatcherIndex(29), + /* [951] */ MatcherIndex(23), + /* [952] */ MatcherIndex(31), + /* [953] */ MatcherIndex(3), + /* [954] */ MatcherIndex(14), + /* [955] */ MatcherIndex(33), + /* [956] */ MatcherIndex(1), + /* [957] */ MatcherIndex(19), + /* [958] */ MatcherIndex(26), + /* [959] */ MatcherIndex(30), + /* [960] */ MatcherIndex(23), + /* [961] */ MatcherIndex(31), + /* [962] */ MatcherIndex(3), + /* [963] */ MatcherIndex(14), + /* [964] */ MatcherIndex(33), + /* [965] */ MatcherIndex(8), + /* [966] */ MatcherIndex(17), + /* [967] */ MatcherIndex(25), + /* [968] */ MatcherIndex(30), + /* [969] */ MatcherIndex(23), + /* [970] */ MatcherIndex(31), + /* [971] */ MatcherIndex(2), + /* [972] */ MatcherIndex(14), + /* [973] */ MatcherIndex(33), + /* [974] */ MatcherIndex(8), + /* [975] */ MatcherIndex(19), + /* [976] */ MatcherIndex(25), + /* [977] */ MatcherIndex(30), + /* [978] */ MatcherIndex(23), + /* [979] */ MatcherIndex(31), + /* [980] */ MatcherIndex(2), + /* [981] */ MatcherIndex(14), + /* [982] */ MatcherIndex(31), + /* [983] */ MatcherIndex(2), + /* [984] */ MatcherIndex(26), + /* [985] */ MatcherIndex(1), + /* [986] */ MatcherIndex(0), + /* [987] */ MatcherIndex(15), + /* [988] */ MatcherIndex(31), + /* [989] */ MatcherIndex(3), + /* [990] */ MatcherIndex(26), + /* [991] */ MatcherIndex(2), + /* [992] */ MatcherIndex(1), + /* [993] */ MatcherIndex(15), + /* [994] */ MatcherIndex(31), + /* [995] */ MatcherIndex(2), + /* [996] */ MatcherIndex(28), + /* [997] */ MatcherIndex(0), + /* [998] */ MatcherIndex(13), + /* [999] */ MatcherIndex(35), + /* [1000] */ MatcherIndex(1), + /* [1001] */ MatcherIndex(2), + /* [1002] */ MatcherIndex(3), + /* [1003] */ MatcherIndex(4), + /* [1004] */ MatcherIndex(35), + /* [1005] */ MatcherIndex(0), + /* [1006] */ MatcherIndex(1), + /* [1007] */ MatcherIndex(2), + /* [1008] */ MatcherIndex(3), + /* [1009] */ MatcherIndex(35), + /* [1010] */ MatcherIndex(35), + /* [1011] */ MatcherIndex(1), + /* [1012] */ MatcherIndex(2), + /* [1013] */ MatcherIndex(3), + /* [1014] */ MatcherIndex(35), + /* [1015] */ MatcherIndex(33), + /* [1016] */ MatcherIndex(0), + /* [1017] */ MatcherIndex(4), + /* [1018] */ MatcherIndex(3), + /* [1019] */ MatcherIndex(35), + /* [1020] */ MatcherIndex(34), + /* [1021] */ MatcherIndex(0), + /* [1022] */ MatcherIndex(2), + /* [1023] */ MatcherIndex(4), + /* [1024] */ MatcherIndex(35), + /* [1025] */ MatcherIndex(0), + /* [1026] */ MatcherIndex(12), + /* [1027] */ MatcherIndex(1), + /* [1028] */ MatcherIndex(2), + /* [1029] */ MatcherIndex(35), + /* [1030] */ MatcherIndex(0), + /* [1031] */ MatcherIndex(13), + /* [1032] */ MatcherIndex(1), + /* [1033] */ MatcherIndex(2), + /* [1034] */ MatcherIndex(31), + /* [1035] */ MatcherIndex(7), + /* [1036] */ MatcherIndex(32), + /* [1037] */ MatcherIndex(1), + /* [1038] */ MatcherIndex(31), + /* [1039] */ MatcherIndex(2), + /* [1040] */ MatcherIndex(0), + /* [1041] */ MatcherIndex(14), + /* [1042] */ MatcherIndex(31), + /* [1043] */ MatcherIndex(2), + /* [1044] */ MatcherIndex(0), + /* [1045] */ MatcherIndex(15), + /* [1046] */ MatcherIndex(27), + /* [1047] */ MatcherIndex(2), + /* [1048] */ MatcherIndex(3), + /* [1049] */ MatcherIndex(0), + /* [1050] */ MatcherIndex(27), + /* [1051] */ MatcherIndex(1), + /* [1052] */ MatcherIndex(3), + /* [1053] */ MatcherIndex(0), + /* [1054] */ MatcherIndex(27), + /* [1055] */ MatcherIndex(2), + /* [1056] */ MatcherIndex(1), + /* [1057] */ MatcherIndex(0), + /* [1058] */ MatcherIndex(27), + /* [1059] */ MatcherIndex(1), + /* [1060] */ MatcherIndex(2), + /* [1061] */ MatcherIndex(0), + /* [1062] */ MatcherIndex(31), + /* [1063] */ MatcherIndex(1), + /* [1064] */ MatcherIndex(0), + /* [1065] */ MatcherIndex(15), + /* [1066] */ MatcherIndex(31), + /* [1067] */ MatcherIndex(2), + /* [1068] */ MatcherIndex(1), + /* [1069] */ MatcherIndex(15), + /* [1070] */ MatcherIndex(31), + /* [1071] */ MatcherIndex(8), + /* [1072] */ MatcherIndex(2), + /* [1073] */ MatcherIndex(14), + /* [1074] */ MatcherIndex(31), + /* [1075] */ MatcherIndex(8), + /* [1076] */ MatcherIndex(10), + /* [1077] */ MatcherIndex(14), + /* [1078] */ MatcherIndex(31), + /* [1079] */ MatcherIndex(8), + /* [1080] */ MatcherIndex(11), + /* [1081] */ MatcherIndex(14), + /* [1082] */ MatcherIndex(31), + /* [1083] */ MatcherIndex(8), + /* [1084] */ MatcherIndex(1), + /* [1085] */ MatcherIndex(15), + /* [1086] */ MatcherIndex(31), + /* [1087] */ MatcherIndex(8), + /* [1088] */ MatcherIndex(10), + /* [1089] */ MatcherIndex(15), + /* [1090] */ MatcherIndex(31), + /* [1091] */ MatcherIndex(8), + /* [1092] */ MatcherIndex(11), + /* [1093] */ MatcherIndex(15), + /* [1094] */ MatcherIndex(26), + /* [1095] */ MatcherIndex(0), + /* [1096] */ MatcherIndex(1), + /* [1097] */ MatcherIndex(26), + /* [1098] */ MatcherIndex(2), + /* [1099] */ MatcherIndex(8), + /* [1100] */ MatcherIndex(26), + /* [1101] */ MatcherIndex(3), + /* [1102] */ MatcherIndex(8), + /* [1103] */ MatcherIndex(26), + /* [1104] */ MatcherIndex(1), + /* [1105] */ MatcherIndex(8), + /* [1106] */ MatcherIndex(26), + /* [1107] */ MatcherIndex(2), + /* [1108] */ MatcherIndex(0), + /* [1109] */ MatcherIndex(26), + /* [1110] */ MatcherIndex(0), + /* [1111] */ MatcherIndex(7), + /* [1112] */ MatcherIndex(26), + /* [1113] */ MatcherIndex(3), + /* [1114] */ MatcherIndex(0), + /* [1115] */ MatcherIndex(26), + /* [1116] */ MatcherIndex(3), + /* [1117] */ MatcherIndex(1), + /* [1118] */ MatcherIndex(26), + /* [1119] */ MatcherIndex(3), + /* [1120] */ MatcherIndex(2), + /* [1121] */ MatcherIndex(26), + /* [1122] */ MatcherIndex(4), + /* [1123] */ MatcherIndex(0), + /* [1124] */ MatcherIndex(26), + /* [1125] */ MatcherIndex(4), + /* [1126] */ MatcherIndex(1), + /* [1127] */ MatcherIndex(26), + /* [1128] */ MatcherIndex(4), + /* [1129] */ MatcherIndex(2), + /* [1130] */ MatcherIndex(26), + /* [1131] */ MatcherIndex(4), + /* [1132] */ MatcherIndex(3), + /* [1133] */ MatcherIndex(26), + /* [1134] */ MatcherIndex(0), + /* [1135] */ MatcherIndex(2), + /* [1136] */ MatcherIndex(26), + /* [1137] */ MatcherIndex(2), + /* [1138] */ MatcherIndex(7), + /* [1139] */ MatcherIndex(16), + /* [1140] */ MatcherIndex(8), + /* [1141] */ MatcherIndex(16), + /* [1142] */ MatcherIndex(0), + /* [1143] */ MatcherIndex(16), + /* [1144] */ MatcherIndex(10), + /* [1145] */ MatcherIndex(16), + /* [1146] */ MatcherIndex(11), + /* [1147] */ MatcherIndex(16), + /* [1148] */ MatcherIndex(1), + /* [1149] */ MatcherIndex(17), + /* [1150] */ MatcherIndex(0), + /* [1151] */ MatcherIndex(21), + /* [1152] */ MatcherIndex(0), + /* [1153] */ MatcherIndex(25), + /* [1154] */ MatcherIndex(0), + /* [1155] */ MatcherIndex(37), + /* [1156] */ MatcherIndex(36), + /* [1157] */ MatcherIndex(38), + /* [1158] */ MatcherIndex(43), + /* [1159] */ MatcherIndex(40), + /* [1160] */ MatcherIndex(9), + /* [1161] */ MatcherIndex(39), + /* [1162] */ MatcherIndex(42), + /* [1163] */ MatcherIndex(41), +}; + +static_assert(MatcherIndicesIndex::CanIndex(kMatcherIndices), + "MatcherIndicesIndex is not large enough to index kMatcherIndices"); + +constexpr ParameterInfo kParameters[] = { + { + /* [0] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(994), + }, + { + /* [1] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [2] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [3] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [4] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [5] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [6] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [7] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [8] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1042), + }, + { + /* [9] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [10] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [11] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [12] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [13] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [14] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [15] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [16] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(62), + }, + { + /* [17] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [18] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1100), + }, + { + /* [19] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [20] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [21] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [22] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [23] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [24] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [25] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [26] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [27] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [28] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [29] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [30] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [31] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [32] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [33] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [34] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [35] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [36] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [37] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [38] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [39] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [40] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [41] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [42] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [43] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [44] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [45] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [46] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [47] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [48] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [49] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [50] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [51] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [52] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [53] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [54] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [55] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [56] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [57] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [58] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [59] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [60] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [61] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [62] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [63] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [64] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [65] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [66] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [67] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [68] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [69] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [70] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [71] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [72] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [73] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [74] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [75] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [76] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [77] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(284), + }, + { + /* [78] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [79] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [80] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [81] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [82] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [83] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(284), + }, + { + /* [84] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [85] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [86] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [87] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [88] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [89] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(0), + }, + { + /* [90] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [91] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [92] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [93] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [94] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(11), + }, + { + /* [95] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [96] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [97] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [98] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [99] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(54), + }, + { + /* [100] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [101] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [102] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [103] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [104] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(74), + }, + { + /* [105] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [106] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [107] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [108] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [109] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(114), + }, + { + /* [110] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [111] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [112] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [113] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [114] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(134), + }, + { + /* [115] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [116] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [117] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [118] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [119] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [120] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1100), + }, + { + /* [121] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [122] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [123] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [124] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [125] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [126] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [127] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [128] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [129] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [130] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [131] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [132] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [133] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [134] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [135] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [136] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [137] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [138] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [139] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [140] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [141] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [142] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [143] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [144] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [145] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [146] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [147] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [148] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [149] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [150] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [151] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [152] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [153] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [154] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [155] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [156] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [157] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [158] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [159] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [160] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [161] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [162] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [163] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [164] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [165] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [166] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [167] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [168] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [169] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [170] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1100), + }, + { + /* [171] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [172] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [173] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [174] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [175] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [176] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [177] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [178] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [179] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [180] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [181] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [182] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [183] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [184] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [185] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [186] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [187] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [188] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [189] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [190] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [191] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [192] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [193] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [194] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(194), + }, + { + /* [195] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [196] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [197] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [198] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [199] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(194), + }, + { + /* [200] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [201] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [202] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [203] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [204] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [205] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [206] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [207] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [208] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [209] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [210] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [211] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [212] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [213] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [214] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(214), + }, + { + /* [215] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [216] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [217] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [218] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [219] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(214), + }, + { + /* [220] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [221] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [222] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [223] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [224] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(224), + }, + { + /* [225] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [226] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [227] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [228] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [229] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [230] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [231] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [232] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [233] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [234] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(124), + }, + { + /* [235] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [236] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [237] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [238] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [239] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(124), + }, + { + /* [240] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [241] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [242] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [243] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [244] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [245] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [246] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [247] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [248] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [249] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [250] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [251] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [252] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [253] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [254] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [255] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [256] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [257] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [258] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [259] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [260] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [261] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [262] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [263] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [264] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [265] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [266] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [267] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [268] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [269] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [270] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [271] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [272] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [273] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [274] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(0), + }, + { + /* [275] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [276] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [277] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [278] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [279] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(0), + }, + { + /* [280] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [281] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [282] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [283] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [284] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(274), + }, + { + /* [285] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [286] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [287] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [288] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [289] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(284), + }, + { + /* [290] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [291] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [292] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [293] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [294] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(284), + }, + { + /* [295] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [296] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [297] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [298] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [299] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(0), + }, + { + /* [300] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1103), + }, + { + /* [301] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [302] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [303] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [304] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(11), + }, + { + /* [305] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [306] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [307] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [308] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [309] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(11), + }, + { + /* [310] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [311] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [312] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [313] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [314] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(22), + }, + { + /* [315] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [316] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [317] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [318] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [319] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(22), + }, + { + /* [320] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [321] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [322] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [323] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [324] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(33), + }, + { + /* [325] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [326] */ + /* usage */ core::ParameterUsage::kDref, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [327] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [328] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [329] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1082), + }, + { + /* [330] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1004), + }, + { + /* [331] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [332] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [333] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [334] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1086), + }, + { + /* [335] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1004), + }, + { + /* [336] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [337] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [338] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [339] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1090), + }, + { + /* [340] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1004), + }, + { + /* [341] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [342] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [343] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [344] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(994), + }, + { + /* [345] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [346] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [347] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [348] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1042), + }, + { + /* [349] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [350] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [351] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [352] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(321), + }, + { + /* [353] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [354] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [355] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [356] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(55), + }, + { + /* [357] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [358] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [359] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [360] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(75), + }, + { + /* [361] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [362] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [363] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [364] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(330), + }, + { + /* [365] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [366] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [367] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [368] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(339), + }, + { + /* [369] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [370] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [371] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [372] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(115), + }, + { + /* [373] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [374] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [375] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [376] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(135), + }, + { + /* [377] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [378] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [379] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [380] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(348), + }, + { + /* [381] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [382] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [383] */ + /* usage */ core::ParameterUsage::kSample, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [384] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [385] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [386] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [387] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [388] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [389] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [390] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [391] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [392] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(84), + }, + { + /* [393] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [394] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [395] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [396] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(94), + }, + { + /* [397] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [398] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [399] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [400] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [401] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(9), + }, + { + /* [402] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [403] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [404] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(124), + }, + { + /* [405] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [406] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [407] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [408] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(144), + }, + { + /* [409] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [410] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [411] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [412] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(154), + }, + { + /* [413] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [414] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [415] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [416] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [417] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [418] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [419] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [420] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [421] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1100), + }, + { + /* [422] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [423] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [424] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [425] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [426] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [427] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [428] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [429] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [430] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [431] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [432] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [433] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [434] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [435] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [436] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(64), + }, + { + /* [437] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [438] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [439] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [440] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(194), + }, + { + /* [441] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [442] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [443] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [444] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(194), + }, + { + /* [445] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [446] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [447] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [448] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [449] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [450] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [451] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [452] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(204), + }, + { + /* [453] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [454] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [455] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [456] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(214), + }, + { + /* [457] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [458] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [459] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [460] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(214), + }, + { + /* [461] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [462] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [463] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [464] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(224), + }, + { + /* [465] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [466] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [467] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [468] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [469] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [470] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [471] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [472] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(124), + }, + { + /* [473] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [474] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [475] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [476] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(124), + }, + { + /* [477] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [478] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [479] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [480] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [481] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [482] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [483] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [484] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [485] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [486] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [487] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [488] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [489] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [490] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [491] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [492] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(44), + }, + { + /* [493] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [494] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [495] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [496] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [497] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [498] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [499] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [500] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(104), + }, + { + /* [501] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [502] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [503] */ + /* usage */ core::ParameterUsage::kConstOffset, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [504] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(164), + }, + { + /* [505] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [506] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [507] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [508] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [509] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [510] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [511] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [512] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [513] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [514] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [515] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [516] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(184), + }, + { + /* [517] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [518] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [519] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [520] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(194), + }, + { + /* [521] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [522] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [523] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [524] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(194), + }, + { + /* [525] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [526] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [527] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [528] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(214), + }, + { + /* [529] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [530] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [531] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [532] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(214), + }, + { + /* [533] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [534] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [535] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [536] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(224), + }, + { + /* [537] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [538] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [539] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [540] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(234), + }, + { + /* [541] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1103), + }, + { + /* [542] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [543] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [544] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(254), + }, + { + /* [545] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [546] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [547] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [548] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(254), + }, + { + /* [549] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [550] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [551] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [552] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(244), + }, + { + /* [553] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [554] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [555] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [556] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(244), + }, + { + /* [557] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [558] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [559] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [560] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(264), + }, + { + /* [561] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [562] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [563] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [564] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [565] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [566] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [567] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [568] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(174), + }, + { + /* [569] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [570] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [571] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [572] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(234), + }, + { + /* [573] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(743), + }, + { + /* [574] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [575] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [576] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(234), + }, + { + /* [577] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [578] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [579] */ + /* usage */ core::ParameterUsage::kLod, + /* matcher_indices */ MatcherIndicesIndex(2), + }, + { + /* [580] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(735), + }, + { + /* [581] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [582] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [583] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [584] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(745), + }, + { + /* [585] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [586] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [587] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [588] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(755), + }, + { + /* [589] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [590] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1143), + }, + { + /* [591] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [592] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(765), + }, + { + /* [593] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [594] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1143), + }, + { + /* [595] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [596] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(775), + }, + { + /* [597] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [598] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1145), + }, + { + /* [599] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [600] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(784), + }, + { + /* [601] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [602] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1145), + }, + { + /* [603] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [604] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(793), + }, + { + /* [605] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [606] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [607] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [608] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(802), + }, + { + /* [609] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [610] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1143), + }, + { + /* [611] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [612] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(811), + }, + { + /* [613] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [614] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1145), + }, + { + /* [615] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [616] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(820), + }, + { + /* [617] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [618] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [619] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [620] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(829), + }, + { + /* [621] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [622] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1143), + }, + { + /* [623] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [624] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(838), + }, + { + /* [625] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [626] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1145), + }, + { + /* [627] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [628] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(847), + }, + { + /* [629] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [630] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1139), + }, + { + /* [631] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [632] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(856), + }, + { + /* [633] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [634] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1143), + }, + { + /* [635] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [636] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(865), + }, + { + /* [637] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [638] */ + /* usage */ core::ParameterUsage::kTexel, + /* matcher_indices */ MatcherIndicesIndex(1145), + }, + { + /* [639] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [640] */ + /* usage */ core::ParameterUsage::kBase, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [641] */ + /* usage */ core::ParameterUsage::kInsert, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [642] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [643] */ + /* usage */ core::ParameterUsage::kCount, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [644] */ + /* usage */ core::ParameterUsage::kBase, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [645] */ + /* usage */ core::ParameterUsage::kInsert, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [646] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [647] */ + /* usage */ core::ParameterUsage::kCount, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [648] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1070), + }, + { + /* [649] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [650] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [651] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [652] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1074), + }, + { + /* [653] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [654] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [655] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [656] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1078), + }, + { + /* [657] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [658] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [659] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [660] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1014), + }, + { + /* [661] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1019), + }, + { + /* [662] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1009), + }, + { + /* [663] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [664] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1038), + }, + { + /* [665] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [666] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [667] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(294), + }, + { + /* [668] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [669] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [670] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(45), + }, + { + /* [671] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [672] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [673] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(65), + }, + { + /* [674] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [675] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [676] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [677] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(753), + }, + { + /* [678] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [679] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(303), + }, + { + /* [680] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(31), + }, + { + /* [681] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [682] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(105), + }, + { + /* [683] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [684] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [685] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(125), + }, + { + /* [686] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(763), + }, + { + /* [687] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [688] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(312), + }, + { + /* [689] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [690] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [691] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(591), + }, + { + /* [692] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [693] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [694] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(600), + }, + { + /* [695] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [696] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [697] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(609), + }, + { + /* [698] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [699] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [700] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(618), + }, + { + /* [701] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [702] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [703] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(627), + }, + { + /* [704] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [705] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [706] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(636), + }, + { + /* [707] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [708] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [709] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(645), + }, + { + /* [710] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [711] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [712] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(654), + }, + { + /* [713] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [714] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [715] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(663), + }, + { + /* [716] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [717] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [718] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(672), + }, + { + /* [719] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(773), + }, + { + /* [720] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [721] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(681), + }, + { + /* [722] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(773), + }, + { + /* [723] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [724] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(690), + }, + { + /* [725] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(773), + }, + { + /* [726] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [727] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(699), + }, + { + /* [728] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(773), + }, + { + /* [729] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [730] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(708), + }, + { + /* [731] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(773), + }, + { + /* [732] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [733] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(717), + }, + { + /* [734] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(773), + }, + { + /* [735] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [736] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(164), + }, + { + /* [737] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(1097), + }, + { + /* [738] */ + /* usage */ core::ParameterUsage::kImageOperands, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [739] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1035), + }, + { + /* [740] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [741] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [742] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1035), + }, + { + /* [743] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [744] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [745] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1133), + }, + { + /* [746] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1109), + }, + { + /* [747] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [748] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [749] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1124), + }, + { + /* [750] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1127), + }, + { + /* [751] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1130), + }, + { + /* [752] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [753] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [754] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [755] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [756] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [757] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [758] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1054), + }, + { + /* [759] */ + /* usage */ core::ParameterUsage::kBase, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [760] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [761] */ + /* usage */ core::ParameterUsage::kCount, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [762] */ + /* usage */ core::ParameterUsage::kBase, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [763] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [764] */ + /* usage */ core::ParameterUsage::kCount, + /* matcher_indices */ MatcherIndicesIndex(1155), + }, + { + /* [765] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [766] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [767] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [768] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [769] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [770] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [771] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [772] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [773] */ + /* usage */ core::ParameterUsage::kDir, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [774] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [775] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [776] */ + /* usage */ core::ParameterUsage::kDir, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [777] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [778] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [779] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [780] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [781] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [782] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [783] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [784] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [785] */ + /* usage */ core::ParameterUsage::kMask, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [786] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [787] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [788] */ + /* usage */ core::ParameterUsage::kMask, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [789] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [790] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [791] */ + /* usage */ core::ParameterUsage::kDelta, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [792] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [793] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [794] */ + /* usage */ core::ParameterUsage::kDelta, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [795] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [796] */ + /* usage */ core::ParameterUsage::kGroupOperation, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [797] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [798] */ + /* usage */ core::ParameterUsage::kScope, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [799] */ + /* usage */ core::ParameterUsage::kGroupOperation, + /* matcher_indices */ MatcherIndicesIndex(628), + }, + { + /* [800] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(1094), + }, + { + /* [801] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1034), + }, + { + /* [802] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [803] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(474), + }, + { + /* [804] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [805] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(483), + }, + { + /* [806] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [807] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(492), + }, + { + /* [808] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [809] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(501), + }, + { + /* [810] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [811] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(510), + }, + { + /* [812] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [813] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(519), + }, + { + /* [814] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [815] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(528), + }, + { + /* [816] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [817] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(537), + }, + { + /* [818] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [819] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(546), + }, + { + /* [820] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [821] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(555), + }, + { + /* [822] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [823] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(564), + }, + { + /* [824] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(32), + }, + { + /* [825] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(726), + }, + { + /* [826] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [827] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1050), + }, + { + /* [828] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1054), + }, + { + /* [829] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1058), + }, + { + /* [830] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [831] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1058), + }, + { + /* [832] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [833] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1106), + }, + { + /* [834] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(990), + }, + { + /* [835] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1115), + }, + { + /* [836] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1118), + }, + { + /* [837] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [838] */ + /* usage */ core::ParameterUsage::kI, + /* matcher_indices */ MatcherIndicesIndex(1062), + }, + { + /* [839] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(984), + }, + { + /* [840] */ + /* usage */ core::ParameterUsage::kI, + /* matcher_indices */ MatcherIndicesIndex(982), + }, + { + /* [841] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(8), + }, + { + /* [842] */ + /* usage */ core::ParameterUsage::kI, + /* matcher_indices */ MatcherIndicesIndex(1066), + }, + { + /* [843] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(1106), + }, + { + /* [844] */ + /* usage */ core::ParameterUsage::kI, + /* matcher_indices */ MatcherIndicesIndex(988), + }, + { + /* [845] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1004), + }, + { + /* [846] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1004), + }, + { + /* [847] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1024), + }, + { + /* [848] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1024), + }, + { + /* [849] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1029), + }, + { + /* [850] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1029), + }, + { + /* [851] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(357), + }, + { + /* [852] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(366), + }, + { + /* [853] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(375), + }, + { + /* [854] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(384), + }, + { + /* [855] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(393), + }, + { + /* [856] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [857] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(411), + }, + { + /* [858] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(420), + }, + { + /* [859] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(429), + }, + { + /* [860] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(438), + }, + { + /* [861] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(447), + }, + { + /* [862] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(456), + }, + { + /* [863] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(465), + }, + { + /* [864] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(573), + }, + { + /* [865] */ + /* usage */ core::ParameterUsage::kImage, + /* matcher_indices */ MatcherIndicesIndex(582), + }, + { + /* [866] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1020), + }, + { + /* [867] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1149), + }, + { + /* [868] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1151), + }, + { + /* [869] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(1153), + }, +}; + +static_assert(ParameterIndex::CanIndex(kParameters), + "ParameterIndex is not large enough to index kParameters"); + +constexpr TemplateInfo kTemplates[] = { + { + /* [0] */ + /* name */ "Z", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [1] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [2] */ + /* name */ "D", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [3] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [4] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [5] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [6] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [7] */ + /* name */ "Z", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [8] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [9] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [10] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [11] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [12] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [13] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [14] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [15] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [16] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [17] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [18] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [19] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [20] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [21] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [22] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [23] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [24] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [25] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [26] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [27] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [28] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [29] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [30] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [31] */ + /* name */ "V", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [32] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [33] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1159), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [34] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(999), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [35] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [36] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1161), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [37] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [38] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [39] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(999), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [40] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [41] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(782), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [42] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [43] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [44] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(999), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [45] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [46] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(998), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [47] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [48] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [49] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1160), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [50] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [51] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [52] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [53] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [54] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1161), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [55] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [56] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [57] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(2), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [58] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(2), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [59] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [60] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [61] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [62] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [63] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [64] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [65] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [66] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [67] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [68] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [69] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1162), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [70] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(1163), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [71] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [72] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [73] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [74] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [75] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [76] */ + /* name */ "Z", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [77] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [78] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [79] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [80] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(9), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [81] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [82] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [83] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [84] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [85] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [86] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [87] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [88] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [89] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [90] */ + /* name */ "Z", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [91] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [92] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [93] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [94] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(628), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [95] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(2), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [96] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(928), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [97] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [98] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1158), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [99] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [100] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(937), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [101] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [102] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1158), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [103] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [104] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(946), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [105] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [106] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1158), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [107] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [108] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(955), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [109] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [110] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1158), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [111] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [112] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [113] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [114] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [115] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [116] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [117] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [118] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [119] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [120] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [121] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [122] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [123] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1160), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [124] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [125] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [126] */ + /* name */ "B", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [127] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [128] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [129] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [130] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [131] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [132] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [133] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [134] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [135] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(610), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [136] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(9), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [137] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [138] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(628), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [139] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(9), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [140] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [141] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(782), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [142] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(9), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [143] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [144] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [145] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [146] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [147] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(874), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [148] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [149] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [150] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(883), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [151] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [152] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [153] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(892), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [154] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [155] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [156] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(901), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [157] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1157), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [158] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [159] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(964), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [160] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1158), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [161] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [162] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(973), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [163] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1158), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [164] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [165] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [166] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [167] */ + /* name */ "M", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [168] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [169] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [170] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [171] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [172] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [173] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1160), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [174] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [175] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [176] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1160), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [177] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [178] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [179] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [180] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [181] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [182] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [183] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [184] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(1155), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [185] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [186] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(628), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [187] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [188] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(910), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [189] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [190] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(919), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [191] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [192] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(1156), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [193] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1160), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [194] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(782), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [195] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(610), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [196] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(998), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [197] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(628), + /* kind */ TemplateInfo::Kind::kType, + }, +}; + +static_assert(TemplateIndex::CanIndex(kTemplates), + "TemplateIndex is not large enough to index kTemplates"); + +constexpr OverloadInfo kOverloads[] = { + { + /* [0] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(504), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [1] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(736), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [2] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(164), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [3] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(416), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [4] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(119), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [5] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(420), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [6] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(174), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [7] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [8] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(424), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [9] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(428), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [10] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(432), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [11] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(436), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [12] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(124), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [13] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(129), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [14] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(194), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [15] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(199), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [16] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(440), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [17] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(444), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [18] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(134), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [19] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [20] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(448), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [21] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [22] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(214), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [23] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [24] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(456), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [25] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(460), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [26] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(224), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [27] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(464), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [28] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(8), + /* parameters */ ParameterIndex(540), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [29] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [30] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(552), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [31] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(556), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [32] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(544), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [33] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(548), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [34] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(472), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [35] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(476), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [36] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(560), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [37] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(504), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [38] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(508), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [39] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(164), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [40] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(169), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [41] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [42] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(512), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [43] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(516), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [44] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(174), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [45] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [46] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(184), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [47] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(189), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [48] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(23), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [49] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(29), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [50] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(520), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [51] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(524), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [52] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(194), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [53] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(199), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [54] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(204), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [55] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(209), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [56] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(35), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [57] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(41), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [58] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(528), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [59] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(532), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [60] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(214), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [61] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [62] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(536), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [63] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(224), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [64] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(8), + /* parameters */ ParameterIndex(540), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [65] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(229), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [66] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(544), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [67] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(548), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [68] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(234), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [69] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(239), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [70] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(552), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [71] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(556), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [72] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(560), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [73] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(144), + /* parameters */ ParameterIndex(736), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [74] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(244), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [75] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(249), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [76] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(480), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [77] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(484), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [78] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [79] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(149), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [80] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [81] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [82] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(199), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [83] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(444), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [84] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [85] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [86] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(572), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [87] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(576), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [88] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(496), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [89] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(500), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [90] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(564), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [91] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(568), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [92] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(244), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [93] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(249), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [94] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(254), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [95] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(259), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [96] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(47), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [97] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(53), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [98] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(524), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [99] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(199), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [100] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(209), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [101] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(89), + /* parameters */ ParameterIndex(41), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [102] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(82), + /* parameters */ ParameterIndex(532), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [103] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(572), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [104] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(576), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [105] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(264), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [106] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(269), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [107] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(667), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [108] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(670), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [109] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(673), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [110] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(676), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [111] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(679), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [112] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(682), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [113] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(685), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [114] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(688), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [115] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(352), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [116] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(356), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [117] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(360), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [118] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(364), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [119] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(368), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [120] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(372), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [121] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(376), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [122] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(380), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [123] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(135), + /* parameters */ ParameterIndex(691), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [124] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(135), + /* parameters */ ParameterIndex(694), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [125] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(138), + /* parameters */ ParameterIndex(697), + /* return_matcher_indices */ MatcherIndicesIndex(1143), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [126] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(138), + /* parameters */ ParameterIndex(700), + /* return_matcher_indices */ MatcherIndicesIndex(1143), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [127] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(141), + /* parameters */ ParameterIndex(703), + /* return_matcher_indices */ MatcherIndicesIndex(1145), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [128] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(141), + /* parameters */ ParameterIndex(706), + /* return_matcher_indices */ MatcherIndicesIndex(1145), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [129] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(135), + /* parameters */ ParameterIndex(709), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [130] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(138), + /* parameters */ ParameterIndex(712), + /* return_matcher_indices */ MatcherIndicesIndex(1143), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [131] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(141), + /* parameters */ ParameterIndex(715), + /* return_matcher_indices */ MatcherIndicesIndex(1145), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [132] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(135), + /* parameters */ ParameterIndex(718), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [133] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(138), + /* parameters */ ParameterIndex(721), + /* return_matcher_indices */ MatcherIndicesIndex(1143), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [134] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(141), + /* parameters */ ParameterIndex(724), + /* return_matcher_indices */ MatcherIndicesIndex(1145), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [135] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(135), + /* parameters */ ParameterIndex(727), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [136] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(138), + /* parameters */ ParameterIndex(730), + /* return_matcher_indices */ MatcherIndicesIndex(1143), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [137] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(141), + /* parameters */ ParameterIndex(733), + /* return_matcher_indices */ MatcherIndicesIndex(1145), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [138] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(77), + /* parameters */ ParameterIndex(825), + /* return_matcher_indices */ MatcherIndicesIndex(1147), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [139] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(580), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [140] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(584), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [141] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(588), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [142] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(592), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [143] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(596), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [144] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(600), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [145] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(604), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [146] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(608), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [147] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(612), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [148] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(616), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [149] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(620), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [150] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(624), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [151] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(628), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [152] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(632), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [153] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(636), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [154] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(851), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [155] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(852), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [156] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(853), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [157] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(854), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [158] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(855), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [159] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(856), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [160] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(81), + /* parameters */ ParameterIndex(857), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [161] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(18), + /* parameters */ ParameterIndex(858), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [162] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(132), + /* parameters */ ParameterIndex(859), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [163] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(132), + /* parameters */ ParameterIndex(860), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [164] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(132), + /* parameters */ ParameterIndex(861), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [165] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(132), + /* parameters */ ParameterIndex(862), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [166] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(85), + /* parameters */ ParameterIndex(863), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [167] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(384), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [168] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(99), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [169] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(388), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [170] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(74), + /* parameters */ ParameterIndex(104), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [171] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(392), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [172] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(128), + /* parameters */ ParameterIndex(396), + /* return_matcher_indices */ MatcherIndicesIndex(1141), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [173] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(400), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [174] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(109), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [175] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(404), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [176] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(75), + /* parameters */ ParameterIndex(114), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [177] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(408), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [178] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(129), + /* parameters */ ParameterIndex(412), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [179] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(803), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [180] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(805), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [181] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(807), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [182] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(809), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [183] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(811), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [184] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(813), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [185] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(815), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [186] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(817), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [187] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(819), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [188] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(821), + /* return_matcher_indices */ MatcherIndicesIndex(42), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [189] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(823), + /* return_matcher_indices */ MatcherIndicesIndex(763), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [190] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(8), + /* parameters */ ParameterIndex(299), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [191] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [192] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [193] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(309), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [194] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(289), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [195] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(294), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [196] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(314), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [197] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(319), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [198] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(324), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [199] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(8), + /* parameters */ ParameterIndex(299), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [200] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(71), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [201] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [202] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(309), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [203] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(77), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [204] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(83), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [205] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(314), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [206] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(319), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [207] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(324), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [208] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [209] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [210] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [211] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [212] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(314), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [213] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(324), + /* return_matcher_indices */ MatcherIndicesIndex(1139), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [214] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(147), + /* parameters */ ParameterIndex(866), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [215] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(150), + /* parameters */ ParameterIndex(866), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [216] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(153), + /* parameters */ ParameterIndex(866), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [217] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(156), + /* parameters */ ParameterIndex(866), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [218] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(188), + /* parameters */ ParameterIndex(866), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [219] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(190), + /* parameters */ ParameterIndex(866), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [220] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(6), + /* return_matcher_indices */ MatcherIndicesIndex(1020), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [221] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(6), + /* return_matcher_indices */ MatcherIndicesIndex(1020), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [222] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(6), + /* return_matcher_indices */ MatcherIndicesIndex(1020), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [223] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(6), + /* return_matcher_indices */ MatcherIndicesIndex(1020), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [224] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(159), + /* parameters */ ParameterIndex(13), + /* return_matcher_indices */ MatcherIndicesIndex(1020), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [225] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(162), + /* parameters */ ParameterIndex(13), + /* return_matcher_indices */ MatcherIndicesIndex(1020), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [226] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(274), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [227] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [228] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(154), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [229] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(159), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [230] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(274), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [231] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(5), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [232] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(59), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [233] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(65), + /* return_matcher_indices */ MatcherIndicesIndex(2), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [234] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(49), + /* parameters */ ParameterIndex(660), + /* return_matcher_indices */ MatcherIndicesIndex(1009), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [235] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(57), + /* parameters */ ParameterIndex(660), + /* return_matcher_indices */ MatcherIndicesIndex(1009), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [236] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(64), + /* parameters */ ParameterIndex(660), + /* return_matcher_indices */ MatcherIndicesIndex(1009), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [237] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(69), + /* parameters */ ParameterIndex(660), + /* return_matcher_indices */ MatcherIndicesIndex(1009), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [238] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(739), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [239] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(742), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [240] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(746), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [241] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(867), + /* return_matcher_indices */ MatcherIndicesIndex(1149), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [242] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(868), + /* return_matcher_indices */ MatcherIndicesIndex(1151), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [243] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(869), + /* return_matcher_indices */ MatcherIndicesIndex(1153), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [244] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(34), + /* parameters */ ParameterIndex(648), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [245] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(652), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [246] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(44), + /* parameters */ ParameterIndex(656), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [247] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(35), + /* parameters */ ParameterIndex(329), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [248] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(40), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [249] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(45), + /* parameters */ ParameterIndex(339), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [250] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(53), + /* parameters */ ParameterIndex(845), + /* return_matcher_indices */ MatcherIndicesIndex(1004), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [251] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(61), + /* parameters */ ParameterIndex(847), + /* return_matcher_indices */ MatcherIndicesIndex(1024), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [252] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(61), + /* parameters */ ParameterIndex(849), + /* return_matcher_indices */ MatcherIndicesIndex(1029), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [253] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [254] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(664), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [255] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(344), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [256] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(348), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [257] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(344), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [258] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(348), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [259] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [260] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(8), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [261] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(4), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [262] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(9), + /* parameters */ ParameterIndex(743), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [263] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(28), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [264] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(168), + /* parameters */ ParameterIndex(834), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [265] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(28), + /* parameters */ ParameterIndex(14), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [266] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(116), + /* parameters */ ParameterIndex(835), + /* return_matcher_indices */ MatcherIndicesIndex(1112), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [267] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(28), + /* parameters */ ParameterIndex(14), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [268] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(28), + /* parameters */ ParameterIndex(749), + /* return_matcher_indices */ MatcherIndicesIndex(1121), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [269] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(4), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [270] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(752), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [271] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(4), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [272] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(752), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [273] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(4), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [274] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(755), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [275] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(10), + /* parameters */ ParameterIndex(13), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [276] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(9), + /* parameters */ ParameterIndex(744), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [277] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(192), + /* parameters */ ParameterIndex(837), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [278] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(171), + /* parameters */ ParameterIndex(839), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [279] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(174), + /* parameters */ ParameterIndex(841), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [280] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(120), + /* parameters */ ParameterIndex(843), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [281] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(29), + /* parameters */ ParameterIndex(640), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [282] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(644), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [283] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(29), + /* parameters */ ParameterIndex(759), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [284] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(762), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [285] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(124), + /* parameters */ ParameterIndex(14), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [286] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(124), + /* parameters */ ParameterIndex(835), + /* return_matcher_indices */ MatcherIndicesIndex(1112), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [287] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(125), + /* parameters */ ParameterIndex(13), + /* return_matcher_indices */ MatcherIndicesIndex(1035), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [288] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(125), + /* parameters */ ParameterIndex(833), + /* return_matcher_indices */ MatcherIndicesIndex(1136), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [289] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(177), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [290] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(177), + /* parameters */ ParameterIndex(834), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [291] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(180), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [292] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(180), + /* parameters */ ParameterIndex(834), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [293] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(124), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [294] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(834), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [295] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(765), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [296] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(768), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [297] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(777), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [298] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(780), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [299] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(771), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [300] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(774), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [301] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(777), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [302] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(780), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [303] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(783), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [304] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(786), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [305] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(789), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [306] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(32), + /* parameters */ ParameterIndex(792), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [307] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(29), + /* parameters */ ParameterIndex(795), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [308] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(798), + /* return_matcher_indices */ MatcherIndicesIndex(1094), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [309] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(186), + /* parameters */ ParameterIndex(801), + /* return_matcher_indices */ MatcherIndicesIndex(628), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [310] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(93), + /* parameters */ ParameterIndex(8), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [311] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(9), + /* parameters */ ParameterIndex(743), + /* return_matcher_indices */ MatcherIndicesIndex(32), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [312] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 7, + /* templates */ TemplateIndex(0), + /* parameters */ ParameterIndex(864), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [313] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 7, + /* templates */ TemplateIndex(0), + /* parameters */ ParameterIndex(865), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [314] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(112), + /* parameters */ ParameterIndex(827), + /* return_matcher_indices */ MatcherIndicesIndex(1046), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [315] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(829), + /* return_matcher_indices */ MatcherIndicesIndex(1058), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [316] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(831), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [317] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(757), + /* return_matcher_indices */ MatcherIndicesIndex(1106), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [318] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(753), + /* return_matcher_indices */ MatcherIndicesIndex(984), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [319] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(194), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [320] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(196), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(8), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [321] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(832), + /* return_matcher_indices */ MatcherIndicesIndex(1054), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [322] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(331), + /* return_matcher_indices */ MatcherIndicesIndex(610), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [323] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(331), + /* return_matcher_indices */ MatcherIndicesIndex(628), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, +}; + +static_assert(OverloadIndex::CanIndex(kOverloads), + "OverloadIndex is not large enough to index kOverloads"); + +constexpr IntrinsicInfo kBuiltins[] = { + { + /* [0] */ + /* fn array_length[I : u32, A : access](ptr, I) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(309), + }, + { + /* [1] */ + /* fn atomic_load[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U) -> T */ + /* fn atomic_load[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(253), + }, + { + /* [2] */ + /* fn atomic_store[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) */ + /* fn atomic_store[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(255), + }, + { + /* [3] */ + /* fn atomic_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [4] */ + /* fn atomic_compare_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, U, T, T) -> T */ + /* fn atomic_compare_exchange[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, U, T, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(259), + }, + { + /* [5] */ + /* fn atomic_i_add[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_i_add[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [6] */ + /* fn atomic_i_sub[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_i_sub[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [7] */ + /* fn atomic_s_max[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_s_max[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [8] */ + /* fn atomic_s_min[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_s_min[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [9] */ + /* fn atomic_u_max[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_u_max[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [10] */ + /* fn atomic_u_min[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_u_min[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [11] */ + /* fn atomic_and[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_and[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [12] */ + /* fn atomic_or[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_or[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [13] */ + /* fn atomic_xor[T : iu32, U : u32, S : workgroup_or_storage](ptr, read_write>, U, U, T) -> T */ + /* fn atomic_xor[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U, T) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(257), + }, + { + /* [14] */ + /* fn atomic_i_increment[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(310), + }, + { + /* [15] */ + /* fn atomic_i_decrement[T : iu32, U : u32, S : workgroup_or_storage](ptr, U, U) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(310), + }, + { + /* [16] */ + /* fn dot[N : num, T : f32_f16](vec, vec) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(311), + }, + { + /* [17] */ + /* fn image_dref_gather[F : texel_format](image: sampled_image>, coords: vec2, dref: f32, image_operands: u32) -> vec4 */ + /* fn image_dref_gather[F : texel_format, A : access, Z : iu32](image: sampled_image>, coords: vec2, dref: f32, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_dref_gather[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32) -> vec4 */ + /* fn image_dref_gather[F : texel_format, A : access, Z : iu32](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_dref_gather[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32) -> vec4 */ + /* fn image_dref_gather[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32) -> vec4 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(208), + }, + { + /* [18] */ + /* fn image_fetch[T : fiu32, C : iu32, F : texel_format](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, F : texel_format](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, F : texel_format](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_fetch[C : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_fetch[C : iu32, F : texel_format](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_fetch[C : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: image, coords: C, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: image, coords: vec3, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: image, coords: vec3, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[C : iu32, Z : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[C : iu32, Z : iu32, F : texel_format](image: image, coords: vec3, image_operands: u32, sample: Z) -> vec4 */ + /* fn image_fetch[C : iu32, Z : iu32, F : texel_format](image: image, coords: vec2, image_operands: u32, sample: Z) -> vec4 */ + /* num overloads */ 16, + /* overloads */ OverloadIndex(107), + }, + { + /* [19] */ + /* fn image_gather[T : fiu32, C : iu32, F : texel_format](image: sampled_image>, coords: vec2, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec2, component: C, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_gather[T : fiu32, C : iu32, F : texel_format](image: sampled_image>, coords: vec3, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[T : fiu32, C : iu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, component: C, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_gather[T : fiu32, C : iu32, F : texel_format](image: sampled_image>, coords: vec3, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[T : fiu32, C : iu32, F : texel_format](image: sampled_image>, coords: vec4, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[C : iu32, F : texel_format](image: sampled_image>, coords: vec2, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[C : iu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec2, component: C, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_gather[C : iu32, F : texel_format](image: sampled_image>, coords: vec3, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[C : iu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, component: C, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_gather[C : iu32, F : texel_format](image: sampled_image>, coords: vec3, component: C, image_operands: u32) -> vec4 */ + /* fn image_gather[C : iu32, F : texel_format](image: sampled_image>, coords: vec4, component: C, image_operands: u32) -> vec4 */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(167), + }, + { + /* [20] */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> R */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> R */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> vec2 */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> vec3 */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> vec3 */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> vec2 */ + /* fn image_query_size[T : fiu32, F : texel_format, A : access](image: image) -> vec3 */ + /* fn image_query_size[T : fiu32, S : sampled, F : texel_format, A : access](image: image) -> vec2 */ + /* fn image_query_size[F : texel_format, A : access](image: image) -> vec2 */ + /* fn image_query_size[F : texel_format, A : access](image: image) -> vec3 */ + /* fn image_query_size[F : texel_format, A : access](image: image) -> vec2 */ + /* fn image_query_size[F : texel_format, A : access](image: image) -> vec3 */ + /* fn image_query_size[S : sampled, F : texel_format, A : access](image: image) -> vec2 */ + /* num overloads */ 13, + /* overloads */ OverloadIndex(154), + }, + { + /* [21] */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> R */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> R */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec2 */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec3 */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec3 */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec2 */ + /* fn image_query_size_lod[T : fiu32, L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec3 */ + /* fn image_query_size_lod[L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec2 */ + /* fn image_query_size_lod[L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec3 */ + /* fn image_query_size_lod[L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec2 */ + /* fn image_query_size_lod[L : iu32, S : sampled, F : texel_format, A : access](image: image, level: L) -> vec3 */ + /* num overloads */ 11, + /* overloads */ OverloadIndex(179), + }, + { + /* [22] */ + /* fn image_query_levels[T : fiu32, D : depth, R : arrayed, S : sampled, F : texel_format, A : access](image: image) -> Z */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(312), + }, + { + /* [23] */ + /* fn image_query_samples[T : fiu32, D : depth, R : arrayed, S : sampled, F : texel_format, A : access](image: image) -> Z */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(313), + }, + { + /* [24] */ + /* fn image_read[F : f32_texel_format, A : readable, C : iu32](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_read[F : f32_texel_format, A : readable, C : iu32](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_read[F : i32_texel_format, A : readable, C : iu32](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_read[F : i32_texel_format, A : readable, C : iu32](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_read[F : u32_texel_format, A : readable, C : iu32](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_read[F : u32_texel_format, A : readable, C : iu32](image: image, coords: C, image_operands: u32) -> vec4 */ + /* fn image_read[F : f32_texel_format, A : readable, C : iu32](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_read[F : i32_texel_format, A : readable, C : iu32](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_read[F : u32_texel_format, A : readable, C : iu32](image: image, coords: vec2, image_operands: u32) -> vec4 */ + /* fn image_read[F : f32_texel_format, A : readable, C : iu32](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_read[F : i32_texel_format, A : readable, C : iu32](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_read[F : u32_texel_format, A : readable, C : iu32](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_read[F : f32_texel_format, A : readable, C : iu32](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_read[F : i32_texel_format, A : readable, C : iu32](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_read[F : u32_texel_format, A : readable, C : iu32](image: image, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_read[F : texel_format, T : fiu32, C : iu32, A : readable](image: image, coords: vec2) -> vec4 */ + /* num overloads */ 16, + /* overloads */ OverloadIndex(123), + }, + { + /* [25] */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: f32, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, bias: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32, const_offset: vec3) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32, const_offset: vec3) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, const_offset: vec3) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, const_offset: vec3) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_implicit_lod[F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* num overloads */ 37, + /* overloads */ OverloadIndex(0), + }, + { + /* [26] */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, bias: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, bias: f32, const_offset: vec3) -> vec4 */ + /* fn image_sample_proj_implicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, const_offset: vec3) -> vec4 */ + /* fn image_sample_proj_implicit_lod[F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32) -> vec4 */ + /* fn image_sample_proj_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, const_offset: vec2) -> vec4 */ + /* num overloads */ 17, + /* overloads */ OverloadIndex(73), + }, + { + /* [27] */ + /* fn image_sample_proj_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_proj_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_proj_dref_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, const_offset: vec2) -> f32 */ + /* fn image_sample_proj_dref_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, const_offset: vec2) -> f32 */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(226), + }, + { + /* [28] */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: f32, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, ddx: vec2, ddy: vec2, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec2, ddy: vec2, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec2, ddy: vec2, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32, const_offset: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32, const_offset: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec3, ddy: vec3, const_offset: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec3, ddy: vec3, const_offset: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn image_sample_explicit_lod[F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_explicit_lod[F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* num overloads */ 36, + /* overloads */ OverloadIndex(37), + }, + { + /* [29] */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, ddx: vec2, ddy: vec2, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec2, ddy: vec2, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32, const_offset: vec3) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, ddx: vec3, ddy: vec3, const_offset: vec3) -> vec4 */ + /* fn image_sample_proj_explicit_lod[T : fiu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_proj_explicit_lod[F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_proj_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32) -> vec4 */ + /* fn image_sample_proj_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* fn image_sample_proj_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, image_operands: u32, lod: f32, const_offset: vec2) -> vec4 */ + /* num overloads */ 17, + /* overloads */ OverloadIndex(90), + }, + { + /* [30] */ + /* fn image_sample_proj_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_proj_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_proj_dref_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, lod: f32, const_offset: vec2) -> f32 */ + /* fn image_sample_proj_dref_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, lod: f32, const_offset: vec2) -> f32 */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(230), + }, + { + /* [31] */ + /* fn image_sample_dref_implicit_lod[F : texel_format, N : num](image: sampled_image>, coords: vec, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_dref_implicit_lod[Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, dref: f32, image_operands: u32, const_offset: vec2) -> f32 */ + /* fn image_sample_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_dref_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, const_offset: vec2) -> f32 */ + /* fn image_sample_dref_implicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, const_offset: vec2) -> f32 */ + /* fn image_sample_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32) -> f32 */ + /* fn image_sample_dref_implicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32) -> f32 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(190), + }, + { + /* [32] */ + /* fn image_sample_dref_explicit_lod[F : texel_format, N : num](image: sampled_image>, coords: vec, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_dref_explicit_lod[Z : iu32, F : texel_format, N : num](image: sampled_image>, coords: vec, dref: f32, image_operands: u32, lod: f32, const_offset: vec2) -> f32 */ + /* fn image_sample_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_dref_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, lod: f32, const_offset: vec2) -> f32 */ + /* fn image_sample_dref_explicit_lod[Z : iu32, F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, lod: f32, const_offset: vec2) -> f32 */ + /* fn image_sample_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec3, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* fn image_sample_dref_explicit_lod[F : texel_format](image: sampled_image>, coords: vec4, dref: f32, image_operands: u32, lod: f32) -> f32 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(199), + }, + { + /* [33] */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: C, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: C, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: C, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: C, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: C, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: C, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec2, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec2, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec2, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec3, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec3, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec3, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec3, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec3, texel: vec4, image_operands: u32) */ + /* fn image_write[C : iu32, F : texel_format, A : access](image: image, coords: vec3, texel: vec4, image_operands: u32) */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(139), + }, + { + /* [34] */ + /* fn op_image>[T : fiu32, F : texel_format](sampled_image) -> I */ + /* fn op_image>[T : fiu32, F : texel_format](sampled_image) -> I */ + /* fn op_image>[T : fiu32, F : texel_format](sampled_image) -> I */ + /* fn op_image>[T : fiu32, F : texel_format](sampled_image) -> I */ + /* fn op_image>[F : texel_format](sampled_image) -> I */ + /* fn op_image>[F : texel_format](sampled_image) -> I */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(214), + }, + { + /* [35] */ + /* fn op_sampled_image>[T : fiu32, S : samplers, F : texel_format](I, S) -> sampled_image */ + /* fn op_sampled_image>[T : fiu32, S : samplers, F : texel_format](I, S) -> sampled_image */ + /* fn op_sampled_image>[T : fiu32, S : samplers, F : texel_format](I, S) -> sampled_image */ + /* fn op_sampled_image>[T : fiu32, S : samplers, F : texel_format](I, S) -> sampled_image */ + /* fn op_sampled_image>[S : samplers, F : texel_format](I, S) -> sampled_image */ + /* fn op_sampled_image>[S : samplers, F : texel_format](I, S) -> sampled_image */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(220), + }, + { + /* [36] */ + /* fn matrix_times_matrix[T : f32_f16, K : num, C : num, R : num](mat, mat) -> mat */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(314), + }, + { + /* [37] */ + /* fn matrix_times_scalar[T : f32_f16, N : num, M : num](mat, T) -> mat */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(315), + }, + { + /* [38] */ + /* fn matrix_times_vector[T : f32_f16, N : num, M : num](mat, vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(316), + }, + { + /* [39] */ + /* fn select[T : scalar](bool, T, T) -> T */ + /* fn select[N : num, T : scalar](bool, vec, vec) -> vec */ + /* fn select[N : num, T : scalar](vec, vec, vec) -> vec */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(238), + }, + { + /* [40] */ + /* fn vector_times_matrix[T : f32_f16, N : num, M : num](vec, mat) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(317), + }, + { + /* [41] */ + /* fn vector_times_scalar[T : f32_f16, N : num](vec, T) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(318), + }, + { + /* [42] */ + /* fn normalize[T : f32_f16](T) -> T */ + /* fn normalize[N : num, T : f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(261), + }, + { + /* [43] */ + /* fn inverse[T : f32_f16](mat2x2) -> mat2x2 */ + /* fn inverse[T : f32_f16](mat3x3) -> mat3x3 */ + /* fn inverse[T : f32_f16](mat4x4) -> mat4x4 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(241), + }, + { + /* [44] */ + /* fn sign[T : iu32](T) -> R */ + /* fn sign[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(263), + }, + { + /* [45] */ + /* fn abs[T : iu32](T) -> R */ + /* fn abs[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(263), + }, + { + /* [46] */ + /* fn s_max[T : iu32, U : iu32](T, U) -> R */ + /* fn s_max[T : iu32, U : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(265), + }, + { + /* [47] */ + /* fn s_min[T : iu32, U : iu32](T, U) -> R */ + /* fn s_min[T : iu32, U : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(265), + }, + { + /* [48] */ + /* fn s_clamp[T : iu32, U : iu32, V : iu32](T, U, V) -> R */ + /* fn s_clamp[T : iu32, U : iu32, V : iu32, N : num](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(267), + }, + { + /* [49] */ + /* fn u_max[T : iu32, U : iu32](T, U) -> R */ + /* fn u_max[T : iu32, U : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(265), + }, + { + /* [50] */ + /* fn u_min[T : iu32, U : iu32](T, U) -> R */ + /* fn u_min[T : iu32, U : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(265), + }, + { + /* [51] */ + /* fn u_clamp[T : iu32, U : iu32, V : iu32](T, U, V) -> R */ + /* fn u_clamp[T : iu32, U : iu32, V : iu32, N : num](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(267), + }, + { + /* [52] */ + /* fn find_i_lsb[T : iu32](T) -> R */ + /* fn find_i_lsb[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(263), + }, + { + /* [53] */ + /* fn find_s_msb[T : iu32](T) -> R */ + /* fn find_s_msb[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(263), + }, + { + /* [54] */ + /* fn find_u_msb[T : iu32](T) -> R */ + /* fn find_u_msb[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(263), + }, + { + /* [55] */ + /* fn refract[T : f32_f16](T, T, T) -> T */ + /* fn refract[T : f32_f16, N : num](vec, vec, T) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(269), + }, + { + /* [56] */ + /* fn reflect[T : f32_f16](T, T) -> T */ + /* fn reflect[T : f32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(271), + }, + { + /* [57] */ + /* fn face_forward[T : f32_f16](T, T, T) -> T */ + /* fn face_forward[T : f32_f16, N : num](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(273), + }, + { + /* [58] */ + /* fn ldexp[T : f32_f16, U : iu32](T, U) -> T */ + /* fn ldexp[N : num, T : f32_f16, U : iu32](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(275), + }, + { + /* [59] */ + /* fn modf[T : f32_f16, S : function_private_workgroup_storage](x: T, i: ptr) -> T */ + /* fn modf[T : f32_f16, N : num, S : function_private_workgroup_storage](x: vec, i: ptr, writable>) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(277), + }, + { + /* [60] */ + /* fn frexp[T : f32_f16, R : iu32, S : function_private_workgroup_storage](x: T, i: ptr) -> T */ + /* fn frexp[T : f32_f16, R : iu32, N : num, S : function_private_workgroup_storage](x: vec, i: ptr, writable>) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(279), + }, + { + /* [61] */ + /* fn bit_count[T : iu32](T) -> R */ + /* fn bit_count[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(263), + }, + { + /* [62] */ + /* fn bit_field_insert[T : iu32](base: T, insert: T, offset: iu32, count: iu32) -> T */ + /* fn bit_field_insert[T : iu32, N : num](base: vec, insert: vec, offset: iu32, count: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(281), + }, + { + /* [63] */ + /* fn bit_field_s_extract[T : iu32](base: T, offset: iu32, count: iu32) -> T */ + /* fn bit_field_s_extract[T : iu32, N : num](base: vec, offset: iu32, count: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(283), + }, + { + /* [64] */ + /* fn bit_field_u_extract[T : iu32](base: T, offset: iu32, count: iu32) -> T */ + /* fn bit_field_u_extract[T : iu32, N : num](base: vec, offset: iu32, count: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(283), + }, + { + /* [65] */ + /* fn add[A : iu32, B : iu32](A, B) -> R */ + /* fn add[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [66] */ + /* fn sub[A : iu32, B : iu32](A, B) -> R */ + /* fn sub[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [67] */ + /* fn mul[A : iu32, B : iu32](A, B) -> R */ + /* fn mul[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [68] */ + /* fn s_div[A : iu32, B : iu32](A, B) -> R */ + /* fn s_div[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [69] */ + /* fn s_mod[A : iu32, B : iu32](A, B) -> R */ + /* fn s_mod[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [70] */ + /* fn s_greater_than[A : iu32, B : iu32](A, B) -> bool */ + /* fn s_greater_than[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [71] */ + /* fn s_greater_than_equal[A : iu32, B : iu32](A, B) -> bool */ + /* fn s_greater_than_equal[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [72] */ + /* fn s_less_than[A : iu32, B : iu32](A, B) -> bool */ + /* fn s_less_than[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [73] */ + /* fn s_less_than_equal[A : iu32, B : iu32](A, B) -> bool */ + /* fn s_less_than_equal[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [74] */ + /* fn u_greater_than[A : iu32, B : iu32](A, B) -> bool */ + /* fn u_greater_than[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [75] */ + /* fn u_greater_than_equal[A : iu32, B : iu32](A, B) -> bool */ + /* fn u_greater_than_equal[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [76] */ + /* fn u_less_than[A : iu32, B : iu32](A, B) -> bool */ + /* fn u_less_than[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [77] */ + /* fn u_less_than_equal[A : iu32, B : iu32](A, B) -> bool */ + /* fn u_less_than_equal[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [78] */ + /* fn convert_f_to_s[T : f32_f16](T) -> R */ + /* fn convert_f_to_s[T : f32_f16, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(289), + }, + { + /* [79] */ + /* fn convert_s_to_f[T : iu32](T) -> R */ + /* fn convert_s_to_f[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(291), + }, + { + /* [80] */ + /* fn convert_u_to_f[T : iu32](T) -> R */ + /* fn convert_u_to_f[T : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(291), + }, + { + /* [81] */ + /* fn s_convert[T : i32](T) -> K */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(319), + }, + { + /* [82] */ + /* fn u_convert[T : u32](T) -> K */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(320), + }, + { + /* [83] */ + /* fn bitwise_and[A : iu32, B : iu32](A, B) -> R */ + /* fn bitwise_and[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [84] */ + /* fn bitwise_or[A : iu32, B : iu32](A, B) -> R */ + /* fn bitwise_or[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [85] */ + /* fn bitwise_xor[A : iu32, B : iu32](A, B) -> R */ + /* fn bitwise_xor[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [86] */ + /* fn equal[A : iu32, B : iu32](A, B) -> bool */ + /* fn equal[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [87] */ + /* fn not_equal[A : iu32, B : iu32](A, B) -> bool */ + /* fn not_equal[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(287), + }, + { + /* [88] */ + /* fn shift_left_logical[A : iu32, B : iu32](A, B) -> R */ + /* fn shift_left_logical[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [89] */ + /* fn shift_right_logical[A : iu32, B : iu32](A, B) -> R */ + /* fn shift_right_logical[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [90] */ + /* fn shift_right_arithmetic[A : iu32, B : iu32](A, B) -> R */ + /* fn shift_right_arithmetic[A : iu32, B : iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(285), + }, + { + /* [91] */ + /* fn not[A : iu32](A) -> R */ + /* fn not[A : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(293), + }, + { + /* [92] */ + /* fn s_negate[A : iu32](A) -> R */ + /* fn s_negate[A : iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(293), + }, + { + /* [93] */ + /* fn f_mod[T : f32_f16](T, T) -> T */ + /* fn f_mod[T : f32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(271), + }, + { + /* [94] */ + /* fn outer_product[T : f32_f16, N : num, M : num](vec, vec) -> mat */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(321), + }, + { + /* [95] */ + /* fn s_dot(u32, u32, u32) -> i32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(322), + }, + { + /* [96] */ + /* fn u_dot(u32, u32, u32) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(323), + }, + { + /* [97] */ + /* fn cooperative_matrix_load>[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num](ptr, u32, u32, u32) -> T */ + /* fn cooperative_matrix_load>[K : subgroup_matrix_kind, S : i8, C : num, R : num](ptr, u32, u32, u32) -> T */ + /* fn cooperative_matrix_load>[K : subgroup_matrix_kind, S : u8, C : num, R : num](ptr, u32, u32, u32) -> T */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(244), + }, + { + /* [98] */ + /* fn cooperative_matrix_store[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num](ptr, subgroup_matrix, u32, u32, u32) */ + /* fn cooperative_matrix_store[K : subgroup_matrix_kind, S : i8, C : num, R : num](ptr, subgroup_matrix, u32, u32, u32) */ + /* fn cooperative_matrix_store[K : subgroup_matrix_kind, S : u8, C : num, R : num](ptr, subgroup_matrix, u32, u32, u32) */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(247), + }, + { + /* [99] */ + /* fn cooperative_matrix_mul_add[T : f16, TR : f32_f16, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix, u32) -> subgroup_matrix */ + /* fn cooperative_matrix_mul_add[T : f32, TR : f32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix, u32) -> subgroup_matrix */ + /* fn cooperative_matrix_mul_add[T : iu32, TR : iu32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix, u32) -> subgroup_matrix */ + /* fn cooperative_matrix_mul_add[T : iu8, TR : iu32_iu8, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix, u32) -> subgroup_matrix */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(234), + }, + { + /* [100] */ + /* fn group_non_uniform_broadcast[T : scalar](scope: u32, e: T, @const id: u32) -> T */ + /* fn group_non_uniform_broadcast[N : num, T : scalar](scope: u32, e: vec, @const id: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(295), + }, + { + /* [101] */ + /* fn group_non_uniform_broadcast_first[T : scalar](scope: u32, value: T) -> T */ + /* fn group_non_uniform_broadcast_first[N : num, T : scalar](scope: u32, value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(297), + }, + { + /* [102] */ + /* fn group_non_uniform_quad_broadcast[T : scalar](scope: u32, e: T, @const id: u32) -> T */ + /* fn group_non_uniform_quad_broadcast[N : num, T : scalar](scope: u32, e: vec, @const id: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(295), + }, + { + /* [103] */ + /* fn group_non_uniform_quad_swap[T : scalar](scope: u32, e: T, @const dir: u32) -> T */ + /* fn group_non_uniform_quad_swap[N : num, T : scalar](scope: u32, e: vec, @const dir: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(299), + }, + { + /* [104] */ + /* fn group_non_uniform_shuffle[T : scalar](scope: u32, value: T, id: u32) -> T */ + /* fn group_non_uniform_shuffle[N : num, T : scalar](scope: u32, value: vec, id: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(301), + }, + { + /* [105] */ + /* fn group_non_uniform_shuffle_xor[T : scalar](scope: u32, value: T, mask: u32) -> T */ + /* fn group_non_uniform_shuffle_xor[N : num, T : scalar](scope: u32, value: vec, mask: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(303), + }, + { + /* [106] */ + /* fn group_non_uniform_shuffle_down[T : scalar](scope: u32, value: T, delta: u32) -> T */ + /* fn group_non_uniform_shuffle_down[N : num, T : scalar](scope: u32, value: vec, delta: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(305), + }, + { + /* [107] */ + /* fn group_non_uniform_shuffle_up[T : scalar](scope: u32, value: T, delta: u32) -> T */ + /* fn group_non_uniform_shuffle_up[N : num, T : scalar](scope: u32, value: vec, delta: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(305), + }, + { + /* [108] */ + /* fn group_non_uniform_s_min[T : iu32](scope: u32, group_operation: u32, value: T) -> T */ + /* fn group_non_uniform_s_min[N : num, T : iu32](scope: u32, group_operation: u32, value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(307), + }, + { + /* [109] */ + /* fn group_non_uniform_s_max[T : iu32](scope: u32, group_operation: u32, value: T) -> T */ + /* fn group_non_uniform_s_max[N : num, T : iu32](scope: u32, group_operation: u32, value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(307), + }, +}; + +constexpr IntrinsicInfo kBinaryOperators[] = { + { + /* [0] */ + /* op +[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* op +[K : subgroup_matrix_kind, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* op +[K : subgroup_matrix_kind, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(250), + }, + { + /* [1] */ + /* op -[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* op -[K : subgroup_matrix_kind, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* op -[K : subgroup_matrix_kind, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(250), + }, + { + /* [2] */ + /* op *[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* op *[K : subgroup_matrix_kind, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* op *[K : subgroup_matrix_kind, C : num, R : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(250), + }, +}; +constexpr uint8_t kBinaryOperatorPlus = 0; +constexpr uint8_t kBinaryOperatorMinus = 1; +constexpr uint8_t kBinaryOperatorStar = 2; + +} // anonymous namespace + +const core::intrinsic::TableData Dialect::kData{ + /* templates */ kTemplates, + /* type_matcher_indices */ kMatcherIndices, + /* type_matchers */ kTypeMatchers, + /* number_matchers */ kNumberMatchers, + /* parameters */ kParameters, + /* overloads */ kOverloads, + /* const_eval_functions */ Empty, + /* ctor_conv */ Empty, + /* builtins */ kBuiltins, + /* binary '+' */ kBinaryOperators[kBinaryOperatorPlus], + /* binary '-' */ kBinaryOperators[kBinaryOperatorMinus], + /* binary '*' */ kBinaryOperators[kBinaryOperatorStar], + /* binary '/' */ tint::core::intrinsic::kNoOverloads, + /* binary '%' */ tint::core::intrinsic::kNoOverloads, + /* binary '^' */ tint::core::intrinsic::kNoOverloads, + /* binary '&' */ tint::core::intrinsic::kNoOverloads, + /* binary '|' */ tint::core::intrinsic::kNoOverloads, + /* binary '&&' */ tint::core::intrinsic::kNoOverloads, + /* binary '||' */ tint::core::intrinsic::kNoOverloads, + /* binary '==' */ tint::core::intrinsic::kNoOverloads, + /* binary '!=' */ tint::core::intrinsic::kNoOverloads, + /* binary '<' */ tint::core::intrinsic::kNoOverloads, + /* binary '>' */ tint::core::intrinsic::kNoOverloads, + /* binary '<=' */ tint::core::intrinsic::kNoOverloads, + /* binary '>=' */ tint::core::intrinsic::kNoOverloads, + /* binary '<<' */ tint::core::intrinsic::kNoOverloads, + /* binary '>>' */ tint::core::intrinsic::kNoOverloads, + /* unary '!' */ tint::core::intrinsic::kNoOverloads, + /* unary '~' */ tint::core::intrinsic::kNoOverloads, + /* unary '-' */ tint::core::intrinsic::kNoOverloads, + /* unary '*' */ tint::core::intrinsic::kNoOverloads, + /* unary '&' */ tint::core::intrinsic::kNoOverloads, +}; + +} // namespace tint::spirv::intrinsic + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/spirv/intrinsic/dialect.h b/3rdparty/dawn/src/tint/lang/spirv/intrinsic/dialect.h new file mode 100644 index 000000000..4993a8687 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/intrinsic/dialect.h @@ -0,0 +1,51 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_INTRINSIC_DIALECT_H_ +#define SRC_TINT_LANG_SPIRV_INTRINSIC_DIALECT_H_ + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/spirv/builtin_fn.h" + +namespace tint::spirv::intrinsic { + +/// Dialect holds the intrinsic table data and types for the SPIR-V dialect +struct Dialect { + /// The dialect's intrinsic table data + static const core::intrinsic::TableData kData; + + /// The dialect's builtin function enumerator + using BuiltinFn = spirv::BuiltinFn; + + /// @returns the name of the builtin function @p fn + /// @param fn the builtin function + static std::string_view ToString(BuiltinFn fn) { return str(fn); } +}; + +} // namespace tint::spirv::intrinsic + +#endif // SRC_TINT_LANG_SPIRV_INTRINSIC_DIALECT_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/intrinsic/type_matchers.h b/3rdparty/dawn/src/tint/lang/spirv/intrinsic/type_matchers.h new file mode 100644 index 000000000..1a6380ab1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/intrinsic/type_matchers.h @@ -0,0 +1,136 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_INTRINSIC_TYPE_MATCHERS_H_ +#define SRC_TINT_LANG_SPIRV_INTRINSIC_TYPE_MATCHERS_H_ + +#include "src/tint/lang/core/intrinsic/table.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/spirv/type/sampled_image.h" + +namespace tint::spirv::intrinsic { + +inline bool MatchStructWithRuntimeArray(core::intrinsic::MatchState&, const core::type::Type* ty) { + if (auto* str = ty->As()) { + if (str->Members().IsEmpty()) { + return false; + } + if (auto* ary = str->Members().Back()->Type()->As()) { + if (ary->Count()->Is()) { + return true; + } + } + } + return false; +} + +inline const core::type::Type* BuildStructWithRuntimeArray(core::intrinsic::MatchState&, + const core::type::Type* ty) { + return ty; +} + +inline bool MatchSampledImage(core::intrinsic::MatchState&, + const core::type::Type* ty, + const core::type::Type*& T) { + if (ty->Is()) { + T = ty; + return true; + } + if (auto* v = ty->As()) { + T = v->Image(); + return true; + } + return false; +} + +inline const core::type::Type* BuildSampledImage(core::intrinsic::MatchState& state, + const core::type::Type*, + const core::type::Type* T) { + return state.types.Get(T); +} + +inline bool MatchImage(core::intrinsic::MatchState&, + const core::type::Type* ty, + const core::type::Type*& T, + core::intrinsic::Number& D, + core::intrinsic::Number& E, + core::intrinsic::Number& R, + core::intrinsic::Number& M, + core::intrinsic::Number& S, + core::intrinsic::Number& F, + core::intrinsic::Number& A) { + if (ty->Is()) { + T = ty; + D = core::intrinsic::Number::any; + E = core::intrinsic::Number::any; + R = core::intrinsic::Number::any; + M = core::intrinsic::Number::any; + S = core::intrinsic::Number::any; + F = core::intrinsic::Number::any; + A = core::intrinsic::Number::any; + return true; + } + if (auto* v = ty->As()) { + T = v->GetSampledType(); + D = core::intrinsic::Number(static_cast(v->GetDim())); + E = core::intrinsic::Number(static_cast(v->GetDepth())); + R = core::intrinsic::Number(static_cast(v->GetArrayed())); + M = core::intrinsic::Number(static_cast(v->GetMultisampled())); + S = core::intrinsic::Number(static_cast(v->GetSampled())); + F = core::intrinsic::Number(static_cast(v->GetTexelFormat())); + A = core::intrinsic::Number(static_cast(v->GetAccess())); + return true; + } + return false; +} + +inline const core::type::Type* BuildImage(core::intrinsic::MatchState& state, + const core::type::Type*, + const core::type::Type* T, + core::intrinsic::Number D, + core::intrinsic::Number E, + core::intrinsic::Number R, + core::intrinsic::Number M, + core::intrinsic::Number S, + core::intrinsic::Number F, + core::intrinsic::Number A) { + auto dim = static_cast(D.Value()); + auto depth = static_cast(E.Value()); + auto arrayed = static_cast(R.Value()); + auto ms = static_cast(M.Value()); + auto sampled = static_cast(S.Value()); + auto fmt = static_cast(F.Value()); + auto access = static_cast(A.Value()); + + return state.types.Get(T, dim, depth, arrayed, ms, sampled, fmt, access); +} + +} // namespace tint::spirv::intrinsic + +#endif // SRC_TINT_LANG_SPIRV_INTRINSIC_TYPE_MATCHERS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/binary.cc b/3rdparty/dawn/src/tint/lang/spirv/ir/binary.cc new file mode 100644 index 000000000..ea86a3f17 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/binary.cc @@ -0,0 +1,53 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/ir/binary.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::ir::Binary); + +namespace tint::spirv::ir { + +Binary::Binary(Instruction::Id id, + core::ir::InstructionResult* result, + core::BinaryOp op, + core::ir::Value* lhs, + core::ir::Value* rhs) + : Base(id, result, op, lhs, rhs) {} + +Binary::~Binary() = default; + +Binary* Binary::Clone(core::ir::CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* new_rhs = ctx.Remap(RHS()); + auto* new_lhs = ctx.Remap(LHS()); + return ctx.ir.CreateInstruction(new_result, Op(), new_lhs, new_rhs); +} + +} // namespace tint::spirv::ir diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/binary.h b/3rdparty/dawn/src/tint/lang/spirv/ir/binary.h new file mode 100644 index 000000000..5aa72f13e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/binary.h @@ -0,0 +1,66 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_IR_BINARY_H_ +#define SRC_TINT_LANG_SPIRV_IR_BINARY_H_ + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/spirv/intrinsic/dialect.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::spirv::ir { + +/// A SPIRV-dialect binary instruction in the IR. +class Binary final : public Castable { + public: + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param op the binary operator + /// @param lhs the lhs of the instruction + /// @param rhs the rhs of the instruction + Binary(Id id, + core::ir::InstructionResult* result, + core::BinaryOp op, + core::ir::Value* lhs, + core::ir::Value* rhs); + + ~Binary() override; + + /// @copydoc core::ir::Instruction::Clone() + Binary* Clone(core::ir::CloneContext& ctx) override; + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override { + return spirv::intrinsic::Dialect::kData; + } +}; + +} // namespace tint::spirv::ir + +#endif // SRC_TINT_LANG_SPIRV_IR_BINARY_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.cc b/3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.cc new file mode 100644 index 000000000..4e35f210b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.cc @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/ir/builtin_call.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::ir::BuiltinCall); + +namespace tint::spirv::ir { + +BuiltinCall::BuiltinCall(Id id, + core::ir::InstructionResult* result, + BuiltinFn func, + VectorRef arguments) + : Base(id, result, arguments), func_(func) { + flags_.Add(Flag::kSequenced); + TINT_ASSERT(func != BuiltinFn::kNone); +} + +BuiltinCall::~BuiltinCall() = default; + +BuiltinCall* BuiltinCall::Clone(core::ir::CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto new_args = ctx.Clone(Args()); + auto new_explicit = ExplicitTemplateParams(); + + auto* inst = ctx.ir.CreateInstruction(new_result, func_, new_args); + if (!new_explicit.IsEmpty()) { + inst->SetExplicitTemplateParams(new_explicit); + } + return inst; +} + +tint::core::ir::Instruction::Accesses BuiltinCall::GetSideEffects() const { + return spirv::GetSideEffects(func_); +} + +std::string BuiltinCall::FriendlyName() const { + return std::string("spirv.") + str(func_); +} + +} // namespace tint::spirv::ir diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.h b/3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.h new file mode 100644 index 000000000..8d9e44f50 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/builtin_call.h @@ -0,0 +1,82 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_IR_BUILTIN_CALL_H_ +#define SRC_TINT_LANG_SPIRV_IR_BUILTIN_CALL_H_ + +#include + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/ir/builtin_call.h" +#include "src/tint/lang/spirv/builtin_fn.h" +#include "src/tint/lang/spirv/intrinsic/dialect.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::spirv::ir { + +/// A spirv builtin call instruction in the IR. +class BuiltinCall final : public Castable { + public: + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param func the builtin function + /// @param args the conversion arguments + BuiltinCall(Id id, + core::ir::InstructionResult* result, + BuiltinFn func, + VectorRef args = tint::Empty); + + ~BuiltinCall() override; + + /// @copydoc core::ir::Instruction::Clone() + BuiltinCall* Clone(core::ir::CloneContext& ctx) override; + + /// @returns the builtin function + BuiltinFn Func() const { return func_; } + + /// @returns the identifier for the function + size_t FuncId() const override { return static_cast(func_); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override; + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override { + return spirv::intrinsic::Dialect::kData; + } + + /// @returns an access information for the function + Accesses GetSideEffects() const override; + + private: + BuiltinFn func_; +}; + +} // namespace tint::spirv::ir + +#endif // SRC_TINT_LANG_SPIRV_IR_BUILTIN_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.cc b/3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.cc new file mode 100644 index 000000000..b361e06bd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.cc @@ -0,0 +1,56 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/ir/copy_logical.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::ir::CopyLogical); + +namespace tint::spirv::ir { + +CopyLogical::CopyLogical(Id id, core::ir::InstructionResult* result, core::ir::Value* arg) + : Base(id) { + AddOperand(CopyLogical::kArgOperandOffset, arg); + AddResult(result); +} + +CopyLogical::~CopyLogical() = default; + +CopyLogical* CopyLogical::Clone(core::ir::CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* arg = ctx.Remap(Arg()); + return ctx.ir.CreateInstruction(new_result, arg); +} + +std::string CopyLogical::FriendlyName() const { + return std::string("spirv.copy_logical"); +} + +} // namespace tint::spirv::ir diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.h b/3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.h new file mode 100644 index 000000000..c9ed7ccbe --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/copy_logical.h @@ -0,0 +1,73 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_IR_COPY_LOGICAL_H_ +#define SRC_TINT_LANG_SPIRV_IR_COPY_LOGICAL_H_ + +#include + +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::spirv::ir { + +/// A spirv OpCopyLogical instruction in the IR. +class CopyLogical final : public Castable { + public: + /// The offset in Operands() for Arg. + static constexpr size_t kArgOperandOffset = 0; + + /// The number of results. + static constexpr size_t kNumResults = 1; + + /// The number of operands. + static constexpr size_t kNumOperands = 1; + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param arg the object to copy + CopyLogical(Id id, core::ir::InstructionResult* result, core::ir::Value* arg); + + ~CopyLogical() override; + + /// @copydoc Instruction::Clone() + CopyLogical* Clone(core::ir::CloneContext& ctx) override; + + /// @returns The argument being copied. + core::ir::Value* Arg() { return Operand(kArgOperandOffset); } + + /// @returns The argument being copied. + const core::ir::Value* Arg() const { return Operand(kArgOperandOffset); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override; +}; + +} // namespace tint::spirv::ir + +#endif // SRC_TINT_LANG_SPIRV_IR_COPY_LOGICAL_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.cc b/3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.cc new file mode 100644 index 000000000..c691e340e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.cc @@ -0,0 +1,38 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/ir/literal_operand.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::ir::LiteralOperand); + +namespace tint::spirv::ir { + +LiteralOperand::LiteralOperand(const core::constant::Value* value) : Base(value) {} + +LiteralOperand::~LiteralOperand() = default; + +} // namespace tint::spirv::ir diff --git a/3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.h b/3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.h new file mode 100644 index 000000000..c5275caef --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/ir/literal_operand.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_IR_LITERAL_OPERAND_H_ +#define SRC_TINT_LANG_SPIRV_IR_LITERAL_OPERAND_H_ + +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::spirv::ir { + +/// LiteralOperand is a type of constant value that is intended to be emitted as a literal in +/// the SPIR-V instruction stream. +class LiteralOperand final : public Castable { + public: + /// Constructor + /// @param value the operand value + explicit LiteralOperand(const core::constant::Value* value); + /// Destructor + ~LiteralOperand() override; +}; + +} // namespace tint::spirv::ir + +#endif // SRC_TINT_LANG_SPIRV_IR_LITERAL_OPERAND_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/common/common.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/common/common.cc new file mode 100644 index 000000000..330e9354a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/common/common.cc @@ -0,0 +1,33 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +// A placeholder symbol used to emit a symbol for this lib target. +int tint_lang_spirv_reader_common_symbol = 1; diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/common/options.h b/3rdparty/dawn/src/tint/lang/spirv/reader/common/options.h new file mode 100644 index 000000000..32d13d32c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/common/options.h @@ -0,0 +1,56 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_COMMON_OPTIONS_H_ +#define SRC_TINT_LANG_SPIRV_READER_COMMON_OPTIONS_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/wgsl/allowed_features.h" + +namespace tint::spirv::reader { + +/// Options that control how the SPIR-V parser should behave. +struct Options { + /// Set to `true` to allow calls to derivative builtins in non-uniform control flow. + bool allow_non_uniform_derivatives = false; + // TODO(jrprice): Remove this when SPIR-V -> IR and IR -> WGSL are separate steps. + /// The extensions and language features that are allowed to be used in the generated WGSL. + wgsl::AllowedFeatures allowed_features = {}; + + /// Mapping from a SPIR-V Sampler binding point to a WGSL sampler binding + /// point. This allows remapping samplers which are split out of the + /// combined texture/sampler pairs in SPIR-V. + /// If this map is empty, any binding conflicts will be automatically resolved by incrementing + /// binding numbers until they are unique. + std::unordered_map sampler_mappings{}; +}; + +} // namespace tint::spirv::reader + +#endif // SRC_TINT_LANG_SPIRV_READER_COMMON_OPTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.cc new file mode 100644 index 000000000..62de2e9cf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.cc @@ -0,0 +1,570 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/atomics.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/hashset.h" + +namespace tint::spirv::reader::lower { +namespace { + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The `ir::Value`s to be converted to atomics + Vector values_to_convert_{}; + + /// The `ir::Values`s which have had their types changed, they then need to have their + /// loads/stores updated to match. This maps to the root FunctionParam or Var for each atomic. + Vector values_to_fix_usages_{}; + + /// Any `ir::UserCall` instructions which have atomic params which need to + /// be updated. + Hashset user_calls_to_convert_{}; + + /// The `ir::Value`s which have been converted + Hashset converted_{}; + + /// Function to atomic replacements, this is done by hashcode since the + /// function pointer is combined with the parameters which are converted to + /// atomics. + Hashmap func_hash_to_func_{}; + + struct ForkedStruct { + const core::type::Struct* src_struct = nullptr; + const core::type::Struct* dst_struct = nullptr; + Hashset atomic_members; + }; + + /// Map of original structure to forked structure information + Hashmap forked_structs_{}; + /// List of value objects to update with new struct types + Hashset values_needing_struct_update_{}; + + /// Process the module. + void Process() { + Vector builtin_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* builtin = inst->As()) { + switch (builtin->Func()) { + case spirv::BuiltinFn::kAtomicLoad: + case spirv::BuiltinFn::kAtomicStore: + case spirv::BuiltinFn::kAtomicExchange: + case spirv::BuiltinFn::kAtomicCompareExchange: + case spirv::BuiltinFn::kAtomicIAdd: + case spirv::BuiltinFn::kAtomicISub: + case spirv::BuiltinFn::kAtomicSMax: + case spirv::BuiltinFn::kAtomicSMin: + case spirv::BuiltinFn::kAtomicUMax: + case spirv::BuiltinFn::kAtomicUMin: + case spirv::BuiltinFn::kAtomicAnd: + case spirv::BuiltinFn::kAtomicOr: + case spirv::BuiltinFn::kAtomicXor: + case spirv::BuiltinFn::kAtomicIIncrement: + case spirv::BuiltinFn::kAtomicIDecrement: + builtin_worklist.Push(builtin); + break; + default: + // Ignore any unknown instruction. The `Texture` transform runs after this + // one which will catch any unknown instructions. + break; + } + } + } + + for (auto* builtin : builtin_worklist) { + values_to_convert_.Push(builtin->Args()[0]); + + switch (builtin->Func()) { + case spirv::BuiltinFn::kAtomicLoad: + AtomicOpNoArgs(builtin, core::BuiltinFn::kAtomicLoad); + break; + case spirv::BuiltinFn::kAtomicStore: + AtomicOp(builtin, core::BuiltinFn::kAtomicStore); + break; + case spirv::BuiltinFn::kAtomicExchange: + AtomicOp(builtin, core::BuiltinFn::kAtomicExchange); + break; + case spirv::BuiltinFn::kAtomicCompareExchange: + AtomicCompareExchange(builtin); + break; + case spirv::BuiltinFn::kAtomicIAdd: + AtomicOp(builtin, core::BuiltinFn::kAtomicAdd); + break; + case spirv::BuiltinFn::kAtomicISub: + AtomicOp(builtin, core::BuiltinFn::kAtomicSub); + break; + case spirv::BuiltinFn::kAtomicSMax: + AtomicOp(builtin, core::BuiltinFn::kAtomicMax); + break; + case spirv::BuiltinFn::kAtomicSMin: + AtomicOp(builtin, core::BuiltinFn::kAtomicMin); + break; + case spirv::BuiltinFn::kAtomicUMax: + AtomicOp(builtin, core::BuiltinFn::kAtomicMax); + break; + case spirv::BuiltinFn::kAtomicUMin: + AtomicOp(builtin, core::BuiltinFn::kAtomicMin); + break; + case spirv::BuiltinFn::kAtomicAnd: + AtomicOp(builtin, core::BuiltinFn::kAtomicAnd); + break; + case spirv::BuiltinFn::kAtomicOr: + AtomicOp(builtin, core::BuiltinFn::kAtomicOr); + break; + case spirv::BuiltinFn::kAtomicXor: + AtomicOp(builtin, core::BuiltinFn::kAtomicXor); + break; + case spirv::BuiltinFn::kAtomicIIncrement: + AtomicChangeByOne(builtin, core::BuiltinFn::kAtomicAdd); + break; + case spirv::BuiltinFn::kAtomicIDecrement: + AtomicChangeByOne(builtin, core::BuiltinFn::kAtomicSub); + break; + default: + TINT_UNREACHABLE() << "unknown spirv builtin: " << builtin->Func(); + } + } + + // Propagate up the instruction list until we get to the root identifier + while (!values_to_convert_.IsEmpty()) { + auto* val = values_to_convert_.Pop(); + + if (converted_.Add(val)) { + ConvertAtomicValue(val); + } + } + + ProcessForkedStructs(); + ReplaceStructTypes(); + + // The double loop happens because when we convert user calls, that will + // add more values to convert, but those values can find user calls to + // convert, so we have to work until we stabilize + while (!values_to_fix_usages_.IsEmpty()) { + while (!values_to_fix_usages_.IsEmpty()) { + auto* val = values_to_fix_usages_.Pop(); + ConvertUsagesToAtomic(val); + } + + auto user_calls = user_calls_to_convert_.Vector(); + // Sort for deterministic output + user_calls.Sort(); + for (auto& call : user_calls) { + ConvertUserCall(call); + } + user_calls_to_convert_.Clear(); + } + } + + core::ir::Value* One(const core::type::Type* const_ty) { + return tint::Switch( + const_ty, // + [&](const core::type::I32*) { return b.Constant(1_i); }, + [&](const core::type::U32*) { return b.Constant(1_u); }, // + TINT_ICE_ON_NO_MATCH); + } + + void AtomicCompareExchange(spirv::ir::BuiltinCall* call) { + auto args = call->Args(); + + b.InsertBefore(call, [&] { + auto* var = args[0]; + + auto* val = args[4]; + auto* comp = args[5]; + + auto* strct = + core::type::CreateAtomicCompareExchangeResult(ty, ir.symbols, val->Type()); + + auto* bi = b.Call(strct, core::BuiltinFn::kAtomicCompareExchangeWeak, var, comp, val); + b.AccessWithResult(call->DetachResult(), bi, 0_u); + }); + call->Destroy(); + } + + void AtomicChangeByOne(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) { + auto args = call->Args(); + + b.InsertBefore(call, [&] { + auto* var = args[0]; + auto* one = One(call->Result()->Type()); + b.CallWithResult(call->DetachResult(), fn, var, one); + }); + call->Destroy(); + } + + void AtomicOpNoArgs(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) { + auto args = call->Args(); + + b.InsertBefore(call, [&] { + auto* var = args[0]; + b.CallWithResult(call->DetachResult(), fn, var); + }); + call->Destroy(); + } + + void AtomicOp(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) { + auto args = call->Args(); + + b.InsertBefore(call, [&] { + auto* var = args[0]; + auto* val = args[3]; + b.CallWithResult(call->DetachResult(), fn, var, val); + }); + call->Destroy(); + } + + void ProcessForkedStructs() { + for (auto iter : forked_structs_) { + auto& forked = iter.value; + CreateForkIfNeeded(forked.src_struct); + } + } + + const core::type::Struct* CreateForkIfNeeded(const core::type::Struct* src_struct) { + if (!forked_structs_.Contains(src_struct)) { + return src_struct; + } + + auto forked = forked_structs_.Get(src_struct); + if (forked->dst_struct != nullptr) { + return forked->dst_struct; + } + + auto members = forked->src_struct->Members(); + Vector new_members; + for (size_t i = 0; i < members.Length(); ++i) { + auto* member = members[i]; + const core::type::Type* new_member_type = nullptr; + if (forked->atomic_members.Contains(i)) { + new_member_type = AtomicTypeFor(nullptr, member->Type()); + } else { + new_member_type = member->Type(); + } + auto index = static_cast(i); + new_members.Push(ty.Get( + member->Name(), new_member_type, index, member->Offset(), member->Align(), + member->Size(), core::IOAttributes{})); + } + + // Create a new struct with the rewritten members. + auto name = ir.symbols.New(forked->src_struct->Name().Name() + "_atomic"); + forked->dst_struct = ty.Struct(name, std::move(new_members)); + + return forked->dst_struct; + } + + void ReplaceStructTypes() { + for (auto iter : values_needing_struct_update_) { + auto* orig_ty = iter->Type(); + iter->SetType(AtomicTypeFor(nullptr, orig_ty)); + } + } + + void ConvertAtomicValue(core::ir::Value* val) { + tint::Switch( // + val, // + [&](core::ir::InstructionResult* res) { + auto* orig_ty = res->Type(); + auto* atomic_ty = AtomicTypeFor(val, orig_ty); + res->SetType(atomic_ty); + + tint::Switch( + res->Instruction(), + [&](core::ir::Access* a) { + CheckForStructForking(a); + values_to_convert_.Push(a->Object()); + values_to_fix_usages_.Push(a->Result()); + }, + [&](core::ir::Let* l) { + values_to_convert_.Push(l->Value()); + values_to_fix_usages_.Push(l->Result()); + }, + [&](core::ir::Var* v) { + auto* var_res = v->Result(); + values_to_fix_usages_.Push(var_res); + }, + TINT_ICE_ON_NO_MATCH); + }, + [&](core::ir::FunctionParam* param) { + auto* orig_ty = param->Type(); + auto* atomic_ty = AtomicTypeFor(val, orig_ty); + param->SetType(atomic_ty); + values_to_fix_usages_.Push(param); + + for (auto& usage : param->Function()->UsagesUnsorted()) { + if (usage->instruction->Is()) { + continue; + } + + auto* call = usage->instruction->As(); + TINT_ASSERT(call); + values_to_convert_.Push(call->Args()[param->Index()]); + } + }, + TINT_ICE_ON_NO_MATCH); + } + + void ConvertUsagesToAtomic(core::ir::Value* val) { + val->ForEachUseUnsorted([&](const core::ir::Usage& usage) { + auto* inst = usage.instruction; + + tint::Switch( // + inst, + [&](core::ir::Load* ld) { + TINT_ASSERT(ld->From()->Type()->UnwrapPtr()->Is()); + + b.InsertBefore(ld, [&] { + b.CallWithResult(ld->DetachResult(), core::BuiltinFn::kAtomicLoad, + ld->From()); + }); + ld->Destroy(); + }, + [&](core::ir::Store* st) { + TINT_ASSERT(st->To()->Type()->UnwrapPtr()->Is()); + + b.InsertBefore(st, [&] { + b.Call(ty.void_(), core::BuiltinFn::kAtomicStore, st->To(), st->From()); + }); + st->Destroy(); + }, + [&](core::ir::Access* access) { + auto* res = access->Result(); + auto* new_ty = TypeForAccess(access); + if (new_ty == res->Type()) { + return; + } + + res->SetType(new_ty); + if (converted_.Add(res)) { + values_to_fix_usages_.Push(res); + } + }, + [&](core::ir::Let* l) { + auto* res = l->Result(); + auto* orig_ty = res->Type(); + auto* new_ty = AtomicTypeFor(nullptr, orig_ty); + if (new_ty == orig_ty) { + return; + } + + res->SetType(new_ty); + if (converted_.Add(res)) { + values_to_fix_usages_.Push(res); + } + }, + [&](core::ir::UserCall* uc) { user_calls_to_convert_.Add(uc); }, + [&](core::ir::CoreBuiltinCall* bc) { + // The only non-atomic builtin that can touch something that contains an atomic + // is arrayLength. + if (bc->Func() == core::BuiltinFn::kArrayLength) { + return; + } + + // This was converted when we switched from a SPIR-V intrinsic to core + TINT_ASSERT(core::IsAtomic(bc->Func())); + TINT_ASSERT(bc->Args()[0]->Type()->UnwrapPtr()->Is()); + }, + TINT_ICE_ON_NO_MATCH); + }); + } + + // The user calls need to check all of the parameters which were converted + // to atomics and create a forked function call for that combination of + // parameters. + void ConvertUserCall(core::ir::UserCall* uc) { + auto* target = uc->Target(); + auto& params = target->Params(); + const auto& args = uc->Args(); + + Vector to_convert; + for (size_t i = 0; i < args.Length(); ++i) { + if (params[i]->Type() != args[i]->Type()) { + to_convert.Push(i); + } + } + // Everything is already converted we're done. + if (to_convert.IsEmpty()) { + return; + } + + // Hash based on the original function pointer and the specific + // parameters we're converting. + auto hash = Hash(target); + hash = HashCombine(hash, to_convert); + + auto* new_fn = func_hash_to_func_.GetOrAdd(hash, [&] { + core::ir::CloneContext ctx{ir}; + auto* fn = uc->Target()->Clone(ctx); + ir.functions.Push(fn); + + for (auto idx : to_convert) { + auto* p = fn->Params()[idx]; + p->SetType(args[idx]->Type()); + + values_to_fix_usages_.Push(p); + } + return fn; + }); + uc->SetTarget(new_fn); + } + + const core::type::Type* TypeForAccess(core::ir::Access* access) { + auto* ptr = access->Object()->Type()->As(); + TINT_ASSERT(ptr); + + auto* cur_ty = ptr->UnwrapPtr(); + for (auto& idx : access->Indices()) { + tint::Switch( // + cur_ty, // + [&](const core::type::Struct* str) { + if (forked_structs_.Contains(str)) { + str = forked_structs_.Get(str)->dst_struct; + } + + auto* const_val = idx->As(); + TINT_ASSERT(const_val); + + auto const_idx = const_val->Value()->ValueAs(); + cur_ty = str->Members()[const_idx]->Type(); + }, + [&](const core::type::Array* arr) { cur_ty = arr->ElemType(); }); + } + return ty.ptr(ptr->AddressSpace(), cur_ty, ptr->Access()); + } + + void CheckForStructForking(core::ir::Access* access) { + auto* cur_ty = access->Object()->Type()->UnwrapPtr(); + for (auto* idx : access->Indices()) { + tint::Switch( + cur_ty, // + [&](const core::type::Struct* str) { + auto& forked = Fork(str); + + auto* const_val = idx->As(); + TINT_ASSERT(const_val); + + auto const_idx = const_val->Value()->ValueAs(); + forked.atomic_members.Add(const_idx); + + cur_ty = str->Members()[const_idx]->Type(); + }, // + [&](const core::type::Array* ary) { cur_ty = ary->ElemType(); }, // + TINT_ICE_ON_NO_MATCH); + } + } + + const core::type::Type* AtomicTypeFor(core::ir::Value* val, const core::type::Type* orig_ty) { + return tint::Switch( + orig_ty, // + [&](const core::type::I32*) { return ty.atomic(orig_ty); }, + [&](const core::type::U32*) { return ty.atomic(orig_ty); }, + [&](const core::type::Struct* str) { + // If a `val` is provided, then we're getting the atomic type for a value as we walk + // the full instruction list. This means we can't replace structs at this point + // because we may not have all the information about what members are atomics. So, + // we record the type needs to be updated for `val` after we've created the structs. + // (This works through pointers because this method is recursive, so a pointer to a + // struct will record the type needs updating). + // + // In the case `val` is a nullptr then we've gathered all the needed information for + // which members are atomics and can create the forked strut. + if (val) { + auto* res = val->As(); + TINT_ASSERT(res); + + values_needing_struct_update_.Add(res); + Fork(str); + return str; + } + + return CreateForkIfNeeded(str); + }, + [&](const core::type::Array* arr) { + if (arr->Count()->Is()) { + return ty.runtime_array(AtomicTypeFor(val, arr->ElemType())); + } + auto count = arr->ConstantCount(); + TINT_ASSERT(count); + + return ty.array(AtomicTypeFor(val, arr->ElemType()), u32(count.value())); + }, + [&](const core::type::Pointer* ptr) { + return ty.ptr(ptr->AddressSpace(), AtomicTypeFor(val, ptr->StoreType()), + ptr->Access()); + }, + [&](const core::type::Atomic* atomic) { return atomic; }, // + TINT_ICE_ON_NO_MATCH); + } + + ForkedStruct& Fork(const core::type::Struct* str) { + return forked_structs_.GetOrAdd(str, [&]() { + ForkedStruct forked; + forked.src_struct = str; + return forked; + }); + } +}; + +} // namespace + +Result Atomics(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.Atomics", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowPointerToHandle, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.h new file mode 100644 index 000000000..ee21c99e1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/atomics.h @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_ATOMICS_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_ATOMICS_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// Atomics is a transform that converts SPIR-V atomic methods into the form expected by Tint's +/// core IR. +/// @param module the module to transform +/// @returns success or failure +Result Atomics(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_ATOMICS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.cc new file mode 100644 index 000000000..d773ebb22 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.cc @@ -0,0 +1,1327 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/builtins.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" + +namespace tint::spirv::reader::lower { +namespace { + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + Vector builtin_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* builtin = inst->As()) { + builtin_worklist.Push(builtin); + } + } + + // Replace the builtins that we found. + for (auto* builtin : builtin_worklist) { + switch (builtin->Func()) { + case spirv::BuiltinFn::kNormalize: + Normalize(builtin); + break; + case spirv::BuiltinFn::kInverse: + Inverse(builtin); + break; + case spirv::BuiltinFn::kSign: + Sign(builtin); + break; + case spirv::BuiltinFn::kAbs: + Abs(builtin); + break; + case spirv::BuiltinFn::kSMax: + SMax(builtin); + break; + case spirv::BuiltinFn::kSMin: + SMin(builtin); + break; + case spirv::BuiltinFn::kSClamp: + SClamp(builtin); + break; + case spirv::BuiltinFn::kUMax: + UMax(builtin); + break; + case spirv::BuiltinFn::kUMin: + UMin(builtin); + break; + case spirv::BuiltinFn::kUClamp: + UClamp(builtin); + break; + case spirv::BuiltinFn::kFindILsb: + FindILsb(builtin); + break; + case spirv::BuiltinFn::kFindSMsb: + FindSMsb(builtin); + break; + case spirv::BuiltinFn::kFindUMsb: + FindUMsb(builtin); + break; + case spirv::BuiltinFn::kRefract: + Refract(builtin); + break; + case spirv::BuiltinFn::kReflect: + Reflect(builtin); + break; + case spirv::BuiltinFn::kFaceForward: + FaceForward(builtin); + break; + case spirv::BuiltinFn::kLdexp: + Ldexp(builtin); + break; + case spirv::BuiltinFn::kModf: + Modf(builtin); + break; + case spirv::BuiltinFn::kFrexp: + Frexp(builtin); + break; + case spirv::BuiltinFn::kBitCount: + BitCount(builtin); + break; + case spirv::BuiltinFn::kBitFieldInsert: + BitFieldInsert(builtin); + break; + case spirv::BuiltinFn::kBitFieldSExtract: + BitFieldSExtract(builtin); + break; + case spirv::BuiltinFn::kBitFieldUExtract: + BitFieldUExtract(builtin); + break; + case spirv::BuiltinFn::kAdd: + Add(builtin); + break; + case spirv::BuiltinFn::kSub: + Sub(builtin); + break; + case spirv::BuiltinFn::kMul: + Mul(builtin); + break; + case spirv::BuiltinFn::kSDiv: + SDiv(builtin); + break; + case spirv::BuiltinFn::kSMod: + SMod(builtin); + break; + case spirv::BuiltinFn::kConvertFToS: + ConvertFToS(builtin); + break; + case spirv::BuiltinFn::kConvertSToF: + ConvertSToF(builtin); + break; + case spirv::BuiltinFn::kConvertUToF: + ConvertUToF(builtin); + break; + case spirv::BuiltinFn::kBitwiseAnd: + BitwiseAnd(builtin); + break; + case spirv::BuiltinFn::kBitwiseOr: + BitwiseOr(builtin); + break; + case spirv::BuiltinFn::kBitwiseXor: + BitwiseXor(builtin); + break; + case spirv::BuiltinFn::kEqual: + Equal(builtin); + break; + case spirv::BuiltinFn::kNotEqual: + NotEqual(builtin); + break; + case spirv::BuiltinFn::kSGreaterThan: + SGreaterThan(builtin); + break; + case spirv::BuiltinFn::kSGreaterThanEqual: + SGreaterThanEqual(builtin); + break; + case spirv::BuiltinFn::kSLessThan: + SLessThan(builtin); + break; + case spirv::BuiltinFn::kSLessThanEqual: + SLessThanEqual(builtin); + break; + case spirv::BuiltinFn::kUGreaterThan: + UGreaterThan(builtin); + break; + case spirv::BuiltinFn::kUGreaterThanEqual: + UGreaterThanEqual(builtin); + break; + case spirv::BuiltinFn::kULessThan: + ULessThan(builtin); + break; + case spirv::BuiltinFn::kULessThanEqual: + ULessThanEqual(builtin); + break; + case spirv::BuiltinFn::kShiftLeftLogical: + ShiftLeftLogical(builtin); + break; + case spirv::BuiltinFn::kShiftRightLogical: + ShiftRightLogical(builtin); + break; + case spirv::BuiltinFn::kShiftRightArithmetic: + ShiftRightArithmetic(builtin); + break; + case spirv::BuiltinFn::kNot: + Not(builtin); + break; + case spirv::BuiltinFn::kSNegate: + SNegate(builtin); + break; + case spirv::BuiltinFn::kFMod: + FMod(builtin); + break; + case spirv::BuiltinFn::kSelect: + Select(builtin); + break; + case spirv::BuiltinFn::kOuterProduct: + OuterProduct(builtin); + break; + case spirv::BuiltinFn::kGroupNonUniformBroadcast: + GroupNonUniformBuiltin(builtin, core::BuiltinFn::kSubgroupBroadcast); + break; + case spirv::BuiltinFn::kGroupNonUniformShuffle: + GroupNonUniformBuiltin(builtin, core::BuiltinFn::kSubgroupShuffle); + break; + case spirv::BuiltinFn::kGroupNonUniformShuffleXor: + GroupNonUniformBuiltin(builtin, core::BuiltinFn::kSubgroupShuffleXor); + break; + case spirv::BuiltinFn::kGroupNonUniformShuffleDown: + GroupNonUniformBuiltin(builtin, core::BuiltinFn::kSubgroupShuffleDown); + break; + case spirv::BuiltinFn::kGroupNonUniformShuffleUp: + GroupNonUniformBuiltin(builtin, core::BuiltinFn::kSubgroupShuffleUp); + break; + case spirv::BuiltinFn::kGroupNonUniformBroadcastFirst: + GroupNonUniformBroadcastFirst(builtin); + break; + case spirv::BuiltinFn::kGroupNonUniformQuadBroadcast: + GroupNonUniformBuiltin(builtin, core::BuiltinFn::kQuadBroadcast); + break; + case spirv::BuiltinFn::kGroupNonUniformQuadSwap: + GroupNonUniformQuadSwap(builtin); + break; + case spirv::BuiltinFn::kGroupNonUniformSMin: + GroupNonUniformMinMax(builtin, core::BuiltinFn::kSubgroupMin); + break; + case spirv::BuiltinFn::kGroupNonUniformSMax: + GroupNonUniformMinMax(builtin, core::BuiltinFn::kSubgroupMax); + break; + case spirv::BuiltinFn::kAtomicLoad: + case spirv::BuiltinFn::kAtomicStore: + case spirv::BuiltinFn::kAtomicExchange: + case spirv::BuiltinFn::kAtomicCompareExchange: + case spirv::BuiltinFn::kAtomicIAdd: + case spirv::BuiltinFn::kAtomicISub: + case spirv::BuiltinFn::kAtomicSMax: + case spirv::BuiltinFn::kAtomicSMin: + case spirv::BuiltinFn::kAtomicUMax: + case spirv::BuiltinFn::kAtomicUMin: + case spirv::BuiltinFn::kAtomicAnd: + case spirv::BuiltinFn::kAtomicOr: + case spirv::BuiltinFn::kAtomicXor: + case spirv::BuiltinFn::kAtomicIIncrement: + case spirv::BuiltinFn::kAtomicIDecrement: + // Ignore Atomics, they'll be handled by the `Atomics` transform. + break; + case spirv::BuiltinFn::kOpImage: + case spirv::BuiltinFn::kOpSampledImage: + case spirv::BuiltinFn::kImageRead: + case spirv::BuiltinFn::kImageFetch: + case spirv::BuiltinFn::kImageGather: + case spirv::BuiltinFn::kImageDrefGather: + case spirv::BuiltinFn::kImageQueryLevels: + case spirv::BuiltinFn::kImageQuerySamples: + case spirv::BuiltinFn::kImageQuerySize: + case spirv::BuiltinFn::kImageQuerySizeLod: + case spirv::BuiltinFn::kImageSampleExplicitLod: + case spirv::BuiltinFn::kImageSampleImplicitLod: + case spirv::BuiltinFn::kImageSampleProjImplicitLod: + case spirv::BuiltinFn::kImageSampleProjExplicitLod: + case spirv::BuiltinFn::kImageSampleDrefImplicitLod: + case spirv::BuiltinFn::kImageSampleDrefExplicitLod: + case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod: + case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod: + case spirv::BuiltinFn::kImageWrite: + // Ignore image methods, they'll be handled by the `Texture` transform. + break; + default: + TINT_UNREACHABLE() << "unknown spirv builtin: " << builtin->Func(); + } + } + } + + void GroupNonUniformMinMax(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) { + auto* value = call->Args()[2]; + + auto* orig_type = call->Result()->Type(); + b.InsertBefore(call, [&] { + auto* type = orig_type; + if (orig_type->IsUnsignedIntegerScalarOrVector()) { + type = ty.MatchWidth(ty.i32(), type); + value = b.Convert(type, value)->Result(); + } + + value = b.Call(type, fn, Vector{value})->Result(); + + if (type != orig_type) { + value = b.Convert(call->Result()->Type(), value)->Result(); + } + + call->Result()->ReplaceAllUsesWith(value); + }); + call->Destroy(); + } + + void GroupNonUniformQuadSwap(spirv::ir::BuiltinCall* call) { + auto* value = call->Args()[1]; + auto* dir_val = call->Args()[2]; + + TINT_ASSERT(dir_val->Is()); + auto* cnst = dir_val->As(); + TINT_ASSERT(cnst); + + uint32_t dir = cnst->Value()->ValueAs(); + core::BuiltinFn fn = core::BuiltinFn::kNone; + switch (dir) { + case 0: + fn = core::BuiltinFn::kQuadSwapX; + break; + case 1: + fn = core::BuiltinFn::kQuadSwapY; + break; + case 2: + fn = core::BuiltinFn::kQuadSwapDiagonal; + break; + default: + TINT_UNREACHABLE(); + } + + auto* type = call->Result()->Type(); + b.InsertBefore(call, [&] { + if (type->DeepestElement()->Is()) { + type = ty.MatchWidth(ty.u32(), type); + value = b.Convert(type, value)->Result(); + } + + core::ir::Value* c = b.Call(type, fn, Vector{value})->Result(); + + if (type != call->Result()->Type()) { + c = b.Convert(call->Result()->Type(), c)->Result(); + } + + call->Result()->ReplaceAllUsesWith(c); + }); + call->Destroy(); + } + + void GroupNonUniformBuiltin(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) { + auto* value = call->Args()[1]; + auto* id = call->Args()[2]; + + auto* type = call->Result()->Type(); + b.InsertBefore(call, [&] { + if (type->DeepestElement()->Is()) { + type = ty.MatchWidth(ty.u32(), type); + value = b.Convert(type, value)->Result(); + } + + core::ir::Value* c = b.Call(type, fn, Vector{value, id})->Result(); + + if (type != call->Result()->Type()) { + c = b.Convert(call->Result()->Type(), c)->Result(); + } + + call->Result()->ReplaceAllUsesWith(c); + }); + call->Destroy(); + } + + void GroupNonUniformBroadcastFirst(spirv::ir::BuiltinCall* call) { + auto* value = call->Args()[1]; + + auto* type = call->Result()->Type(); + b.InsertBefore(call, [&] { + if (type->DeepestElement()->Is()) { + type = ty.MatchWidth(ty.u32(), type); + value = b.Convert(type, value)->Result(); + } + + core::ir::Value* c = + b.Call(type, core::BuiltinFn::kSubgroupBroadcastFirst, Vector{value})->Result(); + + if (type != call->Result()->Type()) { + c = b.Convert(call->Result()->Type(), c)->Result(); + } + + call->Result()->ReplaceAllUsesWith(c); + }); + call->Destroy(); + } + + void OuterProduct(spirv::ir::BuiltinCall* call) { + auto* vector1 = call->Args()[0]; + auto* vector2 = call->Args()[1]; + + uint32_t rows = vector1->Type()->As()->Width(); + uint32_t cols = vector2->Type()->As()->Width(); + + auto* elem_ty = vector1->Type()->DeepestElement(); + + b.InsertBefore(call, [&] { + Vector col_vectors; + + for (uint32_t col = 0; col < cols; ++col) { + Vector col_elements; + auto* v2_element = b.Access(elem_ty, vector2, u32(col)); + + for (uint32_t row = 0; row < rows; ++row) { + auto* v1_element = b.Access(elem_ty, vector1, u32(row)); + auto* result = b.Multiply(v1_element, v2_element)->Result(); + col_elements.Push(result); + } + + auto* row_vector = b.Construct(ty.vec(elem_ty, rows), col_elements)->Result(); + col_vectors.Push(row_vector); + } + b.ConstructWithResult(call->DetachResult(), col_vectors); + }); + + call->Destroy(); + } + + void Select(spirv::ir::BuiltinCall* call) { + auto* cond = call->Args()[0]; + auto* true_ = call->Args()[1]; + auto* false_ = call->Args()[2]; + b.InsertBefore(call, [&] { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kSelect, false_, true_, cond); + }); + call->Destroy(); + } + + // FMod(x, y) emulated with: x - y * floor(x / y) + void FMod(spirv::ir::BuiltinCall* call) { + auto* x = call->Args()[0]; + auto* y = call->Args()[1]; + + auto* res_ty = call->Result()->Type(); + b.InsertBefore(call, [&] { + auto* div = b.Divide(x, y); + auto* floor = b.Call(res_ty, core::BuiltinFn::kFloor, div); + auto* mul = b.Multiply(y, floor); + auto* sub = b.Subtract(x, mul); + + call->Result()->ReplaceAllUsesWith(sub->Result()); + }); + call->Destroy(); + } + + void SNegate(spirv::ir::BuiltinCall* call) { + auto* val = call->Args()[0]; + + auto* res_ty = call->Result()->Type(); + auto* neg_ty = ty.MatchWidth(ty.i32(), val->Type()); + b.InsertBefore(call, [&] { + if (val->Type() != neg_ty) { + val = b.Bitcast(neg_ty, val)->Result(); + } + val = b.Negation(val)->Result(); + + if (neg_ty != res_ty) { + val = b.Bitcast(res_ty, val)->Result(); + } + call->Result()->ReplaceAllUsesWith(val); + }); + call->Destroy(); + } + + void Not(spirv::ir::BuiltinCall* call) { + auto* val = call->Args()[0]; + auto* result_ty = call->Result()->Type(); + b.InsertBefore(call, [&] { + auto* complement = b.Complement(val)->Result(); + if (val->Type() != result_ty) { + complement = b.Bitcast(result_ty, complement)->Result(); + } + call->Result()->ReplaceAllUsesWith(complement); + }); + call->Destroy(); + } + + void ConvertSToF(spirv::ir::BuiltinCall* call) { + b.InsertBefore(call, [&] { + auto* result_ty = call->Result()->Type(); + + auto* arg = call->Args()[0]; + if (arg->Type()->IsUnsignedIntegerScalarOrVector()) { + arg = b.Bitcast(ty.MatchWidth(ty.i32(), result_ty), arg)->Result(); + } + + b.ConvertWithResult(call->DetachResult(), arg); + }); + call->Destroy(); + } + + void ConvertUToF(spirv::ir::BuiltinCall* call) { + b.InsertBefore(call, [&] { + auto* result_ty = call->Result()->Type(); + + auto* arg = call->Args()[0]; + if (arg->Type()->IsSignedIntegerScalarOrVector()) { + arg = b.Bitcast(ty.MatchWidth(ty.u32(), result_ty), arg)->Result(); + } + + b.ConvertWithResult(call->DetachResult(), arg); + }); + call->Destroy(); + } + + void ConvertFToS(spirv::ir::BuiltinCall* call) { + b.InsertBefore(call, [&] { + auto* res_ty = call->Result()->Type(); + auto deepest = res_ty->DeepestElement(); + + auto* res = b.Convert(ty.MatchWidth(ty.i32(), res_ty), call->Args()[0])->Result(); + if (deepest->IsUnsignedIntegerScalar()) { + res = b.Bitcast(res_ty, res)->Result(); + } + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + void EmitBinaryWrappedAsFirstArg(spirv::ir::BuiltinCall* call, core::BinaryOp op) { + const auto& args = call->Args(); + auto* lhs = args[0]; + auto* rhs = args[1]; + + auto* op_ty = lhs->Type(); + auto* res_ty = call->Result()->Type(); + + b.InsertBefore(call, [&] { + if (rhs->Type() != op_ty) { + rhs = b.Bitcast(op_ty, rhs)->Result(); + } + + auto* c = b.Binary(op, op_ty, lhs, rhs)->Result(); + if (res_ty != op_ty) { + c = b.Bitcast(res_ty, c)->Result(); + } + call->Result()->ReplaceAllUsesWith(c); + }); + call->Destroy(); + } + + void BitwiseAnd(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedAsFirstArg(call, core::BinaryOp::kAnd); + } + void BitwiseOr(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedAsFirstArg(call, core::BinaryOp::kOr); + } + void BitwiseXor(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedAsFirstArg(call, core::BinaryOp::kXor); + } + + void Add(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedAsFirstArg(call, core::BinaryOp::kAdd); + } + void Sub(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedAsFirstArg(call, core::BinaryOp::kSubtract); + } + void Mul(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedAsFirstArg(call, core::BinaryOp::kMultiply); + } + + void EmitBinaryWrappedSignedSpirvMethods(spirv::ir::BuiltinCall* call, core::BinaryOp op) { + const auto& args = call->Args(); + auto* lhs = args[0]; + auto* rhs = args[1]; + + auto* res_ty = call->Result()->Type(); + auto* op_ty = ty.MatchWidth(ty.i32(), res_ty); + + b.InsertBefore(call, [&] { + if (lhs->Type() != op_ty) { + lhs = b.Bitcast(op_ty, lhs)->Result(); + } + if (rhs->Type() != op_ty) { + rhs = b.Bitcast(op_ty, rhs)->Result(); + } + + auto* c = b.Binary(op, op_ty, lhs, rhs)->Result(); + if (res_ty != op_ty) { + c = b.Bitcast(res_ty, c)->Result(); + } + call->Result()->ReplaceAllUsesWith(c); + }); + call->Destroy(); + } + + void SDiv(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedSignedSpirvMethods(call, core::BinaryOp::kDivide); + } + void SMod(spirv::ir::BuiltinCall* call) { + EmitBinaryWrappedSignedSpirvMethods(call, core::BinaryOp::kModulo); + } + + void EmitBinaryMatchedArgs(spirv::ir::BuiltinCall* call, core::BinaryOp op) { + const auto& args = call->Args(); + auto* lhs = args[0]; + auto* rhs = args[1]; + + b.InsertBefore(call, [&] { + if (rhs->Type() != lhs->Type()) { + rhs = b.Bitcast(lhs->Type(), rhs)->Result(); + } + + b.BinaryWithResult(call->DetachResult(), op, lhs, rhs)->Result(); + }); + call->Destroy(); + } + void Equal(spirv::ir::BuiltinCall* call) { + EmitBinaryMatchedArgs(call, core::BinaryOp::kEqual); + } + void NotEqual(spirv::ir::BuiltinCall* call) { + EmitBinaryMatchedArgs(call, core::BinaryOp::kNotEqual); + } + + void EmitBinaryWithSignedArgs(spirv::ir::BuiltinCall* call, core::BinaryOp op) { + const auto& args = call->Args(); + auto* lhs = args[0]; + auto* rhs = args[1]; + + auto* arg_ty = ty.MatchWidth(ty.i32(), call->Result()->Type()); + b.InsertBefore(call, [&] { + if (lhs->Type() != arg_ty) { + lhs = b.Bitcast(arg_ty, lhs)->Result(); + } + if (rhs->Type() != arg_ty) { + rhs = b.Bitcast(arg_ty, rhs)->Result(); + } + + b.BinaryWithResult(call->DetachResult(), op, lhs, rhs)->Result(); + }); + call->Destroy(); + } + void SGreaterThan(spirv::ir::BuiltinCall* call) { + EmitBinaryWithSignedArgs(call, core::BinaryOp::kGreaterThan); + } + void SGreaterThanEqual(spirv::ir::BuiltinCall* call) { + EmitBinaryWithSignedArgs(call, core::BinaryOp::kGreaterThanEqual); + } + void SLessThan(spirv::ir::BuiltinCall* call) { + EmitBinaryWithSignedArgs(call, core::BinaryOp::kLessThan); + } + void SLessThanEqual(spirv::ir::BuiltinCall* call) { + EmitBinaryWithSignedArgs(call, core::BinaryOp::kLessThanEqual); + } + + void EmitBinaryWithUnsignedArgs(spirv::ir::BuiltinCall* call, core::BinaryOp op) { + const auto& args = call->Args(); + auto* lhs = args[0]; + auto* rhs = args[1]; + + auto* arg_ty = ty.MatchWidth(ty.u32(), call->Result()->Type()); + b.InsertBefore(call, [&] { + if (lhs->Type() != arg_ty) { + lhs = b.Bitcast(arg_ty, lhs)->Result(); + } + if (rhs->Type() != arg_ty) { + rhs = b.Bitcast(arg_ty, rhs)->Result(); + } + + b.BinaryWithResult(call->DetachResult(), op, lhs, rhs)->Result(); + }); + call->Destroy(); + } + void UGreaterThan(spirv::ir::BuiltinCall* call) { + EmitBinaryWithUnsignedArgs(call, core::BinaryOp::kGreaterThan); + } + void UGreaterThanEqual(spirv::ir::BuiltinCall* call) { + EmitBinaryWithUnsignedArgs(call, core::BinaryOp::kGreaterThanEqual); + } + void ULessThan(spirv::ir::BuiltinCall* call) { + EmitBinaryWithUnsignedArgs(call, core::BinaryOp::kLessThan); + } + void ULessThanEqual(spirv::ir::BuiltinCall* call) { + EmitBinaryWithUnsignedArgs(call, core::BinaryOp::kLessThanEqual); + } + + // The SPIR-V Signed methods all interpret their arguments as signed (regardless of the type of + // the argument). In order to satisfy this, we must bitcast any unsigned argument to a signed + // type before calling the WGSL equivalent method. + // + // The result of the WGSL method will match the arguments, or in this case a signed value. If + // the SPIR-V instruction expected an unsigned result we must bitcast the WGSL result to the + // corrrect unsigned type. + void WrapSignedSpirvMethods(spirv::ir::BuiltinCall* call, core::BuiltinFn func) { + auto args = call->Args(); + + b.InsertBefore(call, [&] { + auto* result_ty = call->Result()->Type(); + Vector new_args; + + for (auto* arg : args) { + if (arg->Type()->IsUnsignedIntegerScalarOrVector()) { + arg = b.Bitcast(ty.MatchWidth(ty.i32(), result_ty), arg)->Result(); + } + new_args.Push(arg); + } + + auto* new_call = b.Call(result_ty, func, new_args); + + core::ir::Value* replacement = new_call->Result(); + if (result_ty->DeepestElement() == ty.u32()) { + new_call->Result()->SetType(ty.MatchWidth(ty.i32(), result_ty)); + replacement = b.Bitcast(result_ty, replacement)->Result(); + } + call->Result()->ReplaceAllUsesWith(replacement); + }); + call->Destroy(); + } + + void Sign(spirv::ir::BuiltinCall* call) { + WrapSignedSpirvMethods(call, core::BuiltinFn::kSign); + } + void Abs(spirv::ir::BuiltinCall* call) { WrapSignedSpirvMethods(call, core::BuiltinFn::kAbs); } + void FindSMsb(spirv::ir::BuiltinCall* call) { + WrapSignedSpirvMethods(call, core::BuiltinFn::kFirstLeadingBit); + } + void SMax(spirv::ir::BuiltinCall* call) { WrapSignedSpirvMethods(call, core::BuiltinFn::kMax); } + void SMin(spirv::ir::BuiltinCall* call) { WrapSignedSpirvMethods(call, core::BuiltinFn::kMin); } + void SClamp(spirv::ir::BuiltinCall* call) { + WrapSignedSpirvMethods(call, core::BuiltinFn::kClamp); + } + + void Ldexp(spirv::ir::BuiltinCall* call) { + WrapSignedSpirvMethods(call, core::BuiltinFn::kLdexp); + } + + // The SPIR-V Unsigned methods all interpret their arguments as unsigned (regardless of the type + // of the argument). In order to satisfy this, we must bitcast any signed argument to an + // unsigned type before calling the WGSL equivalent method. + // + // The result of the WGSL method will match the arguments, or in this case an unsigned value. If + // the SPIR-V instruction expected a signed result we must bitcast the WGSL result to the + // correct signed type. + void WrapUnsignedSpirvMethods(spirv::ir::BuiltinCall* call, core::BuiltinFn func) { + auto args = call->Args(); + + b.InsertBefore(call, [&] { + auto* result_ty = call->Result()->Type(); + Vector new_args; + + for (auto* arg : args) { + if (arg->Type()->IsSignedIntegerScalarOrVector()) { + arg = b.Bitcast(ty.MatchWidth(ty.u32(), result_ty), arg)->Result(); + } + new_args.Push(arg); + } + + auto* new_call = b.Call(result_ty, func, new_args); + + core::ir::Value* replacement = new_call->Result(); + if (result_ty->DeepestElement() == ty.i32()) { + new_call->Result()->SetType(ty.MatchWidth(ty.u32(), result_ty)); + replacement = b.Bitcast(result_ty, replacement)->Result(); + } + call->Result()->ReplaceAllUsesWith(replacement); + }); + call->Destroy(); + } + + void UMax(spirv::ir::BuiltinCall* call) { + WrapUnsignedSpirvMethods(call, core::BuiltinFn::kMax); + } + void UMin(spirv::ir::BuiltinCall* call) { + WrapUnsignedSpirvMethods(call, core::BuiltinFn::kMin); + } + void UClamp(spirv::ir::BuiltinCall* call) { + WrapUnsignedSpirvMethods(call, core::BuiltinFn::kClamp); + } + void FindUMsb(spirv::ir::BuiltinCall* call) { + WrapUnsignedSpirvMethods(call, core::BuiltinFn::kFirstLeadingBit); + } + + void Normalize(spirv::ir::BuiltinCall* call) { + auto* arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + core::BuiltinFn fn = core::BuiltinFn::kNormalize; + if (arg->Type()->IsScalar()) { + fn = core::BuiltinFn::kSign; + } + b.CallWithResult(call->DetachResult(), fn, Vector{arg}); + }); + call->Destroy(); + } + + void FindILsb(spirv::ir::BuiltinCall* call) { + auto* arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* arg_ty = arg->Type(); + auto* ret_ty = call->Result()->Type(); + + auto* v = + b.Call(arg_ty, core::BuiltinFn::kFirstTrailingBit, Vector{arg}) + ->Result(); + if (arg_ty != ret_ty) { + v = b.Bitcast(ret_ty, v)->Result(); + } + call->Result()->ReplaceAllUsesWith(v); + }); + call->Destroy(); + } + + void Refract(spirv::ir::BuiltinCall* call) { + auto args = call->Args(); + + auto* I = args[0]; + auto* N = args[1]; + auto* eta = args[2]; + + b.InsertBefore(call, [&] { + if (I->Type()->IsFloatScalar()) { + auto* src_ty = I->Type(); + auto* vec_ty = ty.vec(src_ty, 2); + auto* zero = b.Zero(src_ty); + I = b.Construct(vec_ty, I, zero)->Result(); + N = b.Construct(vec_ty, N, zero)->Result(); + + auto* c = b.Call(vec_ty, core::BuiltinFn::kRefract, + Vector{I, N, eta}); + auto* s = b.Swizzle(src_ty, c, {0}); + call->Result()->ReplaceAllUsesWith(s->Result()); + } else { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kRefract, + Vector{I, N, eta}); + } + }); + call->Destroy(); + } + + void Reflect(spirv::ir::BuiltinCall* call) { + auto args = call->Args(); + + auto* I = args[0]; + auto* N = args[1]; + + b.InsertBefore(call, [&] { + if (I->Type()->IsFloatScalar()) { + auto* v = b.Multiply(I, N)->Result(); + v = b.Multiply(v, N)->Result(); + v = b.Multiply(v, 2.0_f)->Result(); + v = b.Subtract(I, v)->Result(); + call->Result()->ReplaceAllUsesWith(v); + } else { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kReflect, + Vector{I, N}); + } + }); + call->Destroy(); + } + + void FaceForward(spirv::ir::BuiltinCall* call) { + auto args = call->Args(); + auto* N = args[0]; + auto* I = args[1]; + auto* Nref = args[2]; + + b.InsertBefore(call, [&] { + if (I->Type()->IsFloatScalar()) { + auto* neg = b.Negation(N); + auto* sel = b.Multiply(I, Nref)->Result(); + sel = b.LessThan(sel, b.Zero(sel->Type()))->Result(); + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kSelect, neg, N, sel); + } else { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kFaceForward, N, I, Nref); + } + }); + call->Destroy(); + } + + void Modf(spirv::ir::BuiltinCall* call) { + auto* x = call->Args()[0]; + auto* i = call->Args()[1]; + auto* result_ty = call->Result()->Type(); + auto* modf_result_ty = core::type::CreateModfResult(ty, ir.symbols, result_ty); + + b.InsertBefore(call, [&] { + auto* c = b.Call(modf_result_ty, core::BuiltinFn::kModf, x); + auto* whole = b.Access(result_ty, c, 1_u); + b.Store(i, whole); + + b.AccessWithResult(call->DetachResult(), c, 0_u); + }); + call->Destroy(); + } + + void Frexp(spirv::ir::BuiltinCall* call) { + auto* x = call->Args()[0]; + auto* i = call->Args()[1]; + auto* result_ty = call->Result()->Type(); + auto* frexp_result_ty = core::type::CreateFrexpResult(ty, ir.symbols, result_ty); + + b.InsertBefore(call, [&] { + auto* c = b.Call(frexp_result_ty, core::BuiltinFn::kFrexp, x); + auto* exp = b.Access(ty.MatchWidth(ty.i32(), result_ty), c, 1_u)->Result(); + + if (i->Type()->UnwrapPtr()->DeepestElement()->IsUnsignedIntegerScalar()) { + exp = b.Bitcast(i->Type()->UnwrapPtr(), exp)->Result(); + } + b.Store(i, exp); + + b.AccessWithResult(call->DetachResult(), c, 0_u); + }); + call->Destroy(); + } + + void BitFieldInsert(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + auto* e = args[0]; + auto* newbits = args[1]; + auto* offset = args[2]; + auto* count = args[3]; + + b.InsertBefore(call, [&] { + if (offset->Type()->IsSignedIntegerScalar()) { + offset = b.Bitcast(ty.u32(), offset)->Result(); + } + if (count->Type()->IsSignedIntegerScalar()) { + count = b.Bitcast(ty.u32(), count)->Result(); + } + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kInsertBits, e, newbits, offset, + count); + }); + call->Destroy(); + } + + void BitFieldUExtract(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + auto* e = args[0]; + auto* offset = args[1]; + auto* count = args[2]; + + b.InsertBefore(call, [&] { + bool cast_result = false; + auto* call_ty = ty.MatchWidth(ty.u32(), e->Type()); + + if (e->Type()->DeepestElement()->IsSignedIntegerScalar()) { + e = b.Bitcast(call_ty, e)->Result(); + cast_result = true; + } + + if (offset->Type()->IsSignedIntegerScalar()) { + offset = b.Bitcast(ty.u32(), offset)->Result(); + } + if (count->Type()->IsSignedIntegerScalar()) { + count = b.Bitcast(ty.u32(), count)->Result(); + } + + auto* res = b.Call(call_ty, core::BuiltinFn::kExtractBits, e, offset, count)->Result(); + if (cast_result) { + res = b.Bitcast(call->Result()->Type(), res)->Result(); + } + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + void BitFieldSExtract(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + auto* e = args[0]; + auto* offset = args[1]; + auto* count = args[2]; + + b.InsertBefore(call, [&] { + bool cast_result = false; + auto* call_ty = ty.MatchWidth(ty.i32(), e->Type()); + + if (e->Type()->DeepestElement()->IsUnsignedIntegerScalar()) { + e = b.Bitcast(call_ty, e)->Result(); + cast_result = true; + } + + if (offset->Type()->IsSignedIntegerScalar()) { + offset = b.Bitcast(ty.u32(), offset)->Result(); + } + if (count->Type()->IsSignedIntegerScalar()) { + count = b.Bitcast(ty.u32(), count)->Result(); + } + + auto* res = b.Call(call_ty, core::BuiltinFn::kExtractBits, e, offset, count)->Result(); + if (cast_result) { + res = b.Bitcast(call->Result()->Type(), res)->Result(); + } + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + void BitCount(spirv::ir::BuiltinCall* call) { + auto arg = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* res_ty = call->Result()->Type(); + auto* arg_ty = arg->Type(); + + auto* bc = b.Call(arg_ty, core::BuiltinFn::kCountOneBits, arg)->Result(); + if (res_ty != arg_ty) { + bc = b.Bitcast(res_ty, bc)->Result(); + } + call->Result()->ReplaceAllUsesWith(bc); + }); + call->Destroy(); + } + + void ShiftLeftLogical(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + auto* base = args[0]; + auto* shift = args[1]; + + if (!shift->Type()->IsUnsignedIntegerScalarOrVector()) { + shift = b.Bitcast(ty.MatchWidth(ty.u32(), shift->Type()), shift)->Result(); + } + + auto* bin = b.Binary(core::BinaryOp::kShiftLeft, base->Type(), base, shift)->Result(); + if (base->Type() != call->Result()->Type()) { + bin = b.Bitcast(call->Result()->Type(), bin)->Result(); + } + call->Result()->ReplaceAllUsesWith(bin); + }); + call->Destroy(); + } + + void ShiftRightLogical(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + auto* base = args[0]; + auto* shift = args[1]; + + auto* u_ty = ty.MatchWidth(ty.u32(), base->Type()); + if (!base->Type()->IsUnsignedIntegerScalarOrVector()) { + base = b.Bitcast(u_ty, base)->Result(); + } + if (!shift->Type()->IsUnsignedIntegerScalarOrVector()) { + shift = b.Bitcast(u_ty, shift)->Result(); + } + + auto* bin = b.Binary(core::BinaryOp::kShiftRight, u_ty, base, shift)->Result(); + if (u_ty != call->Result()->Type()) { + bin = b.Bitcast(call->Result()->Type(), bin)->Result(); + } + call->Result()->ReplaceAllUsesWith(bin); + }); + call->Destroy(); + } + + void ShiftRightArithmetic(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + auto* base = args[0]; + auto* shift = args[1]; + + auto* s_ty = ty.MatchWidth(ty.i32(), base->Type()); + if (!base->Type()->IsSignedIntegerScalarOrVector()) { + base = b.Bitcast(s_ty, base)->Result(); + } + if (!shift->Type()->IsUnsignedIntegerScalarOrVector()) { + shift = b.Bitcast(ty.MatchWidth(ty.u32(), shift->Type()), shift)->Result(); + } + + auto* bin = b.Binary(core::BinaryOp::kShiftRight, s_ty, base, shift)->Result(); + if (s_ty != call->Result()->Type()) { + bin = b.Bitcast(call->Result()->Type(), bin)->Result(); + } + call->Result()->ReplaceAllUsesWith(bin); + }); + call->Destroy(); + } + + void Inverse(spirv::ir::BuiltinCall* call) { + auto* arg = call->Args()[0]; + auto* mat_ty = arg->Type()->As(); + TINT_ASSERT(mat_ty); + TINT_ASSERT(mat_ty->Columns() == mat_ty->Rows()); + + auto* elem_ty = mat_ty->Type(); + + b.InsertBefore(call, [&] { + auto* det = + b.Call(elem_ty, core::BuiltinFn::kDeterminant, Vector{arg}); + core::ir::Value* one = nullptr; + if (elem_ty->Is()) { + one = b.Constant(1.0_f); + } else if (elem_ty->Is()) { + one = b.Constant(1.0_h); + } else { + TINT_UNREACHABLE(); + } + auto* inv_det = b.Divide(one, det); + + // Returns (m * n) - (o * p) + auto sub_mul2 = [&](auto* m, auto* n, auto* o, auto* p) { + auto* x = b.Multiply(m, n); + auto* y = b.Multiply(o, p); + return b.Subtract(x, y); + }; + + // Returns (m * n) - (o * p) + (q * r) + auto sub_add_mul3 = [&](auto* m, auto* n, auto* o, auto* p, auto* q, auto* r) { + auto* w = b.Multiply(m, n); + auto* x = b.Multiply(o, p); + auto* y = b.Multiply(q, r); + + auto* z = b.Subtract(w, x); + return b.Add(z, y); + }; + + // Returns (m * n) + (o * p) - (q * r) + auto add_sub_mul3 = [&](auto* m, auto* n, auto* o, auto* p, auto* q, auto* r) { + auto* w = b.Multiply(m, n); + auto* x = b.Multiply(o, p); + auto* y = b.Multiply(q, r); + + auto* z = b.Add(w, x); + return b.Subtract(z, y); + }; + + switch (mat_ty->Columns()) { + case 2: { + auto* neg_inv_det = b.Negation(inv_det); + + auto* ma = b.Access(elem_ty, arg, 0_u, 0_u); + auto* mb = b.Access(elem_ty, arg, 0_u, 1_u); + auto* mc = b.Access(elem_ty, arg, 1_u, 0_u); + auto* md = b.Access(elem_ty, arg, 1_u, 1_u); + + auto* r_00 = b.Multiply(inv_det, md); + auto* r_01 = b.Multiply(neg_inv_det, mb); + auto* r_10 = b.Multiply(neg_inv_det, mc); + auto* r_11 = b.Multiply(inv_det, ma); + + auto* r1 = b.Construct(ty.vec2(elem_ty), r_00, r_01); + auto* r2 = b.Construct(ty.vec2(elem_ty), r_10, r_11); + b.ConstructWithResult(call->DetachResult(), r1, r2); + break; + } + case 3: { + auto* ma = b.Access(elem_ty, arg, 0_u, 0_u); + auto* mb = b.Access(elem_ty, arg, 0_u, 1_u); + auto* mc = b.Access(elem_ty, arg, 0_u, 2_u); + auto* md = b.Access(elem_ty, arg, 1_u, 0_u); + auto* me = b.Access(elem_ty, arg, 1_u, 1_u); + auto* mf = b.Access(elem_ty, arg, 1_u, 2_u); + auto* mg = b.Access(elem_ty, arg, 2_u, 0_u); + auto* mh = b.Access(elem_ty, arg, 2_u, 1_u); + auto* mi = b.Access(elem_ty, arg, 2_u, 2_u); + + // e * i - f * h + auto* r_00 = sub_mul2(me, mi, mf, mh); + // c * h - b * i + auto* r_01 = sub_mul2(mc, mh, mb, mi); + // b * f - c * e + auto* r_02 = sub_mul2(mb, mf, mc, me); + + // f * g - d * i + auto* r_10 = sub_mul2(mf, mg, md, mi); + // a * i - c * g + auto* r_11 = sub_mul2(ma, mi, mc, mg); + // c * d - a * f + auto* r_12 = sub_mul2(mc, md, ma, mf); + + // d * h - e * g + auto* r_20 = sub_mul2(md, mh, me, mg); + // b * g - a * h + auto* r_21 = sub_mul2(mb, mg, ma, mh); + // a * e - b * d + auto* r_22 = sub_mul2(ma, me, mb, md); + + auto* r1 = b.Construct(ty.vec3(elem_ty), r_00, r_01, r_02); + auto* r2 = b.Construct(ty.vec3(elem_ty), r_10, r_11, r_12); + auto* r3 = b.Construct(ty.vec3(elem_ty), r_20, r_21, r_22); + + auto* m = b.Construct(mat_ty, r1, r2, r3); + auto* inv = b.Multiply(inv_det, m); + call->Result()->ReplaceAllUsesWith(inv->Result()); + break; + } + case 4: { + auto* ma = b.Access(elem_ty, arg, 0_u, 0_u); + auto* mb = b.Access(elem_ty, arg, 0_u, 1_u); + auto* mc = b.Access(elem_ty, arg, 0_u, 2_u); + auto* md = b.Access(elem_ty, arg, 0_u, 3_u); + auto* me = b.Access(elem_ty, arg, 1_u, 0_u); + auto* mf = b.Access(elem_ty, arg, 1_u, 1_u); + auto* mg = b.Access(elem_ty, arg, 1_u, 2_u); + auto* mh = b.Access(elem_ty, arg, 1_u, 3_u); + auto* mi = b.Access(elem_ty, arg, 2_u, 0_u); + auto* mj = b.Access(elem_ty, arg, 2_u, 1_u); + auto* mk = b.Access(elem_ty, arg, 2_u, 2_u); + auto* ml = b.Access(elem_ty, arg, 2_u, 3_u); + auto* mm = b.Access(elem_ty, arg, 3_u, 0_u); + auto* mn = b.Access(elem_ty, arg, 3_u, 1_u); + auto* mo = b.Access(elem_ty, arg, 3_u, 2_u); + auto* mp = b.Access(elem_ty, arg, 3_u, 3_u); + + // kplo = k * p - l * o + auto* kplo = sub_mul2(mk, mp, ml, mo); + // jpln = j * p - l * n + auto* jpln = sub_mul2(mj, mp, ml, mn); + // jokn = j * o - k * n; + auto* jokn = sub_mul2(mj, mo, mk, mn); + // gpho = g * p - h * o + auto* gpho = sub_mul2(mg, mp, mh, mo); + // fphn = f * p - h * n + auto* fphn = sub_mul2(mf, mp, mh, mn); + // fogn = f * o - g * n; + auto* fogn = sub_mul2(mf, mo, mg, mn); + // glhk = g * l - h * k + auto* glhk = sub_mul2(mg, ml, mh, mk); + // flhj = f * l - h * j + auto* flhj = sub_mul2(mf, ml, mh, mj); + // fkgj = f * k - g * j; + auto* fkgj = sub_mul2(mf, mk, mg, mj); + // iplm = i * p - l * m + auto* iplm = sub_mul2(mi, mp, ml, mm); + // iokm = i * o - k * m + auto* iokm = sub_mul2(mi, mo, mk, mm); + // ephm = e * p - h * m; + auto* ephm = sub_mul2(me, mp, mh, mm); + // eogm = e * o - g * m + auto* eogm = sub_mul2(me, mo, mg, mm); + // elhi = e * l - h * i + auto* elhi = sub_mul2(me, ml, mh, mi); + // ekgi = e * k - g * i; + auto* ekgi = sub_mul2(me, mk, mg, mi); + // injm = i * n - j * m + auto* injm = sub_mul2(mi, mn, mj, mm); + // enfm = e * n - f * m + auto* enfm = sub_mul2(me, mn, mf, mm); + // ejfi = e * j - f * i; + auto* ejfi = sub_mul2(me, mj, mf, mi); + + auto* neg_b = b.Negation(mb); + // f * kplo - g * jpln + h * jokn + auto* r_00 = sub_add_mul3(mf, kplo, mg, jpln, mh, jokn); + // -b * kplo + c * jpln - d * jokn + auto* r_01 = add_sub_mul3(neg_b, kplo, mc, jpln, md, jokn); + // b * gpho - c * fphn + d * fogn + auto* r_02 = sub_add_mul3(mb, gpho, mc, fphn, md, fogn); + // -b * glhk + c * flhj - d * fkgj + auto* r_03 = add_sub_mul3(neg_b, glhk, mc, flhj, md, fkgj); + + auto* neg_e = b.Negation(me); + auto* neg_a = b.Negation(ma); + // -e * kplo + g * iplm - h * iokm + auto* r_10 = add_sub_mul3(neg_e, kplo, mg, iplm, mh, iokm); + // a * kplo - c * iplm + d * iokm + auto* r_11 = sub_add_mul3(ma, kplo, mc, iplm, md, iokm); + // -a * gpho + c * ephm - d * eogm + auto* r_12 = add_sub_mul3(neg_a, gpho, mc, ephm, md, eogm); + // a * glhk - c * elhi + d * ekgi + auto* r_13 = sub_add_mul3(ma, glhk, mc, elhi, md, ekgi); + + // e * jpln - f * iplm + h * injm + auto* r_20 = sub_add_mul3(me, jpln, mf, iplm, mh, injm); + // -a * jpln + b * iplm - d * injm + auto* r_21 = add_sub_mul3(neg_a, jpln, mb, iplm, md, injm); + // a * fphn - b * ephm + d * enfm + auto* r_22 = sub_add_mul3(ma, fphn, mb, ephm, md, enfm); + // -a * flhj + b * elhi - d * ejfi + auto* r_23 = add_sub_mul3(neg_a, flhj, mb, elhi, md, ejfi); + + // -e * jokn + f * iokm - g * injm + auto* r_30 = add_sub_mul3(neg_e, jokn, mf, iokm, mg, injm); + // a * jokn - b * iokm + c * injm + auto* r_31 = sub_add_mul3(ma, jokn, mb, iokm, mc, injm); + // -a * fogn + b * eogm - c * enfm + auto* r_32 = add_sub_mul3(neg_a, fogn, mb, eogm, mc, enfm); + // a * fkgj - b * ekgi + c * ejfi + auto* r_33 = sub_add_mul3(ma, fkgj, mb, ekgi, mc, ejfi); + + auto* r1 = b.Construct(ty.vec4(elem_ty), r_00, r_01, r_02, r_03); + auto* r2 = b.Construct(ty.vec4(elem_ty), r_10, r_11, r_12, r_13); + auto* r3 = b.Construct(ty.vec4(elem_ty), r_20, r_21, r_22, r_23); + auto* r4 = b.Construct(ty.vec4(elem_ty), r_30, r_31, r_32, r_33); + + auto* m = b.Construct(mat_ty, r1, r2, r3, r4); + auto* inv = b.Multiply(inv_det, m); + call->Result()->ReplaceAllUsesWith(inv->Result()); + break; + } + default: { + TINT_UNREACHABLE(); + } + } + }); + call->Destroy(); + } +}; + +} // namespace + +Result Builtins(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.Builtins", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowStructMatrixDecorations, + core::ir::Capability::kAllowPointerToHandle, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.h new file mode 100644 index 000000000..eed84a131 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/builtins.h @@ -0,0 +1,48 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_BUILTINS_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_BUILTINS_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// Builtins is a transform that converts SPIR-V builtin methods into the form expected by Tint's +/// core IR. +/// @param module the module to transform +/// @returns success or failure +Result Builtins(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_BUILTINS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.cc new file mode 100644 index 000000000..63acdfcb8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.cc @@ -0,0 +1,267 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/decompose_strided_array.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/type/explicit_layout_array.h" + +namespace tint::spirv::reader::lower { +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol manager. + SymbolTable& sym{ir.symbols}; + + /// A map from a type to its replacement type (which may be the same as the original). + Hashmap type_map{}; + + /// A map from a constant to the rewritten constant. + Hashmap constant_map{}; + + /// All of the padded structure types that were created by this transform. + Hashset padded_structures{}; + + /// Process the module. + void Process() { + Vector access_worklist; + Vector construct_worklist; + for (auto* inst : ir.Instructions()) { + // Replace all constant operands where the type will be changed, either due to being a + // strided array, or a composite containing a strided array. + for (uint32_t i = 0; i < inst->Operands().Length(); ++i) { + auto* constant = As(inst->Operands()[i]); + if (!constant) { + continue; + } + + auto* new_constant = RewriteConstant(constant->Value()); + if (new_constant != constant->Value()) { + inst->SetOperand(i, b.Constant(new_constant)); + } + } + + // Track all construct instructions that need to be updated later. + if (auto* construct = inst->As()) { + if (construct->Result(0)->Type()->Is()) { + construct_worklist.Push(construct); + } + } + + // Update any instruction result that contains an array with a non-default stride. + for (auto* result : inst->Results()) { + result->SetType(RewriteType(result->Type())); + } + + // Track all access instructions that may need to be updated later. + if (auto* access = inst->As()) { + access_worklist.Push(access); + } + } + + // Update the types of any function parameters and function return types that contain arrays + // with non-default strides. + for (auto func : ir.functions) { + for (auto* param : func->Params()) { + param->SetType(RewriteType(param->Type())); + } + func->SetReturnType(RewriteType(func->ReturnType())); + } + + // Wrap operands for construct instructions in padded structures. + for (auto* construct : construct_worklist) { + WrapConstructOperands(construct); + } + + // Inject additional indices into access instructions where needed. + // We do this last as it relies on us knowing whether the access chain indexes into padded + // structures that we have added in the previous steps. + for (auto* access : access_worklist) { + UpdateAccessIndices(access); + } + } + + /// Rewrite a type to avoid using any arrays that have non-default strides. + const core::type::Type* RewriteType(const core::type::Type* type) { + return type_map.GetOrAdd(type, [&] { + return tint::Switch( + type, // + [&](const spirv::type::ExplicitLayoutArray* arr) { + auto* new_element_type = RewriteType(arr->ElemType()); + + if (!arr->IsStrideImplicit()) { + // The stride does not match the implicit element stride, so we need to wrap + // the element type in a structure that is padded to the target stride. + auto* element_struct = + ty.Struct(sym.New("tint_padded_array_element"), + Vector{ + ty.Get( + sym.New("tint_element"), new_element_type, + /* index */ 0u, + /* offset */ 0u, + /* align */ new_element_type->Align(), + /* size */ arr->Stride(), core::IOAttributes{}), + }); + new_element_type = element_struct; + padded_structures.Add(element_struct); + } + + return ty.Get(new_element_type, arr->Count(), arr->Size()); + }, + [&](const core::type::Array* arr) { + auto* new_element_type = RewriteType(arr->ElemType()); + return ty.Get(new_element_type, arr->Count(), arr->Size()); + }, + [&](const core::type::Struct* str) -> const core::type::Struct* { + // Rewrite members of the struct that contain arrays with non-default strides. + bool made_changes = false; + Vector new_members; + new_members.Reserve(str->Members().Length()); + for (auto* member : str->Members()) { + auto* new_member_type = RewriteType(member->Type()); + if (new_member_type == member->Type()) { + new_members.Push(member); + continue; + } + + new_members.Push(ty.Get( + member->Name(), new_member_type, member->Index(), member->Offset(), + member->Align(), member->Size(), member->Attributes())); + made_changes = true; + } + if (!made_changes) { + return str; + } + + return ty.Struct(sym.New(str->Name().Name()), std::move(new_members)); + }, + [&](const core::type::Pointer* ptr) { + return ty.ptr(ptr->AddressSpace(), RewriteType(ptr->StoreType()), + ptr->Access()); + }, + [&](Default) { return type; }); + }); + } + + /// Rewrite a constant to avoid using any arrays that have non-default strides. + const core::constant::Value* RewriteConstant(const core::constant::Value* constant) { + auto* new_type = RewriteType(constant->Type()); + if (new_type == constant->Type()) { + return constant; + } + + // Check if the constant is an array of padded structures. + // A padded structure will only appear as the element type of an array, so we only need to + // check the first element type. + const core::type::Type* padded_struct_type = nullptr; + if (padded_structures.Contains(new_type->Element(0))) { + padded_struct_type = new_type->Element(0); + } + + Vector elements; + for (uint32_t i = 0; i < constant->NumElements(); i++) { + auto* new_element = RewriteConstant(constant->Index(i)); + + // If we are rewriting an array of padded structures, then we need to wrap the original + // element in a constant structure. + if (padded_struct_type) { + new_element = ir.constant_values.Composite(padded_struct_type, Vector{new_element}); + } + + elements.Push(new_element); + } + return ir.constant_values.Composite(new_type, std::move(elements)); + } + + /// Wrap all operands for a construct instruction that produces an array with padded elements. + void WrapConstructOperands(core::ir::Construct* construct) { + auto* padded_struct_type = construct->Result(0)->Type()->Element(0); + TINT_ASSERT(padded_struct_type && padded_structures.Contains(padded_struct_type)); + b.InsertBefore(construct, [&] { + Vector new_operands; + for (auto* operand : construct->Operands()) { + new_operands.Push(b.Construct(padded_struct_type, operand)->Result(0)); + } + construct->SetOperands(new_operands); + }); + } + + /// Inject additional `0u` indices into access instructions that index into any padded structure + /// types that we have created. + void UpdateAccessIndices(core::ir::Access* access) { + Vector new_operands{access->Object()}; + + auto old_indices = access->Indices(); + auto* current_type = access->Object()->Type()->UnwrapPtr(); + for (auto* idx : old_indices) { + new_operands.Push(idx); + + auto* const_idx = idx->As(); + current_type = const_idx + ? current_type->Element(const_idx->Value()->ValueAs()) + : current_type->Elements().type; + + if (padded_structures.Contains(current_type)) { + new_operands.Push(b.Zero()); + current_type = current_type->Element(0); + } + } + access->SetOperands(std::move(new_operands)); + } +}; + +} // namespace + +Result DecomposeStridedArray(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.DecomposeStridedArray", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPointerToHandle, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.h new file mode 100644 index 000000000..f4a86a4c4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_array.h @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_DECOMPOSE_STRIDED_ARRAY_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_DECOMPOSE_STRIDED_ARRAY_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// DecomposeStridedArray is a transform that replaces arrays with a stride that does not match the +/// natural element stride with an array of structures that are padded to achieve the target stride. +/// @param module the module to transform +/// @returns success or failure +Result DecomposeStridedArray(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_DECOMPOSE_STRIDED_ARRAY_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.cc new file mode 100644 index 000000000..fb3ddcb94 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.cc @@ -0,0 +1,380 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/decompose_strided_matrix.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/spirv/type/explicit_layout_array.h" + +namespace tint::spirv::reader::lower { +namespace { + +using namespace tint::core::fluent_types; // NOLINT + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol manager. + SymbolTable& sym{ir.symbols}; + + /// A map from a type to its replacement type (which may be the same as the original). + struct TypeAndStride { + const core::type::Type* type; + uint32_t stride; + + bool operator==(const TypeAndStride& other) const { + return type == other.type && stride == other.stride; + } + + tint::HashCode HashCode() const { return Hash(type, stride); } + }; + Hashmap type_map{}; + + /// A map from rewritten structs to original structs. + Hashmap struct_to_original{}; + + /// Process the module. + void Process() { + Vector access_worklist; + Vector construct_worklist; + for (auto* inst : ir.Instructions()) { + // Replace all constant operands where the type will be changed due to it containing a + // structure that uses a matrix stride attribute. + for (uint32_t i = 0; i < inst->Operands().Length(); ++i) { + if (auto* constant = As(inst->Operands()[i])) { + auto* new_constant = RewriteConstant(constant->Value()); + if (new_constant != constant->Value()) { + inst->SetOperand(i, b.Constant(new_constant)); + } + } + } + + // Update any instruction result that contains a matrix stride attribute. + for (auto* result : inst->Results()) { + result->SetType(RewriteType(result->Type())); + } + + // Track instructions that may need to be updated later. + if (auto* access = inst->As()) { + access_worklist.Push(access); + } + if (auto* construct = inst->As()) { + construct_worklist.Push(construct); + } + } + + // Update the types of any function parameters and function return types that contain + // matrices with non-default strides. + for (auto func : ir.functions) { + for (auto* param : func->Params()) { + param->SetType(RewriteType(param->Type())); + } + func->SetReturnType(RewriteType(func->ReturnType())); + } + + // Update any access instructions that produce strided matrices. + for (auto* access : access_worklist) { + UpdateAccessInstruction(access, /* source_is_strided */ false); + } + + // Convert strided matrix operands for construct instructions. + for (auto* construct : construct_worklist) { + ConvertConstructOperands(construct); + } + } + + /// Rewrite a type to replace structure members that have matrix strides. + const core::type::Type* RewriteType(const core::type::Type* type, uint32_t stride = 0) { + return type_map.GetOrAdd(TypeAndStride{type, stride}, [&] { + return tint::Switch( + type, // + [&](const core::type::Matrix* mat) -> const core::type::Type* { + if (stride == 0 || stride == mat->ColumnStride()) { + return mat; + } + // Replace the matrix with a strided array of column vectors. + TINT_ASSERT(stride % mat->ColumnStride() == 0); + return ty.Get( + mat->ColumnType(), ty.Get(mat->Columns()), + stride * mat->Columns(), stride); + }, + [&](const core::type::Array* arr) { return RewriteArray(arr, stride); }, + [&](const core::type::Struct* str) { return RewriteStruct(str); }, + [&](const core::type::Pointer* ptr) { + return ty.ptr(ptr->AddressSpace(), RewriteType(ptr->StoreType()), + ptr->Access()); + }, + [&](Default) { return type; }); + }); + } + + /// Rewrite an array type if necessary. + const core::type::Array* RewriteArray(const core::type::Array* arr, uint32_t matrix_stride) { + auto* new_element_type = RewriteType(arr->ElemType(), matrix_stride); + if (new_element_type == arr->ElemType()) { + return arr; + } + + // The element type is the only thing that will change. That does not affect the stride of + // the array itself, which may either be the natural stride or an larger stride in the case + // of an explicitly laid out array. + if (auto* ex = arr->As()) { + return ty.Get(new_element_type, arr->Count(), + arr->Size(), ex->Stride()); + } + return ty.Get(new_element_type, arr->Count(), arr->Size()); + } + + /// Rewrite a structure type to replace structure members that have matrix stride attributes. + const core::type::Struct* RewriteStruct(const core::type::Struct* old_struct) { + bool made_changes = false; + + Vector new_members; + new_members.Reserve(old_struct->Members().Length()); + for (auto* member : old_struct->Members()) { + auto* new_member_type = RewriteType(member->Type(), member->MatrixStride()); + if (member->HasMatrixStride() || new_member_type != member->Type()) { + // Recreate the struct member without the stride attribute, and using the new type. + new_members.Push(ty.Get( + member->Name(), new_member_type, member->Index(), member->Offset(), + member->Align(), member->Size(), member->Attributes())); + made_changes = true; + } else { + new_members.Push(member); + } + } + if (!made_changes) { + return old_struct; + } + + // Create the new struct and record the mapping to the old struct. + auto* new_struct = ty.Struct(sym.New(old_struct->Name().Name()), std::move(new_members)); + struct_to_original.Add(new_struct, old_struct); + return new_struct; + } + + /// Rewrite a constant to replace strided matrix constants with the equivalent strided array + /// of column vector constants. + const core::constant::Value* RewriteConstant(const core::constant::Value* constant, + uint32_t stride = 0) { + auto* new_type = RewriteType(constant->Type(), stride); + if (new_type == constant->Type()) { + return constant; + } + + Vector elements; + for (uint32_t i = 0; i < constant->NumElements(); i++) { + auto* value = constant->Index(i); + + // If this is a struct member, we need to check if the type has changed. + if (auto* new_struct_type = new_type->As()) { + auto* new_member_type = new_struct_type->Members()[i]->Type(); + if (new_member_type != value->Type()) { + // Create a new constant using the strided array type. + // If the type changed, it must have had a MatrixStride decoration and will have + // been rewritten as an array type (or it already was an array). + auto* array = new_member_type->As(); + TINT_ASSERT(array); + + auto* old_struct_type = constant->Type()->As(); + auto member_stride = old_struct_type->Members()[i]->MatrixStride(); + + Vector new_elements; + for (uint32_t j = 0; j < array->ConstantCount().value(); j++) { + new_elements.Push(RewriteConstant(value->Index(j), member_stride)); + } + value = ir.constant_values.Composite(array, std::move(new_elements)); + } + } + + elements.Push(RewriteConstant(value, stride)); + } + return ir.constant_values.Composite(new_type, std::move(elements)); + } + + /// Convert strided matrix operands to strided arrays for a construct instruction. + void ConvertConstructOperands(core::ir::Construct* construct) { + auto* struct_type = construct->Result()->Type()->As(); + if (!struct_type) { + return; + } + + b.InsertBefore(construct, [&] { + Vector new_operands; + for (uint32_t i = 0; i < construct->Operands().Length(); i++) { + auto* operand = construct->Operands()[i]; + auto* member_type = struct_type->Members()[i]->Type(); + if (member_type != operand->Type()) { + new_operands.Push(Convert(member_type, operand)); + } else { + new_operands.Push(operand); + } + } + construct->SetOperands(new_operands); + }); + } + + /// Update the result type of an access instruction if needed, and the uses of that result. + void UpdateAccessInstruction(core::ir::Access* access, bool source_is_strided) { + // Determine the result type based on the potentially modified object type. + bool indexed_through_strided_member = source_is_strided; + auto* current_type = access->Object()->Type()->UnwrapPtr(); + for (auto* idx : access->Indices()) { + if (auto* struct_type = current_type->As()) { + auto const_idx = idx->As()->Value()->ValueAs(); + current_type = current_type->Element(const_idx); + + // Check if we are indexing into a member that has a non-natural matrix stride. + auto* original_struct = struct_to_original.GetOr(struct_type, nullptr); + if (!original_struct) { + // The structure type has not changed so cannot have any matrix strides. + continue; + } + auto* member = original_struct->Members()[const_idx]; + if (member->HasMatrixStride() && current_type != member->Type()) { + indexed_through_strided_member = true; + } + } else { + current_type = current_type->Elements().type; + } + } + if (!indexed_through_strided_member || current_type->Is()) { + return; + } + + if (auto* ptr = access->Result()->Type()->As()) { + ReplaceMatrixPointerWithArrayPointer(ptr, current_type, access); + } else { + // We were extracting a strided matrix from a structure, so we need to convert the + // strided array back to that matrix type. + b.InsertAfter(access, [&] { + auto* extracted_array = b.InstructionResult(current_type); + access->Result()->ReplaceAllUsesWith( + Convert(access->Result()->Type(), extracted_array)); + access->SetResult(extracted_array); + }); + } + } + + /// Change the type of a pointer instruction result that contains a strided matrix, and then + /// update any instructions that use that result. + void ReplaceMatrixPointerWithArrayPointer(const core::type::Pointer* old_ptr, + const core::type::Type* new_store_type, + core::ir::Instruction* instruction) { + auto* old_store_type = old_ptr->StoreType(); + auto* new_ptr = ty.ptr(old_ptr->AddressSpace(), new_store_type, old_ptr->Access()); + + Vector worklist{instruction}; + while (!worklist.IsEmpty()) { + auto* inst = worklist.Pop(); + inst->Result()->SetType(new_ptr); + inst->Result()->ForEachUseUnsorted([&](const core::ir::Usage& use) { + tint::Switch( + use.instruction, // + [&](core::ir::Access* access) { + UpdateAccessInstruction(access, /* source_is_strided */ true); + }, + [&](core::ir::Let* let) { worklist.Push(let); }, + [&](core::ir::Load* load) { + // Convert the value to the original type. + b.InsertAfter(load, [&] { + auto* new_load_result = b.InstructionResult(new_store_type); + auto* converted = Convert(old_store_type, new_load_result); + load->Result()->ReplaceAllUsesWith(converted); + load->SetResult(new_load_result); + }); + }, + [&](core::ir::Store* store) { + // Convert the value to the new type. + b.InsertBefore(store, [&] { // + store->SetFrom(Convert(new_store_type, store->From())); + }); + }, + TINT_ICE_ON_NO_MATCH); + }); + } + } + + /// Convert a value between an [array of] strided matrix and an [array of] strided array. + core::ir::Value* Convert(const core::type::Type* dst, core::ir::Value* src) { + auto dst_elements = dst->Elements(); + auto src_elements = src->Type()->Elements(); + TINT_ASSERT(dst_elements.count == src_elements.count); + Vector elements; + elements.Reserve(dst_elements.count); + for (uint32_t i = 0; i < dst_elements.count; i++) { + // Extract the element from the source value. + core::ir::Value* el = nullptr; + if (auto* constant = src->As()) { + el = b.Constant(constant->Value()->Index(i)); + } else { + el = b.Access(src_elements.type, src, u32(i))->Result(); + } + + // Recurse to convert strided matrices nested in arrays if needed. + if (src_elements.type != dst_elements.type) { + el = Convert(dst_elements.type, el); + } + + elements.Push(el); + } + return b.Construct(dst, std::move(elements))->Result(); + } +}; + +} // namespace + +Result DecomposeStridedMatrix(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.DecomposeStridedMatrix", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowStructMatrixDecorations, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPointerToHandle, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.h new file mode 100644 index 000000000..ae4a724b2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/decompose_strided_matrix.h @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_DECOMPOSE_STRIDED_MATRIX_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_DECOMPOSE_STRIDED_MATRIX_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// DecomposeStridedMatrix is a transform that replaces structure members that have matrix stride +/// attributes with arrays of vectors that have non-default strides. +/// @param module the module to transform +/// @returns success or failure +Result DecomposeStridedMatrix(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_DECOMPOSE_STRIDED_MATRIX_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.cc new file mode 100644 index 000000000..31cee5b81 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.cc @@ -0,0 +1,79 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/lower.h" + +#include "src/tint/lang/core/ir/transform/dead_code_elimination.h" +#include "src/tint/lang/core/ir/transform/remove_terminator_args.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/reader/lower/atomics.h" +#include "src/tint/lang/spirv/reader/lower/builtins.h" +#include "src/tint/lang/spirv/reader/lower/decompose_strided_array.h" +#include "src/tint/lang/spirv/reader/lower/decompose_strided_matrix.h" +#include "src/tint/lang/spirv/reader/lower/shader_io.h" +#include "src/tint/lang/spirv/reader/lower/texture.h" +#include "src/tint/lang/spirv/reader/lower/transpose_row_major.h" +#include "src/tint/lang/spirv/reader/lower/vector_element_pointer.h" + +namespace tint::spirv::reader { + +Result Lower(core::ir::Module& mod) { + TINT_CHECK_RESULT(core::ir::transform::DeadCodeElimination(mod)); + TINT_CHECK_RESULT(lower::VectorElementPointer(mod)); + TINT_CHECK_RESULT(lower::ShaderIO(mod)); + TINT_CHECK_RESULT(lower::Builtins(mod)); + + // TransposeRowMajor must come before DecomposeStridedMatrix as we need to convert the matrices + // first. + TINT_CHECK_RESULT(lower::TransposeRowMajor(mod)); + // DecomposeStridedMatrix must come before DecomposeStridedArray, as it introduces strided + // arrays that need to be replaced. + TINT_CHECK_RESULT(lower::DecomposeStridedMatrix(mod)); + TINT_CHECK_RESULT(lower::DecomposeStridedArray(mod)); + TINT_CHECK_RESULT(lower::Atomics(mod)); + TINT_CHECK_RESULT(lower::Texture(mod)); + + // Remove the terminator args at this point. There are no logical short-circuiting operators in + // SPIR-V that we will lose track of, all the terminators are for hoisted values. We don't do + // this on WGSL raise because `RemoveTerminatorArgs` loses the ability to determine logical `&&` + // and `||` operators based on the terminators. Moving the logical detection to a separate + // transform is also complicated because of the way it currently detects multi element `&&` and + // `||` statements. + TINT_CHECK_RESULT(core::ir::transform::RemoveTerminatorArgs(mod)); + + TINT_CHECK_RESULT( + core::ir::ValidateAndDumpIfNeeded(mod, "spirv.Lower", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + }, + "after")); + + return Success; +} + +} // namespace tint::spirv::reader diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.h new file mode 100644 index 000000000..01c9b13e3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/lower.h @@ -0,0 +1,43 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_LOWER_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_LOWER_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/result.h" + +namespace tint::spirv::reader { + +/// Lower converts a SPIR-V-dialect IR module to a core-dialect IR module +/// @param mod the IR module +/// @return the result of the operation +Result Lower(core::ir::Module& mod); + +} // namespace tint::spirv::reader + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_LOWER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.cc new file mode 100644 index 000000000..a665273f8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.cc @@ -0,0 +1,759 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/shader_io.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/referenced_module_vars.h" +#include "src/tint/lang/core/ir/validator.h" + +namespace tint::spirv::reader::lower { + +namespace { + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// A map from block to its containing function. + Hashmap block_to_function{}; + + /// A map from each function to a map from input variable to parameter. + Hashmap, 8> + function_parameter_map{}; + + /// The set of output variables that have been processed. + Hashset output_variables{}; + + /// The set of structs used as input variable types + Hashset input_structs{}; + + /// The mapping from functions to their transitively referenced output variables. + core::ir::ReferencedModuleVars referenced_output_vars{ + ir, [](const core::ir::Var* var) { + auto* view = var->Result()->Type()->As(); + return view && view->AddressSpace() == core::AddressSpace::kOut; + }}; + + /// Process the module. + Result Process() { + // Process outputs first, as that may introduce new functions that input variables need to + // be propagated through. + TINT_CHECK_RESULT(ProcessOutputs()); + ProcessInputs(); + + auto clean_members = [](const core::type::Struct* strct) { + for (auto* member : strct->Members()) { + // TODO(crbug.com/tint/745): Remove the const_cast. + const_cast(member)->ResetAttributes(); + } + }; + + // Remove attributes from all of the original structs and module-scope output variables. + // This is done last as we need to copy attributes during `ProcessEntryPointOutputs()` and + // we need access to any struct locations during processing of inputs. + for (auto& var : output_variables) { + var->ResetAttributes(); + if (auto* str = var->Result()->Type()->UnwrapPtr()->As()) { + clean_members(str); + } + } + + // All input structs have been reduced to parameters on the entry point so remove any + // annotations from the structure members. + for (auto& strct : input_structs) { + clean_members(strct); + } + return Success; + } + + /// Process output variables. + /// Changes output variables to the `private` address space and wraps entry points that produce + /// outputs with new functions that copy the outputs from the private variables to the return + /// value. + Result ProcessOutputs() { + // Update entry point functions to return their outputs, using a wrapper function. + // Use a worklist as `ProcessEntryPointOutputs()` will add new functions. + Vector entry_points; + for (auto& func : ir.functions) { + if (func->IsEntryPoint()) { + entry_points.Push(func); + } + } + for (auto& ep : entry_points) { + TINT_CHECK_RESULT(ProcessEntryPointOutputs(ep)); + } + return Success; + } + + /// Process input variables. + /// Pass inputs down the call stack as parameters to any functions that need them. + void ProcessInputs() { + // Seed the block-to-function map with the function entry blocks. + for (auto& func : ir.functions) { + block_to_function.Add(func->Block(), func); + } + + // Gather the list of all module-scope input variables. + Vector inputs; + for (auto* global : *ir.root_block) { + if (auto* var = global->As()) { + auto addrspace = var->Result()->Type()->As()->AddressSpace(); + if (addrspace == core::AddressSpace::kIn) { + inputs.Push(var); + } + } + } + + // Replace the input variables with function parameters. + for (auto* var : inputs) { + ReplaceInputPointerUses(var, var->Result()); + var->Destroy(); + } + } + + /// Replace an output pointer address space to make it `private`. + /// @param value the output variable + void ReplaceOutputPointerAddressSpace(core::ir::InstructionResult* value) { + // Change the address space to `private`. + auto* old_ptr_type = value->Type(); + auto* new_ptr_type = ty.ptr(core::AddressSpace::kPrivate, old_ptr_type->UnwrapPtr()); + value->SetType(new_ptr_type); + + // Update all uses of the module-scope variable. + value->ForEachUseUnsorted([&](core::ir::Usage use) { + if (use.instruction->IsAnyOf()) { + ReplaceOutputPointerAddressSpace(use.instruction->Result()); + } else if (use.instruction->Is()) { + use.instruction->Destroy(); + } else if (!use.instruction->IsAnyOf()) { + TINT_UNREACHABLE() + << "unexpected instruction: " << use.instruction->TypeInfo().name; + } + }); + } + + void AddOutput(Vector& output_descriptors, + Vector& results, + core::ir::Value* from, + Symbol name, + const core::type::Type* type, + core::IOAttributes& attributes) { + if (!name) { + name = ir.symbols.New(); + } + + if ((type->Is() || type->IsScalar()) || + attributes.builtin == core::BuiltinValue::kClipDistances) { + output_descriptors.Push(core::type::Manager::StructMemberDesc{name, type, attributes}); + if (attributes.location.has_value()) { + attributes.location = {attributes.location.value() + 1}; + } + results.Push(from); + return; + } + + tint::Switch( + type, + [&](const core::type::Struct* strct) { + const auto& members = strct->Members(); + auto len = members.Length(); + for (size_t i = 0; i < len; ++i) { + auto& mem = members[i]; + + auto mem_attrs = mem->Attributes(); + if (!mem_attrs.location.has_value()) { + mem_attrs.location = attributes.location; + } + if (!mem_attrs.interpolation) { + mem_attrs.interpolation = attributes.interpolation; + } + + auto* a = b.Access(mem->Type(), from, u32(mem->Index())); + + AddOutput(output_descriptors, results, a->Result(), Symbol{}, mem->Type(), + mem_attrs); + attributes.location = mem_attrs.location; + } + }, + [&](const core::type::Array* ary) { + auto cnt = ary->ConstantCount(); + TINT_ASSERT(cnt.has_value()); + + auto* ary_ty = ary->ElemType(); + for (size_t i = 0; i < cnt; ++i) { + auto* a = b.Access(ary_ty, from, u32(i)); + AddOutput(output_descriptors, results, a->Result(), Symbol{}, ary_ty, + attributes); + } + }, + [&](const core::type::Matrix* mat) { + auto* row_ty = ty.vec(mat->DeepestElement(), mat->Rows()); + for (size_t i = 0; i < mat->Columns(); ++i) { + auto* a = b.Access(row_ty, from, u32(i)); + AddOutput(output_descriptors, results, a->Result(), Symbol{}, row_ty, + attributes); + } + }, // + TINT_ICE_ON_NO_MATCH); + } + + /// Process the outputs of an entry point function, adding a wrapper function to forward outputs + /// through the return value. + /// @param ep the entry point + Result ProcessEntryPointOutputs(core::ir::Function* ep) { + const auto& referenced_outputs = referenced_output_vars.TransitiveReferences(ep); + if (referenced_outputs.IsEmpty()) { + return Success; + } + + // Add a wrapper function to return either a single value or a struct. + auto* wrapper = b.Function(ty.void_(), ep->Stage()); + if (auto name = ir.NameOf(ep)) { + ir.SetName(ep, name.Name() + "_inner"); + ir.SetName(wrapper, name); + } + + // Call the original entry point and make it a regular function. + ep->SetStage(core::ir::Function::PipelineStage::kUndefined); + b.Append(wrapper->Block(), [&] { // + b.Call(ep); + }); + + // Collect all outputs into a list of struct member declarations. + // Also add instructions to load their final values in the wrapper function. + Vector results; + Vector output_descriptors; + + for (auto* var : referenced_outputs) { + // Change the address space of the variable to private and update its uses, if we + // haven't already seen this variable. + if (output_variables.Add(var)) { + ReplaceOutputPointerAddressSpace(var->Result()); + } + + // Copy the variable attributes to the struct member. + auto var_attributes = var->Attributes(); + auto var_type = var->Result()->Type()->UnwrapPtr(); + Result result = Success; + b.Append(wrapper->Block(), [&] { + if (auto* str = var_type->As()) { + bool skipped_member_emission = false; + + // Add an output for each member of the struct. + for (auto* member : str->Members()) { + if (ShouldSkipMemberEmission(var, member)) { + skipped_member_emission = true; + continue; + } + + // Use the base variable attributes if not specified directly on the member. + auto member_attributes = member->Attributes(); + if (!member_attributes.location.has_value()) { + member_attributes.location = var_attributes.location; + } + if (!member_attributes.interpolation) { + member_attributes.interpolation = var_attributes.interpolation; + } + + // Load the final result from the member of the original struct variable. + auto* access = + b.Access(ty.ptr(member->Type()), var, u32(member->Index())); + + AddOutput(output_descriptors, results, b.Load(access)->Result(), + member->Name(), member->Type(), member_attributes); + var_attributes.location = member_attributes.location; + } + + // If we skipped emission of any member, then we need to make sure the var is + // only used through `access` instructions, otherwise the members may no longer + // match due to the skipping. + if (skipped_member_emission) { + for (auto& usage : var->Result()->UsagesUnsorted()) { + auto* access = usage->instruction->As(); + TINT_ASSERT(access); + auto* const_idx = access->Indices()[0]->As(); + TINT_ASSERT(const_idx); + + // Check that pointsize members are only assigned values of 1.0. + auto* member = str->Members()[const_idx->Value()->ValueAs()]; + if (member->Attributes().builtin == core::BuiltinValue::kPointSize) { + result = ValidatePointSizeStore(access); + return; + } + } + } + } else { + // Don't want to emit point size as it doesn't exist in WGSL. + if (var->Attributes().builtin == core::BuiltinValue::kPointSize) { + var->SetInitializer(b.Constant(1.0_f)); + result = ValidatePointSizeStore(var); + return; + } + + // Load the final result from the original variable. + auto* ld = b.Load(var); + + core::ir::Value* from = nullptr; + // If we're dealing with sample_mask, extract the scalar from the array. + if (var_attributes.builtin == core::BuiltinValue::kSampleMask) { + // The SPIR-V mask can be either i32 or u32, but WGSL is only u32. So, + // convert if necessary. + auto* access = + b.Access(ld->Result()->Type()->DeepestElement(), ld, u32(0))->Result(); + if (access->Type()->IsSignedIntegerScalar()) { + access = b.Convert(ty.u32(), access)->Result(); + } + from = access; + var_type = ty.u32(); + } else { + from = ld->Result(); + } + + AddOutput(output_descriptors, results, from, ir.NameOf(var), var_type, + var_attributes); + } + }); + TINT_CHECK_RESULT(result); + } + + if (output_descriptors.Length() == 1) { + // Copy the output attributes to the function return. + wrapper->SetReturnAttributes(output_descriptors[0].attributes); + + // Return the output from the wrapper function. + wrapper->SetReturnType(output_descriptors[0].type); + b.Append(wrapper->Block(), [&] { // + b.Return(wrapper, results[0]); + }); + } else { + // Create a struct to hold all of the output values. + auto* str = ty.Struct(ir.symbols.New(), std::move(output_descriptors)); + wrapper->SetReturnType(str); + + // Collect the output values and return them from the wrapper function. + b.Append(wrapper->Block(), [&] { // + b.Return(wrapper, b.Construct(str, std::move(results))); + }); + } + return Success; + } + + /// Validates that a `point_size` builtin is only ever stored to with the constant value `1.0`, + /// or is loaded from. + /// @param point_size the `point_size` pointer + /// @returns success if the validation passes, otherwise a failure. + Result ValidatePointSizeStore(core::ir::Instruction* point_size) { + Vector worklist; + point_size->Result()->ForEachUseUnsorted([&](core::ir::Usage use) { // + worklist.Push(use.instruction); + }); + + while (!worklist.IsEmpty()) { + auto* inst = worklist.Pop(); + if (auto* store = inst->As()) { + auto* constant = store->From()->As(); + if (!constant) { + return Failure{"store to point_size is not a constant"}; + } + TINT_ASSERT(constant->Type()->Is()); + if (constant->Value()->ValueAs() != 1.0f) { + return Failure{"store to point_size is not 1.0"}; + } + } else if (inst->Is()) { + // Load instructions are OK. + } else if (auto* let = inst->As()) { + // Check all uses of the let instruction. + let->Result()->ForEachUseUnsorted([&](core::ir::Usage use) { // + worklist.Push(use.instruction); + }); + } else { + return Failure{"unhandled use of a point_size variable: " + + std::string(inst->TypeInfo().name)}; + } + } + return Success; + } + + /// Returns true if the struct member should be skipped on emission + /// @param var the var which references the structure + /// @param member the member to check + /// @returns true if the member should be skipped. + bool ShouldSkipMemberEmission(core::ir::Var* var, const core::type::StructMember* member) { + auto var_attributes = var->Attributes(); + auto member_attributes = member->Attributes(); + + // If neither the var, nor the member has attributes, then skip + if (!var_attributes.builtin.has_value() && !var_attributes.color.has_value() && + !var_attributes.location.has_value()) { + if (!member_attributes.builtin.has_value() && !member_attributes.color.has_value() && + !member_attributes.location.has_value()) { + return true; + } + } + + // The `gl_PerVertex` structure always gets emitted by glslang, but it may only be used by + // the `gl_Position` variable. The structure will also contain the `gl_PointSize`, + // `gl_ClipDistance` and `gl_CullDistance`. + + if (member_attributes.builtin == core::BuiltinValue::kPointSize) { + return true; + } + if (member_attributes.builtin == core::BuiltinValue::kCullDistance) { + TINT_ASSERT(!IsIndexAccessed(var->Result(), member->Index())); + return true; + } + if (member_attributes.builtin == core::BuiltinValue::kClipDistances) { + return !IsIndexAccessed(var->Result(), member->Index()); + } + return false; + } + + /// Returns true if the `idx` member of `val` is accessed. The `val` must be of type + /// `Structure` which contains the given member index. + /// @param val the value to check + /// @param idx the index to look for + /// @returns true if `idx` is accessed. + bool IsIndexAccessed(core::ir::Value* val, uint32_t idx) { + for (auto& usage : val->UsagesUnsorted()) { + // Only care about access chains + auto* chain = usage->instruction->As(); + if (!chain) { + continue; + } + TINT_ASSERT(chain->Indices().Length() >= 1); + + // A member access has to be a constant index + auto* cnst = chain->Indices()[0]->As(); + if (!cnst) { + continue; + } + + uint32_t v = cnst->Value()->ValueAs(); + if (v == idx) { + return true; + } + } + return false; + } + + /// Replace a use of an input pointer value. + /// @param var the originating input variable + /// @param value the input pointer value + void ReplaceInputPointerUses(core::ir::Var* var, core::ir::Value* value) { + Vector to_destroy; + value->ForEachUseUnsorted([&](core::ir::Usage use) { + auto* object = value; + if (object->Type()->Is()) { + // Get (or create) the function parameter that will replace the variable. + auto* func = ContainingFunction(use.instruction); + object = GetParameter(func, var); + } + + Switch( + use.instruction, + [&](core::ir::Load* l) { + // Fold the load away and replace its uses with the new parameter. + l->Result()->ReplaceAllUsesWith(object); + to_destroy.Push(l); + }, + [&](core::ir::LoadVectorElement* lve) { + // Replace the vector element load with an access instruction. + auto* access = b.AccessWithResult(lve->DetachResult(), object, lve->Index()); + access->InsertBefore(lve); + to_destroy.Push(lve); + }, + [&](core::ir::Access* a) { + // Remove the pointer from the source and destination type. + a->SetOperand(core::ir::Access::kObjectOperandOffset, object); + a->Result()->SetType(a->Result()->Type()->UnwrapPtr()); + ReplaceInputPointerUses(var, a->Result()); + }, + [&](core::ir::Let* l) { + // Fold away + ReplaceInputPointerUses(var, l->Result()); + to_destroy.Push(l); + }, + [&](core::ir::Phony* p) { to_destroy.Push(p); }, // + TINT_ICE_ON_NO_MATCH); + }); + + // Clean up orphaned instructions. + for (auto* inst : to_destroy) { + inst->Destroy(); + } + } + + /// Get the function that contains an instruction. + /// @param inst the instruction + /// @returns the function + core::ir::Function* ContainingFunction(core::ir::Instruction* inst) { + return block_to_function.GetOrAdd(inst->Block(), [&] { // + return ContainingFunction(inst->Block()->Parent()); + }); + } + + core::ir::Value* GetEntryPointParameter(core::ir::Function* func, core::ir::Var* var) { + auto* var_type = var->Result()->Type()->UnwrapPtr(); + + // The SPIR_V type may not match the required WGSL entry point type, swap them as + // needed. + if (var->Attributes().builtin.has_value()) { + switch (var->Attributes().builtin.value()) { + case core::BuiltinValue::kSampleMask: { + TINT_ASSERT(var_type->Is()); + TINT_ASSERT(var_type->As()->ConstantCount() == 1u); + var_type = ty.u32(); + break; + } + case core::BuiltinValue::kInstanceIndex: + case core::BuiltinValue::kPrimitiveIndex: + case core::BuiltinValue::kVertexIndex: + case core::BuiltinValue::kLocalInvocationIndex: + case core::BuiltinValue::kSubgroupInvocationId: + case core::BuiltinValue::kSubgroupSize: + case core::BuiltinValue::kSampleIndex: { + var_type = ty.u32(); + break; + } + case core::BuiltinValue::kLocalInvocationId: + case core::BuiltinValue::kGlobalInvocationId: + case core::BuiltinValue::kWorkgroupId: + case core::BuiltinValue::kNumWorkgroups: { + var_type = ty.vec3u(); + break; + } + default: { + break; + } + } + } + + // Create a new function parameter for the input. + core::ir::Value* param = nullptr; + b.InsertBefore(func->Block()->Front(), + [&] { param = CreateParam(func, var_type, var->Attributes()); }); + + if (auto name = ir.NameOf(var)) { + ir.SetName(param, name); + } + + core::ir::Value* result = param; + if (var->Attributes().builtin.has_value()) { + switch (var->Attributes().builtin.value()) { + case core::BuiltinValue::kSampleMask: { + // Construct an array from the scalar sample_mask builtin value for entry + // points. + + auto* mask_ty = var->Result()->Type()->UnwrapPtr()->As(); + TINT_ASSERT(mask_ty); + + // If the SPIR-V mask was an i32, need to convert from the u32 provided by + // WGSL. + if (mask_ty->ElemType()->IsSignedIntegerScalar()) { + auto* conv = b.Convert(ty.i32(), result); + func->Block()->Prepend(conv); + + auto* construct = b.Construct(mask_ty, conv); + construct->InsertAfter(conv); + result = construct->Result(); + } else { + auto* construct = b.Construct(mask_ty, result); + func->Block()->Prepend(construct); + result = construct->Result(); + } + break; + } + case core::BuiltinValue::kInstanceIndex: + case core::BuiltinValue::kPrimitiveIndex: + case core::BuiltinValue::kVertexIndex: + case core::BuiltinValue::kLocalInvocationIndex: + case core::BuiltinValue::kSubgroupInvocationId: + case core::BuiltinValue::kSubgroupSize: + case core::BuiltinValue::kSampleIndex: { + auto* idx_ty = var->Result()->Type()->UnwrapPtr(); + if (idx_ty->IsSignedIntegerScalar()) { + auto* conv = b.Convert(ty.i32(), result); + func->Block()->Prepend(conv); + result = conv->Result(); + } + break; + } + case core::BuiltinValue::kLocalInvocationId: + case core::BuiltinValue::kGlobalInvocationId: + case core::BuiltinValue::kWorkgroupId: + case core::BuiltinValue::kNumWorkgroups: { + auto* idx_ty = var->Result()->Type()->UnwrapPtr(); + auto* elem_ty = idx_ty->DeepestElement(); + if (elem_ty->IsSignedIntegerScalar()) { + auto* conv = b.Convert(ty.MatchWidth(ty.i32(), idx_ty), result); + func->Block()->Prepend(conv); + result = conv->Result(); + } + break; + } + default: { + break; + } + } + } + return result; + } + + /// Get or create a function parameter to replace a module-scope variable. + /// @param func the function + /// @param var the module-scope variable + /// @returns the function parameter + core::ir::Value* GetParameter(core::ir::Function* func, core::ir::Var* var) { + return function_parameter_map.GetOrAddZero(func).GetOrAdd(var, [&]() -> core::ir::Value* { + if (func->IsEntryPoint()) { + return GetEntryPointParameter(func, var); + } + + // Create a new function parameter for the input. + auto* param = b.FunctionParam(var->Result()->Type()->UnwrapPtr()); + func->AppendParam(param); + if (auto name = ir.NameOf(var)) { + ir.SetName(param, name); + } + + // Update the call sites of this function. + func->ForEachUseUnsorted([&](core::ir::Usage use) { + if (auto* call = use.instruction->As()) { + // Recurse into the calling function. + auto* caller = ContainingFunction(call); + call->AppendArg(GetParameter(caller, var)); + } else if (!use.instruction->Is()) { + TINT_UNREACHABLE() + << "unexpected instruction: " << use.instruction->TypeInfo().name; + } + }); + + return param; + }); + } + + core::ir::Value* CreateParam(core::ir::Function* func, + const core::type::Type* type, + core::IOAttributes& attributes) { + if (type->IsScalar() || type->Is()) { + auto* fp = b.FunctionParam(type); + fp->SetAttributes(attributes); + + if (attributes.location.has_value()) { + attributes.location = {attributes.location.value() + 1}; + } + + func->AppendParam(fp); + return fp; + } + + Vector params; + tint::Switch( + type, // + [&](const core::type::Array* ary) { + auto cnt = ary->ConstantCount(); + TINT_ASSERT(cnt.has_value()); + + params.Reserve(cnt.value()); + + auto* ary_ty = ary->ElemType(); + for (size_t i = 0; i < cnt; ++i) { + params.Push(CreateParam(func, ary_ty, attributes)); + } + }, + [&](const core::type::Matrix* mat) { + params.Reserve(mat->Columns()); + + auto* row_ty = ty.vec(mat->DeepestElement(), mat->Rows()); + for (size_t i = 0; i < mat->Columns(); ++i) { + params.Push(CreateParam(func, row_ty, attributes)); + } + }, + [&](const core::type::Struct* strct) { + params.Reserve(strct->Members().Length()); + + input_structs.Add(strct); + + const auto& members = strct->Members(); + auto len = members.Length(); + for (size_t i = 0; i < len; ++i) { + auto& mem = members[i]; + + auto mem_attrs = mem->Attributes(); + if (attributes.location.has_value()) { + mem_attrs.location = attributes.location.value(); + } + if (!mem_attrs.interpolation) { + mem_attrs.interpolation = attributes.interpolation; + } + + params.Push(CreateParam(func, mem->Type(), mem_attrs)); + attributes.location = mem_attrs.location; + } + }, // + TINT_ICE_ON_NO_MATCH); + + return b.Construct(type, params)->Result(); + } +}; + +} // namespace + +Result ShaderIO(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.ShaderIO", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPhonyInstructions, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowStructMatrixDecorations, + core::ir::Capability::kAllowLocationForNumericElements, + core::ir::Capability::kAllowPointerToHandle, + core::ir::Capability::kLoosenValidationForShaderIO, + })); + + return State{ir}.Process(); +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.h new file mode 100644 index 000000000..58f83de46 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/shader_io.h @@ -0,0 +1,48 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_SHADER_IO_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_SHADER_IO_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// ShaderIO is a transform that converts SPIR-V's style of shader IO (using global variables) into +/// the form expected by Tint's core IR (using function parameters and return values). +/// @param module the module to transform +/// @returns success or failure +Result ShaderIO(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_SHADER_IO_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.cc new file mode 100644 index 000000000..f793dc63f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.cc @@ -0,0 +1,1046 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/texture.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/spirv/builtin_fn.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/lang/spirv/type/image.h" + +namespace tint::spirv::reader::lower { +namespace { + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +enum class ImageOperandsMask : uint32_t { + kBias = 0x00000001, + kLod = 0x00000002, + kGrad = 0x00000004, + kConstOffset = 0x00000008, + kSample = 0x00000040, +}; + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Map of all OpSampledImages seen + Hashmap sampled_images_{}; + + /// Any `ir::UserCall` instructions which have texture params which need to be updated. + Hashset user_calls_to_convert_{}; + + /// The `ir::Values`s which have had their types changed, they then need to have their + /// usages updated to match. This maps to the root FunctionParam or Var for each texture. + Vector values_to_fix_usages_{}; + + Vector lets_to_inline_{}; + + /// Function to texture replacements + Hashmap func_to_rewritten_{}; + + /// Set of textures used in dref calls which need to be depth textures. + Hashset textures_to_convert_to_depth_{}; + /// Set of samplers used in dref calls which need to be comparison samplers + Hashset samplers_to_convert_to_comparison_{}; + + /// Process the module. + void Process() { + ReplacePointerToHandle(); + + for (auto* inst : *ir.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + + auto* ptr = var->Result()->Type()->As(); + TINT_ASSERT(ptr); + + auto* type = ptr->UnwrapPtr(); + if (!type->IsAnyOf()) { + continue; + } + + auto* new_ty = TypeFor(type); + if (type->Is()) { + var->Result()->SetType(ty.ptr(ptr->AddressSpace(), new_ty, ptr->Access())); + values_to_fix_usages_.Push(var->Result()); + } + + var->Result()->ForEachUseUnsorted([&](const core::ir::Usage& usage) { + tint::Switch( + usage.instruction, // + [&](core::ir::Load* l) { + if (type->Is()) { + l->Result()->SetType(new_ty); + } + }, + [&](core::ir::Let* let) { + if (type->Is()) { + lets_to_inline_.Push(let); + } + }); + }); + } + + Vector depth_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* builtin = inst->As()) { + switch (builtin->Func()) { + case spirv::BuiltinFn::kOpSampledImage: + SampledImage(builtin); + break; + case spirv::BuiltinFn::kImageDrefGather: + case spirv::BuiltinFn::kImageSampleDrefImplicitLod: + case spirv::BuiltinFn::kImageSampleDrefExplicitLod: + case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod: + case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod: + depth_worklist.Push(builtin); + break; + default: + break; + } + } + } + + // TODO(dsinclair): Propagate OpTypeSampledImage through function params by replacing with + // the texture/sampler + + // Run the depth functions first so we can convert all the types to depth that are needed. + // This then allows things like textureSample calls below to have the correct return type + // and be able to convert the results if needed. + for (auto* builtin : depth_worklist) { + switch (builtin->Func()) { + case spirv::BuiltinFn::kImageSampleDrefImplicitLod: + case spirv::BuiltinFn::kImageSampleDrefExplicitLod: + case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod: + case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod: + ImageSampleDref(builtin); + break; + case spirv::BuiltinFn::kImageDrefGather: + ImageGatherDref(builtin); + break; + default: + TINT_UNREACHABLE(); + } + } + + for (auto tex : textures_to_convert_to_depth_) { + ConvertVarToDepth(FindRootVarFor(tex)); + } + for (auto tex : samplers_to_convert_to_comparison_) { + ConvertVarToComparison(FindRootVarFor(tex)); + } + UpdateValues(); + + Vector builtin_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* builtin = inst->As()) { + switch (builtin->Func()) { + case spirv::BuiltinFn::kOpSampledImage: + // Note, we _also_ do this here even though it was done above. The one above + // registers for the depth functions, but, we may have forked functions in + // the `UpdateValues` when it does the `ConvertUserCalls`. This would then + // generate new `SampledImage` objects which need to be registered. In the + // worse case, we just write the same data twice. + SampledImage(builtin); + break; + case spirv::BuiltinFn::kOpImage: + case spirv::BuiltinFn::kImageRead: + case spirv::BuiltinFn::kImageFetch: + case spirv::BuiltinFn::kImageGather: + case spirv::BuiltinFn::kImageQueryLevels: + case spirv::BuiltinFn::kImageQuerySamples: + case spirv::BuiltinFn::kImageQuerySize: + case spirv::BuiltinFn::kImageQuerySizeLod: + case spirv::BuiltinFn::kImageSampleExplicitLod: + case spirv::BuiltinFn::kImageSampleImplicitLod: + case spirv::BuiltinFn::kImageSampleProjImplicitLod: + case spirv::BuiltinFn::kImageSampleProjExplicitLod: + case spirv::BuiltinFn::kImageWrite: + builtin_worklist.Push(builtin); + break; + default: + TINT_UNREACHABLE() << "unknown spirv builtin: " << builtin->Func(); + } + } + } + + for (auto* builtin : builtin_worklist) { + switch (builtin->Func()) { + case spirv::BuiltinFn::kOpImage: + Image(builtin); + break; + case spirv::BuiltinFn::kImageRead: + ImageFetch(builtin); + break; + case spirv::BuiltinFn::kImageFetch: + ImageFetch(builtin); + break; + case spirv::BuiltinFn::kImageGather: + ImageGather(builtin); + break; + case spirv::BuiltinFn::kImageQueryLevels: + ImageQuery(builtin, core::BuiltinFn::kTextureNumLevels); + break; + case spirv::BuiltinFn::kImageQuerySamples: + ImageQuery(builtin, core::BuiltinFn::kTextureNumSamples); + break; + case spirv::BuiltinFn::kImageQuerySize: + case spirv::BuiltinFn::kImageQuerySizeLod: + ImageQuerySize(builtin); + break; + case spirv::BuiltinFn::kImageSampleExplicitLod: + case spirv::BuiltinFn::kImageSampleImplicitLod: + case spirv::BuiltinFn::kImageSampleProjImplicitLod: + case spirv::BuiltinFn::kImageSampleProjExplicitLod: + ImageSample(builtin); + break; + case spirv::BuiltinFn::kImageWrite: + ImageWrite(builtin); + break; + default: + TINT_UNREACHABLE(); + } + } + + // Destroy all the OpSampledImage instructions. + for (auto res : sampled_images_) { + // If the sampled image was in a user function which was forked and the original + // destroyed then it will no longer be alive. + if (res.value->Alive()) { + res.value->Destroy(); + } + } + } + + void ReplacePointerToHandle() { + Vector usages_to_update; + Hashset called_functions_to_fixup; + for (auto& func : ir.DependencyOrderedFunctions()) { + for (auto* param : func->Params()) { + auto* ptr = param->Type()->As(); + if (!ptr || !ptr->StoreType()->IsHandle()) { + continue; + } + + param->SetType(ptr->StoreType()); + usages_to_update.Push(param); + called_functions_to_fixup.Add(func); + } + } + + Vector inst_to_delete; + while (!usages_to_update.IsEmpty()) { + auto* val = usages_to_update.Pop(); + for (auto& usage : val->UsagesSorted()) { + tint::Switch( + usage.instruction, // + [&](core::ir::Load* ld) { + ld->Result()->ReplaceAllUsesWith(ld->From()); + inst_to_delete.Push(ld); + }, + [&](core::ir::Let* l) { + for (auto& u : l->Result()->UsagesSorted()) { + usages_to_update.Push(u.instruction->Result()); + } + l->Result()->ReplaceAllUsesWith(l->Value()); + inst_to_delete.Push(l); + }); + } + } + + for (auto& fn : called_functions_to_fixup) { + for (auto& usage : fn->UsagesUnsorted()) { + auto* call = usage->instruction->As(); + if (!call) { + continue; + } + + auto args = call->Args(); + for (size_t i = 0; i < args.Length(); ++i) { + auto& arg = args[i]; + + auto* ptr_ty = arg->Type()->As(); + if (!ptr_ty) { + continue; + } + + if (!ptr_ty->StoreType()->IsHandle()) { + continue; + } + + // We inject the load here but it will get cleaned up when we deal with the + // function itself, if required. + b.InsertBefore(usage->instruction, [&] { + auto* ld = b.Load(arg); + call->SetArg(i, ld->Result()); + }); + } + } + } + + while (!inst_to_delete.IsEmpty()) { + auto* inst = inst_to_delete.Pop(); + inst->Destroy(); + } + } + + void UpdateValues() { + // The double loop happens because when we convert user calls, that will + // add more values to convert, but those values can find user calls to + // convert, so we have to work until we stabilize + while (!values_to_fix_usages_.IsEmpty() || !lets_to_inline_.IsEmpty() || + !user_calls_to_convert_.IsEmpty()) { + while (!values_to_fix_usages_.IsEmpty()) { + auto* val = values_to_fix_usages_.Pop(); + ConvertUsagesToTexture(val); + } + + while (!lets_to_inline_.IsEmpty()) { + auto* let = lets_to_inline_.Pop(); + TINT_ASSERT(let->Value()); + let->Result()->ReplaceAllUsesWith(let->Value()); + // We may have done this value already, but push it back on as any of the let usages + // will now point to it and they need to be updated. + values_to_fix_usages_.Push(let->Value()); + let->Destroy(); + } + + auto user_calls = user_calls_to_convert_.Vector(); + // Sort for deterministic output + user_calls.Sort(); + for (auto& call : user_calls) { + ConvertUserCall(call); + } + user_calls_to_convert_.Clear(); + } + + TINT_ASSERT(lets_to_inline_.IsEmpty()); + TINT_ASSERT(values_to_fix_usages_.IsEmpty()); + TINT_ASSERT(user_calls_to_convert_.IsEmpty()); + } + + // Given a value, walk back up and find the root `var`. + core::ir::Var* FindRootVarFor(core::ir::Value* val) { + auto* inst_res = val->As(); + TINT_ASSERT(inst_res); + return tint::Switch( + inst_res->Instruction(), // + [&](core::ir::Let* l) { return FindRootVarFor(l->Value()); }, + [&](core::ir::Load* l) { return FindRootVarFor(l->From()); }, + [&](core::ir::Var* v) { return v; }, // + TINT_ICE_ON_NO_MATCH); + } + + void ConvertVarToDepth(core::ir::Var* var) { + auto* orig_ptr_ty = var->Result()->Type()->As(); + TINT_ASSERT(orig_ptr_ty); + + auto* orig_tex_ty = orig_ptr_ty->UnwrapPtr()->As(); + TINT_ASSERT(orig_tex_ty); + + const core::type::Type* depth_ty = nullptr; + if (orig_tex_ty->Is()) { + depth_ty = ty.depth_multisampled_texture(orig_tex_ty->Dim()); + } else { + depth_ty = ty.depth_texture(orig_tex_ty->Dim()); + } + + auto* depth_ptr = ty.ptr(orig_ptr_ty->AddressSpace(), depth_ty, orig_ptr_ty->Access()); + var->Result()->SetType(depth_ptr); + + values_to_fix_usages_.Push(var->Result()); + } + + void ConvertVarToComparison(core::ir::Var* var) { + auto* orig_ptr_ty = var->Result()->Type()->As(); + TINT_ASSERT(orig_ptr_ty); + + auto* sampler = ty.comparison_sampler(); + auto* sampler_ptr = ty.ptr(orig_ptr_ty->AddressSpace(), sampler, orig_ptr_ty->Access()); + var->Result()->SetType(sampler_ptr); + + values_to_fix_usages_.Push(var->Result()); + } + + // Stores information for operands which need to be updated with the new load result. + struct ReplacementValue { + // The instruction to update + core::ir::Instruction* instruction; + // The operand index to insert into + size_t idx; + // The new value to insert into the instruction operands at `idx` + core::ir::Value* value; + }; + + void ConvertUsagesToTexture(core::ir::Value* val) { + val->ForEachUseUnsorted([&](const core::ir::Usage& usage) { + auto* inst = usage.instruction; + + tint::Switch( // + inst, // + [&](core::ir::Let* l) { lets_to_inline_.Push(l); }, + [&](core::ir::Load* l) { + auto* res = l->Result(); + res->SetType(val->Type()->UnwrapPtr()); + values_to_fix_usages_.Push(res); + }, // + [&](core::ir::UserCall* uc) { user_calls_to_convert_.Add(uc); }, + [&](core::ir::BuiltinCall*) {}, // + TINT_ICE_ON_NO_MATCH); + }); + } + + // The user calls need to check all of the parameters which were converted + // to textures and create a forked function call for that combination of + // parameters. + void ConvertUserCall(core::ir::UserCall* uc) { + auto* target = uc->Target(); + auto& params = target->Params(); + const auto& args = uc->Args(); + + Vector to_convert; + for (size_t i = 0; i < args.Length(); ++i) { + if (params[i]->Type() != args[i]->Type()) { + to_convert.Push(i); + } + } + // Everything is already converted we're done. + if (to_convert.IsEmpty()) { + return; + } + + auto* new_fn = func_to_rewritten_.GetOrAdd(target, [&] { + core::ir::CloneContext ctx{ir}; + auto* fn = uc->Target()->Clone(ctx); + ir.functions.Push(fn); + + for (auto idx : to_convert) { + auto* p = fn->Params()[idx]; + p->SetType(args[idx]->Type()); + values_to_fix_usages_.Push(p); + } + return fn; + }); + uc->SetTarget(new_fn); + + if (target->IsEntryPoint()) { + return; + } + + // Check if any of the usages are calls, if they aren't we can destroy the function. + for (auto& usage : target->UsagesUnsorted()) { + if (usage->instruction->Is()) { + return; + } + } + ir.Destroy(target); + } + + // Record the sampled image so we can extract the texture/sampler information as we process the + // builtins. It will be destroyed after all builtins are done. + void SampledImage(spirv::ir::BuiltinCall* call) { sampled_images_.Add(call->Result(), call); } + + std::pair GetTextureSampler(core::ir::Value* sampled) { + auto res = sampled_images_.Get(sampled); + TINT_ASSERT(res); + + core::ir::Instruction* inst = *res; + TINT_ASSERT(inst->Operands().Length() == 2); + + return {inst->Operands()[0], inst->Operands()[1]}; + } + + uint32_t CoordsRequiredForDim(core::type::TextureDimension dim, bool is_proj) { + uint32_t ret = 0; + if (is_proj) { + ++ret; + } + + switch (dim) { + case core::type::TextureDimension::k1d: + ret += 1; + break; + case core::type::TextureDimension::k2d: + ret += 2; + break; + case core::type::TextureDimension::k2dArray: + case core::type::TextureDimension::k3d: + case core::type::TextureDimension::kCube: + ret += 3; + break; + case core::type::TextureDimension::kCubeArray: + ret += 4; + break; + default: + TINT_UNREACHABLE(); + } + + return ret; + } + + uint32_t Length(const core::type::Type* type) { + if (type->IsScalar()) { + return 1; + } + if (auto* vec = type->As()) { + return vec->Width(); + } + TINT_UNREACHABLE(); + } + + void ProcessCoords(const core::type::Type* type, + bool is_proj, + core::ir::Value* coords, + Vector& new_args) { + auto* tex_ty = type->As(); + TINT_ASSERT(tex_ty); + + auto coords_received = Length(coords->Type()); + + auto mk_coords = [&](uint32_t count) -> core::ir::Value* { + if (count == coords_received) { + return coords; + } + + Vector swizzle_idx = {0}; + for (uint32_t i = 1; i < count; ++i) { + swizzle_idx.Push(i); + } + + auto* new_ty = ty.MatchWidth(coords->Type()->DeepestElement(), count); + return b.Swizzle(new_ty, coords, swizzle_idx)->Result(); + }; + + auto coords_needed = CoordsRequiredForDim(tex_ty->Dim(), is_proj); + TINT_ASSERT(coords_needed <= coords_received); + + if (!is_proj && !IsTextureArray(tex_ty->Dim())) { + new_args.Push(mk_coords(coords_needed)); + return; + } + + auto* coords_ty = coords->Type()->As(); + TINT_ASSERT(coords_ty); + + // The array / projection index, is on the end + uint32_t new_coords_width = coords_needed - 1; + auto* new_coords_ty = ty.MatchWidth(coords_ty->Type(), new_coords_width); + + auto* swizzle = mk_coords(new_coords_width); + core::ir::Value* last = + b.Swizzle(coords_ty->Type(), coords, Vector{new_coords_width})->Result(); + + if (is_proj) { + // New coords + // Divide the coordinates by the last value to simulate the + // projection behaviour. + new_args.Push(b.Divide(swizzle, last)->Result()); + } else { + TINT_ASSERT(new_coords_ty->Is()); + + // New coords + new_args.Push(swizzle); + // Array index + if (!last->Type()->Is()) { + last = b.Convert(ty.i32(), last)->Result(); + } + new_args.Push(last); + } + } + + void ProcessOffset(core::ir::Value* offset, Vector& new_args) { + if (offset->Type()->IsSignedIntegerVector()) { + new_args.Push(offset); + return; + } + + auto* vec_ty = offset->Type()->As(); + TINT_ASSERT(vec_ty); + + auto* ir_constant = offset->As(); + TINT_ASSERT(ir_constant); + + auto* constant_value = ir_constant->Value(); + + Vector new_values; + for (size_t i = 0; i < vec_ty->Width(); ++i) { + uint32_t v = constant_value->Index(i)->ValueAs(); + new_values.Push(b.ConstantValue(i32(v))); + } + + auto* new_offset = b.Composite(ty.vec(ty.i32(), vec_ty->Width()), new_values); + new_args.Push(new_offset); + } + + uint32_t GetOperandMask(core::ir::Value* val) { + auto* op = val->As(); + TINT_ASSERT(op); + return op->Value()->ValueAs(); + } + + bool HasBias(uint32_t mask) { + return (mask & static_cast(ImageOperandsMask::kBias)) != 0; + } + bool HasGrad(uint32_t mask) { + return (mask & static_cast(ImageOperandsMask::kGrad)) != 0; + } + bool HasLod(uint32_t mask) { + return (mask & static_cast(ImageOperandsMask::kLod)) != 0; + } + bool HasConstOffset(uint32_t mask) { + return (mask & static_cast(ImageOperandsMask::kConstOffset)) != 0; + } + bool HasSample(uint32_t mask) { + return (mask & static_cast(ImageOperandsMask::kSample)) != 0; + } + + void Image(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + core::ir::Value* tex = nullptr; + [[maybe_unused]] core::ir::Value* sampler = nullptr; + std::tie(tex, sampler) = GetTextureSampler(args[0]); + + call->Result()->ReplaceAllUsesWith(tex); + call->Destroy(); + } + + void ImageFetch(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + core::ir::Value* tex = args[0]; + auto* coords = args[1]; + + auto* tex_ty = tex->Type(); + uint32_t operand_mask = GetOperandMask(args[2]); + + Vector new_args = {tex}; + ProcessCoords(tex->Type(), false, coords, new_args); + + uint32_t idx = 3; + if (HasLod(operand_mask)) { + core::ir::Value* lod = args[idx++]; + + if (!lod->Type()->Is()) { + lod = b.Convert(ty.i32(), lod)->Result(); + } + new_args.Push(lod); + } else if (!tex_ty->IsAnyOf()) { + // textureLoad requires an explicit level-of-detail parameter for non-multisampled + // and non-storage texture types. + new_args.Push(b.Zero(ty.i32())); + } + if (HasSample(operand_mask)) { + core::ir::Value* sample = args[idx++]; + + if (!sample->Type()->Is()) { + sample = b.Convert(ty.i32(), sample)->Result(); + } + new_args.Push(sample); + } + + // Depth textures have a single value return in WGSL, but a vec4 in SPIR-V. + auto* call_ty = call->Result()->Type(); + if (tex_ty->IsAnyOf()) { + call_ty = call_ty->DeepestElement(); + } + auto* res = b.Call(call_ty, core::BuiltinFn::kTextureLoad, new_args)->Result(); + + // Restore the vec4 result by padding with 0's. + if (call_ty != call->Result()->Type()) { + auto* vec = call->Result()->Type()->As(); + TINT_ASSERT(vec && vec->Width() == 4); + + auto* z = b.Zero(call_ty); + res = b.Construct(call->Result()->Type(), res, z, z, z)->Result(); + } + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + void ImageGatherDref(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + core::ir::Value* tex = nullptr; + core::ir::Value* sampler = nullptr; + std::tie(tex, sampler) = GetTextureSampler(args[0]); + + textures_to_convert_to_depth_.Add(tex); + samplers_to_convert_to_comparison_.Add(sampler); + + auto* coords = args[1]; + auto* dref = args[2]; + + uint32_t operand_mask = GetOperandMask(args[3]); + + Vector new_args; + + new_args.Push(tex); + new_args.Push(sampler); + + ProcessCoords(tex->Type(), false, coords, new_args); + new_args.Push(dref); + + if (HasConstOffset(operand_mask)) { + ProcessOffset(args[4], new_args); + } + + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kTextureGatherCompare, + new_args); + }); + call->Destroy(); + } + + void ImageGather(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + core::ir::Value* tex = nullptr; + core::ir::Value* sampler = nullptr; + std::tie(tex, sampler) = GetTextureSampler(args[0]); + + auto* coords = args[1]; + auto* component = args[2]; + + uint32_t operand_mask = GetOperandMask(args[3]); + + Vector new_args; + if (!tex->Type()->Is()) { + new_args.Push(component); + } + new_args.Push(tex); + new_args.Push(sampler); + + ProcessCoords(tex->Type(), false, coords, new_args); + + if (HasConstOffset(operand_mask)) { + ProcessOffset(args[4], new_args); + } + + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kTextureGather, new_args); + }); + call->Destroy(); + } + + void ImageSampleDref(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + auto* sampled_image = args[0]; + + core::ir::Value* tex = nullptr; + core::ir::Value* sampler = nullptr; + std::tie(tex, sampler) = GetTextureSampler(sampled_image); + + textures_to_convert_to_depth_.Add(tex); + samplers_to_convert_to_comparison_.Add(sampler); + + auto* tex_ty = tex->Type(); + + auto* coords = args[1]; + auto* depth = args[2]; + uint32_t operand_mask = GetOperandMask(args[3]); + + bool is_proj = call->Func() == spirv::BuiltinFn::kImageSampleProjDrefImplicitLod || + call->Func() == spirv::BuiltinFn::kImageSampleProjDrefExplicitLod; + + uint32_t idx = 4; + b.InsertBefore(call, [&] { + Vector new_args; + new_args.Push(tex); + new_args.Push(sampler); + + ProcessCoords(tex_ty, is_proj, coords, new_args); + new_args.Push(depth); + + auto fn = core::BuiltinFn::kTextureSampleCompare; + if (HasLod(operand_mask)) { + fn = core::BuiltinFn::kTextureSampleCompareLevel; + idx++; // Skip over the index + + // Metal only supports Lod = 0 for comparison sampling without derivatives. So, WGSL + // doesn't take a level value, drop the LOD param. + } + if (HasConstOffset(operand_mask)) { + ProcessOffset(args[idx++], new_args); + } + + b.CallWithResult(call->DetachResult(), fn, new_args); + }); + + call->Destroy(); + } + + void ImageSample(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + auto* sampled_image = args[0]; + + core::ir::Value* tex = nullptr; + core::ir::Value* sampler = nullptr; + std::tie(tex, sampler) = GetTextureSampler(sampled_image); + + auto* tex_ty = tex->Type(); + + auto* coords = args[1]; + uint32_t operand_mask = GetOperandMask(args[2]); + + bool is_proj = call->Func() == spirv::BuiltinFn::kImageSampleProjImplicitLod || + call->Func() == spirv::BuiltinFn::kImageSampleProjExplicitLod; + + uint32_t idx = 3; + b.InsertBefore(call, [&] { + Vector new_args; + new_args.Push(tex); + new_args.Push(sampler); + + ProcessCoords(tex_ty, is_proj, coords, new_args); + + core::BuiltinFn fn = core::BuiltinFn::kTextureSample; + if (HasBias(operand_mask)) { + fn = core::BuiltinFn::kTextureSampleBias; + new_args.Push(args[idx++]); + } + if (HasLod(operand_mask)) { + fn = core::BuiltinFn::kTextureSampleLevel; + + core::ir::Value* lod = args[idx++]; + + // Depth texture LOD in WGSL is i32/u32 but f32 in SPIR-V. + // Convert to i32 + if (tex_ty->Is()) { + lod = b.Convert(ty.i32(), lod)->Result(); + } + new_args.Push(lod); + } + if (HasGrad(operand_mask)) { + fn = core::BuiltinFn::kTextureSampleGrad; + new_args.Push(args[idx++]); // ddx + new_args.Push(args[idx++]); // ddy + } + if (HasConstOffset(operand_mask)) { + ProcessOffset(args[idx++], new_args); + } + + // Depth textures have a single value return in WGSL, but a vec4 in SPIR-V. + auto* call_ty = call->Result()->Type(); + if (tex_ty->IsAnyOf()) { + call_ty = call_ty->DeepestElement(); + } + auto* res = b.Call(call_ty, fn, new_args)->Result(); + + // Restore the vec4 result by padding with 0's. + if (call_ty != call->Result()->Type()) { + auto* vec = call->Result()->Type()->As(); + TINT_ASSERT(vec && vec->Width() == 4); + + auto* z = b.Zero(call_ty); + res = b.Construct(call->Result()->Type(), res, z, z, z)->Result(); + } + + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + void ImageWrite(spirv::ir::BuiltinCall* call) { + const auto& args = call->Args(); + + b.InsertBefore(call, [&] { + core::ir::Value* tex = args[0]; + auto* coords = args[1]; + auto* texel = args[2]; + + Vector new_args; + new_args.Push(tex); + + ProcessCoords(tex->Type(), false, coords, new_args); + + new_args.Push(texel); + + b.Call(call->Result()->Type(), core::BuiltinFn::kTextureStore, new_args); + }); + call->Destroy(); + } + + void ImageQuery(spirv::ir::BuiltinCall* call, core::BuiltinFn fn) { + auto* image = call->Args()[0]; + + b.InsertBefore(call, [&] { + auto* type = call->Result()->Type(); + + // WGSL requires a `u32` result component where SPIR-V allows `i32` or `u32` + core::ir::Value* res = + b.Call(ty.MatchWidth(ty.u32(), type), fn, Vector{image})->Result(); + if (type->IsSignedIntegerScalarOrVector()) { + res = b.Convert(type, res)->Result(); + } + + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + void ImageQuerySize(spirv::ir::BuiltinCall* call) { + auto* image = call->Args()[0]; + + auto* tex_ty = image->Type()->As(); + TINT_ASSERT(tex_ty); + + b.InsertBefore(call, [&] { + auto* type = call->Result()->Type(); + + // WGSL requires a `u32` result component where SPIR-V allows `i32` or `u32` + auto* wgsl_type = ty.MatchWidth(ty.u32(), type); + + // A SPIR-V OpImageQuery will return the array `element` entry with + // the image query. In WGSL, these are two calls, the + // `textureDimensions` will get the width,height,depth but we also + // have to call `textureNumLayers` to get the elements and then + // re-inject that back into the result. + if (core::type::IsTextureArray(tex_ty->Dim())) { + wgsl_type = ty.vec(ty.u32(), wgsl_type->As()->Width() - 1); + } + + Vector args = {image}; + if (call->Func() == spirv::BuiltinFn::kImageQuerySizeLod) { + args.Push(call->Args()[1]); + } + + core::ir::Value* res = + b.Call(wgsl_type, core::BuiltinFn::kTextureDimensions, args)->Result(); + + if (core::type::IsTextureArray(tex_ty->Dim())) { + core::ir::Value* layers = + b.Call(ty.u32(), core::BuiltinFn::kTextureNumLayers, image)->Result(); + res = b.Construct(ty.MatchWidth(ty.u32(), type), res, layers)->Result(); + } + + if (type->IsSignedIntegerScalarOrVector()) { + res = b.Convert(type, res)->Result(); + } + + call->Result()->ReplaceAllUsesWith(res); + }); + call->Destroy(); + } + + const core::type::Type* TypeFor(const core::type::Type* src_ty) { + if (auto* img = src_ty->As()) { + return TypeForImage(img); + } + return src_ty; + } + + core::type::TextureDimension ConvertDim(spirv::type::Dim dim, spirv::type::Arrayed arrayed) { + switch (dim) { + case spirv::type::Dim::kD1: + return core::type::TextureDimension::k1d; + case spirv::type::Dim::kD2: + return arrayed == spirv::type::Arrayed::kArrayed + ? core::type::TextureDimension::k2dArray + : core::type::TextureDimension::k2d; + case spirv::type::Dim::kD3: + return core::type::TextureDimension::k3d; + case spirv::type::Dim::kCube: + return arrayed == spirv::type::Arrayed::kArrayed + ? core::type::TextureDimension::kCubeArray + : core::type::TextureDimension::kCube; + default: + TINT_UNREACHABLE(); + } + } + + const core::type::Type* TypeForImage(const spirv::type::Image* img) { + if (img->GetDim() == spirv::type::Dim::kSubpassData) { + return ty.input_attachment(img->GetSampledType()); + } + + if (img->GetSampled() == spirv::type::Sampled::kReadWriteOpCompatible) { + return ty.storage_texture(ConvertDim(img->GetDim(), img->GetArrayed()), + img->GetTexelFormat(), img->GetAccess()); + } + + if (img->GetDepth() == spirv::type::Depth::kDepth) { + if (img->GetMultisampled() == spirv::type::Multisampled::kMultisampled) { + return ty.depth_multisampled_texture(ConvertDim(img->GetDim(), img->GetArrayed())); + } + return ty.depth_texture(ConvertDim(img->GetDim(), img->GetArrayed())); + } + + if (img->GetMultisampled() == spirv::type::Multisampled::kMultisampled) { + return ty.multisampled_texture(ConvertDim(img->GetDim(), img->GetArrayed()), + img->GetSampledType()); + } + + return ty.sampled_texture(ConvertDim(img->GetDim(), img->GetArrayed()), + img->GetSampledType()); + } +}; + +} // namespace + +Result Texture(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.Texture", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowPointerToHandle, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.h new file mode 100644 index 000000000..677b90d2d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/texture.h @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_TEXTURE_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_TEXTURE_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// Texture is a transform that converts SPIR-V image types and methods into the form expected by +/// Tint's core IR. +/// @param module the module to transform +/// @returns success or failure +Result Texture(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_TEXTURE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.cc new file mode 100644 index 000000000..898383553 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.cc @@ -0,0 +1,773 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/transpose_row_major.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/spirv/type/explicit_layout_array.h" + +namespace tint::spirv::reader::lower { +namespace { + +using namespace tint::core::fluent_types; // NOLINT + +constexpr std::string_view kTintLoadRowMajor = "tint_load_row_major_column"; +constexpr std::string_view kTintTransposeRowMajorArray = "tint_transpose_row_major_array"; +constexpr std::string_view kTintStoreRowMajor = "tint_store_row_major_column"; + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol manager. + SymbolTable& sym{ir.symbols}; + + // A map from a (type, is_row_major) pair to it's replacement (which maybe the same as the + // original). + struct TypeAndRowMajor { + const core::type::Type* type; + bool row_major; + + bool operator==(const TypeAndRowMajor& other) const { + return type == other.type && row_major == other.row_major; + } + + tint::HashCode HashCode() const { return Hash(type, row_major); } + }; + Hashmap original_to_transposed{}; + + /// A map from rewritten structs to original structs. + Hashmap struct_to_original{}; + + /// List of instruction results where the usages need to be updated + Vector results_to_update{}; + + /// A hash of access instructions to the vector index they were accessing + Hashmap access_to_vector_index{}; + + /// A list of instructions to remove + Vector instructions_to_remove_if_unused{}; + + /// A map of type to the load helper + Hashmap load_functions{}; + + /// A map of type to the store helper + Hashmap store_functions{}; + + /// Instructions which have been processed + Hashset processed_instructions{}; + + /// Process the module. + void Process() { + Vector instructions_to_process; + for (auto* inst : ir.Instructions()) { + // Replace all constant operands where the type will be changed due to it containing a + // structure that uses a row-major attribute. + for (uint32_t i = 0; i < inst->Operands().Length(); ++i) { + if (auto* constant = As(inst->Operands()[i])) { + auto* new_constant = RewriteConstant(constant->Value(), false); + if (new_constant != constant->Value()) { + inst->SetOperand(i, b.Constant(new_constant)); + } + } + } + + for (auto* res : inst->Results()) { + auto* new_ty = RewriteType(res->Type(), false); + if (new_ty != res->Type()) { + res->SetType(new_ty); + instructions_to_process.Push(inst); + results_to_update.Push(res); + } + } + } + for (auto inst : instructions_to_process) { + ProcessInstruction(inst); + } + + while (!results_to_update.IsEmpty()) { + auto* result = results_to_update.Pop(); + + if (!processed_instructions.Add(result)) { + continue; + } + + // It's possible we've already processed this instruction because we're working through + // results, so if it isn't alive, then we've already replaced it and we can move on. + if (!result->Alive()) { + continue; + } + + // Use sorted usages to force a copy, the replacements may create new usages of this + // result. + for (auto& usage : result->UsagesSorted()) { + ProcessInstruction(usage.instruction); + } + } + + for (auto* inst : instructions_to_remove_if_unused) { + // If we've detached, just remove the instruction + if (inst->Results().IsEmpty()) { + inst->Destroy(); + continue; + } + + TINT_ASSERT(inst->Results().Length() == 1); + if (!inst->Result()->IsUsed()) { + inst->Destroy(); + } + } + } + + void ProcessInstruction(core::ir::Instruction* inst) { + tint::Switch( + inst, // + [&](core::ir::Var*) { + // Nothing to do as we already substituted the type. + }, + [&](core::ir::Let*) { + // Nothing to do as we already substituted the type. + }, + + [&](core::ir::Load* ld) { ReplaceLoad(ld); }, + [&](core::ir::Store* store) { ReplaceStore(store); }, + [&](core::ir::Access* access) { ReplaceAccess(access); }, + [&](core::ir::Construct* construct) { ReplaceConstruct(construct); }, + [&](core::ir::LoadVectorElement* lve) { ReplaceLoadVectorElement(lve); }, + [&](core::ir::StoreVectorElement* sve) { ReplaceStoreVectorElement(sve); }, + TINT_ICE_ON_NO_MATCH); + } + + void ReplaceConstruct(core::ir::Construct* construct) { + auto* struct_type = construct->Result()->Type()->As(); + if (!struct_type) { + return; + } + + b.InsertBefore(construct, [&] { + Vector new_operands; + for (uint32_t i = 0; i < construct->Operands().Length(); i++) { + auto* operand = construct->Operands()[i]; + auto* member_type = struct_type->Members()[i]->Type(); + if (member_type != operand->Type()) { + tint::Switch( + member_type, + [&](const core::type::Matrix*) { + new_operands.Push( + b.Call(member_type, core::BuiltinFn::kTranspose, operand) + ->Result()); + }, + [&](const core::type::Array*) { + // TODO(437140112): Add support for arrays of matrices + TINT_UNIMPLEMENTED() << "handle construct of array of matrices"; + }, + TINT_ICE_ON_NO_MATCH); + } else { + new_operands.Push(operand); + } + } + construct->SetOperands(new_operands); + }); + } + + // This is a store vector element that is going to a matrix which we've transposed the size of. + // So, we need to swap the index on this store with the last index of the source access. + void ReplaceStoreVectorElement(core::ir::StoreVectorElement* sve) { + auto* src_to = sve->To()->As(); + TINT_ASSERT(src_to); + + auto* src_access = src_to->Instruction()->As(); + TINT_ASSERT(src_access); + + auto access_idx = access_to_vector_index.Get(sve->To()); + TINT_ASSERT(access_idx); + + core::ir::Access* new_access = nullptr; + b.InsertAfter(src_access, [&] { + auto* src_ty = src_to->Type()->As(); + TINT_ASSERT(src_ty); + + auto* src_mat = src_ty->StoreType()->As(); + TINT_ASSERT(src_mat); + + auto* new_ptr = + ty.ptr(src_ty->AddressSpace(), ty.vec(src_mat->Type(), src_mat->Rows())); + new_access = b.Access(new_ptr, src_access, Vector{sve->Index()}); + + b.InsertAfter(sve, + [&] { b.StoreVectorElement(new_access, *access_idx, sve->Value()); }); + sve->Destroy(); + }); + + instructions_to_remove_if_unused.Push(src_access); + } + + // This is a load vector element that is coming from a matrix which we've transposed the size + // of. So, we need to swap the index on this load with the last index of the source access. + void ReplaceLoadVectorElement(core::ir::LoadVectorElement* lve) { + auto* src_result = lve->From()->As(); + TINT_ASSERT(src_result); + + auto* src_access = src_result->Instruction()->As(); + TINT_ASSERT(src_access); + + auto access_idx = access_to_vector_index.Get(lve->From()); + TINT_ASSERT(access_idx); + + core::ir::Access* new_access = nullptr; + b.InsertAfter(src_access, [&] { + auto* src_ty = src_result->Type()->As(); + TINT_ASSERT(src_ty); + + auto* src_mat = src_ty->StoreType()->As(); + TINT_ASSERT(src_mat); + + auto* new_ptr = + ty.ptr(src_ty->AddressSpace(), ty.vec(src_mat->Type(), src_mat->Rows())); + new_access = b.Access(new_ptr, src_access, Vector{lve->Index()}); + + b.InsertAfter(lve, [&] { + b.LoadVectorElementWithResult(lve->DetachResult(), new_access, *access_idx); + }); + lve->Destroy(); + }); + + instructions_to_remove_if_unused.Push(src_access); + } + + void ReplaceAccess(core::ir::Access* access) { + bool indexed_through_row_major = false; + + auto* cur_ty = access->Object()->Type()->UnwrapPtr(); + const core::type::Type* parent_ty = nullptr; + const core::type::Matrix* mat_ty = nullptr; + auto indices = access->Indices(); + int32_t matrix_index = -1; + for (uint32_t i = 0; i < indices.Length(); ++i) { + auto* idx = indices[i]; + + if (auto* struct_ty = cur_ty->As()) { + auto const_idx = idx->As()->Value()->ValueAs(); + parent_ty = cur_ty; + cur_ty = cur_ty->Element(const_idx); + + auto* orig_struct = struct_to_original.GetOr(struct_ty, nullptr); + if (!orig_struct) { + // Structure didn't change, so doesn't contain a row-major member + continue; + } + + auto* mem = orig_struct->Members()[const_idx]; + if (mem->RowMajor()) { + indexed_through_row_major = true; + } + + } else { + parent_ty = cur_ty; + cur_ty = cur_ty->Elements().type; + } + + // We do this at the end because we want the index that we load the matrix from, so the + // next thing we look at would be the matrix. + if (cur_ty->Is()) { + TINT_ASSERT(matrix_index == -1); + mat_ty = cur_ty->As(); + matrix_index = int32_t(i); + } + } + + // The matrix is in an array and we're dealing with the array. We'll need to handle the + // array when we load/store it, so add the access to the results to update. + if (cur_ty->Is()) { + ReplacePointerAccess(access, parent_ty, cur_ty); + results_to_update.Push(access->Result()); + return; + } + + // The thing we're accessing has changed, so we need to change. + if (!indexed_through_row_major && cur_ty != access->Result()->Type()->UnwrapPtr()) { + ReplacePointerAccess(access, parent_ty, cur_ty); + return; + } + + // If we don't have a matrix index we need to update, then we've updated the `var` type + // we're accessing but we're accessing another member of the struct, so we're done. + if (matrix_index == -1) { + return; + } + + // Not accessing through a matrix, nothing to do. + if (!indexed_through_row_major) { + return; + } + + if (access->Object()->Type()->Is()) { + ReplacePointerAccess(access, parent_ty, cur_ty); + return; + } + + // This isn't a pointer access, so we'll just split the access in half, transpose the + // matrix itself and then access that matrix with the rest of the expression. + + Vector mat_indices = indices.Truncate(size_t(matrix_index) + 1); + + b.InsertBefore(access, [&] { + auto* m = b.Access(mat_ty, access->Object(), mat_indices); + auto* t = b.Call(RewriteType(mat_ty, true), core::BuiltinFn::kTranspose, m)->Result(); + + if (uint32_t(matrix_index) != indices.Length() - 1) { + Vector access_indices = + indices.Offset(size_t(matrix_index) + 1); + b.AccessWithResult(access->DetachResult(), t, access_indices)->Result(); + } else { + access->Result()->ReplaceAllUsesWith(t); + } + }); + access->Destroy(); + } + + void ReplacePointerAccess(core::ir::Access* access, + const core::type::Type* parent_ty, + const core::type::Type* cur_ty) { + // We've accessed the matrix itself, or an array containing the matrix. We need to update + // the access result type, and if changed, update the uses of this access + if (cur_ty->Is() || cur_ty->Is()) { + auto* new_access_ty = RewriteType(access->Result()->Type(), true); + if (new_access_ty != access->Result()->Type()) { + access->Result()->SetType(new_access_ty); + results_to_update.Push(access->Result()); + } + return; + } + + // We're accessing a row of the vector. We need to replace this access with an access of + // the parent matrix and then store away which row we're accessing so we can rebuild any + // needed accesses later. + if (cur_ty->Is()) { + TINT_ASSERT(parent_ty != nullptr); + auto* idx = access->PopLastIndex(); + + /// The access now returns the transposed matrix + auto* new_access_ty = access->Result()->Type(); + if (auto* access_ptr = access->Result()->Type()->As()) { + new_access_ty = ty.ptr(access_ptr->AddressSpace(), parent_ty, access_ptr->Access()); + } + access->Result()->SetType(new_access_ty); + + access_to_vector_index.Add(access->Result(), idx); + results_to_update.Push(access->Result()); + return; + } + + TINT_UNREACHABLE() << "access of unknown type for row-major matrix"; + } + + void ReplaceLoad(core::ir::Load* ld) { + auto* ld_ty = ld->Result()->Type(); + + tint::Switch( + ld_ty, // + [&](const core::type::Matrix*) { + b.InsertAfter(ld, [&] { + // We're replacing the load, which means the source must have been a transposed + // matrix, so we need to get the load result as if it was row-major decorated. + auto* new_res = b.InstructionResult(RewriteType(ld->Result()->Type(), true)); + b.CallWithResult(ld->DetachResult(), core::BuiltinFn::kTranspose, new_res); + ld->SetResult(new_res); + }); + }, + [&](const core::type::Vector*) { + auto idx = access_to_vector_index.Get(ld->From()); + TINT_ASSERT(idx); + + if (idx) { + // We're loading a vector from an access chain, we need to determine if this + // vector came from a row-major matrix + auto* load_fn = LoadColumnHelper(ld->From()->Type()->As()); + b.InsertAfter(ld, [&] { + auto* v = *idx; + if (v->Type()->Is()) { + v = b.Convert(ty.u32(), v)->Result(); + } + b.CallWithResult(ld->DetachResult(), load_fn, ld->From(), v); + }); + + // Do this after we're done so we don't end up modifying the usage list of the + // result we're iterating over. + instructions_to_remove_if_unused.Push(ld); + + } else { + TINT_UNREACHABLE() << "attempting to load a row-major vector?"; + } + }, + [&](const core::type::Struct*) { + // Handled elsewhere + }, + [&](const core::type::Array*) { + // We're replacing the load, which means the source must have been a transposed + // array of matrix. + auto* load_fn = TransposeArrayHelper(ld->From()->Type()->UnwrapPtr()); + b.InsertAfter(ld, [&] { + auto* new_ld = b.Load(ld->From()); + b.CallWithResult(ld->DetachResult(), load_fn, new_ld); + }); + + // Do this after we're done so we don't end up modifying the usage list of the + // result we're iterating over. + instructions_to_remove_if_unused.Push(ld); + }, + TINT_ICE_ON_NO_MATCH); + } + + void ReplaceStore(core::ir::Store* store) { + auto vec_idx = access_to_vector_index.Get(store->To()); + + auto* to_ty = store->To()->Type()->UnwrapPtr(); + if (!vec_idx) { + tint::Switch( + to_ty, // + [&](const core::type::Matrix*) { + // Storing the full matrix + b.InsertBefore(store, [&] { + auto* from = b.Call(to_ty, core::BuiltinFn::kTranspose, store->From()); + store->SetFrom(from->Result()); + }); + }, + [&](const core::type::Array*) { + b.InsertBefore(store, [&] { + auto* from = store->From(); + if (from->Type()->Is()) { + from = b.Load(from)->Result(); + } + auto* fn = TransposeArrayHelper(from->Type()); + store->SetFrom(b.Call(to_ty, fn, from)->Result()); + }); + }, + [&](const core::type::Struct*) { + // Should already be fixed + }, + TINT_ICE_ON_NO_MATCH); + return; + } + + // Storing a vector + auto* store_fn = StoreColumnHelper(store->To()->Type()->As()); + b.InsertAfter(store, [&] { + auto* v = *vec_idx; + if (v->Type()->Is()) { + v = b.Convert(ty.u32(), v)->Result(); + } + + b.Call(ty.void_(), store_fn, store->To(), v, store->From()); + }); + instructions_to_remove_if_unused.Push(store); + } + + // Note, the type provided in the pointer has _already_ been transposed. + core::ir::Function* StoreColumnHelper(const core::type::Pointer* ptr) { + return store_functions.GetOrAdd(ptr, [&] { + TINT_ASSERT(ptr); + + auto* row_major_ty = ptr->UnwrapPtr()->As(); + TINT_ASSERT(row_major_ty); + + auto* vec_ty = ty.vec(row_major_ty->Type(), row_major_ty->Columns()); + auto* col_ptr_ty = + ty.ptr(ptr->AddressSpace(), ty.vec(row_major_ty->Type(), row_major_ty->Rows()), + ptr->Access()); + + auto* fn = b.Function(kTintStoreRowMajor, ty.void_()); + auto* mat = b.FunctionParam(ptr); + auto* row = b.FunctionParam(ty.u32()); + auto* col = b.FunctionParam(vec_ty); + fn->SetParams({mat, row, col}); + + b.Append(fn->Block(), [&] { + for (uint32_t i = 0; i < row_major_ty->Columns(); ++i) { + auto* col_access = b.Access(vec_ty->DeepestElement(), col, u32(i)); + b.StoreVectorElement(b.Access(col_ptr_ty, mat, u32(i)), row, col_access); + } + b.Return(fn); + }); + return fn; + }); + } + + // Note, the type provided in the pointer has _already_ been transposed. + core::ir::Function* LoadColumnHelper(const core::type::Pointer* ptr) { + return load_functions.GetOrAdd(ptr, [&] { + TINT_ASSERT(ptr); + + auto* row_major_ty = ptr->UnwrapPtr()->As(); + TINT_ASSERT(row_major_ty); + + auto* vec_ty = ty.vec(row_major_ty->Type(), row_major_ty->Columns()); + auto* col_ptr_ty = + ty.ptr(ptr->AddressSpace(), ty.vec(row_major_ty->Type(), row_major_ty->Rows()), + ptr->Access()); + + auto* fn = b.Function(kTintLoadRowMajor, vec_ty); + auto* mat = b.FunctionParam(ptr); + auto* row = b.FunctionParam(ty.u32()); + fn->SetParams({mat, row}); + + b.Append(fn->Block(), [&] { + Vector values; + for (uint32_t i = 0; i < row_major_ty->Columns(); ++i) { + values.Push( + b.LoadVectorElement(b.Access(col_ptr_ty, mat, u32(i)), row)->Result()); + } + b.Return(fn, b.Construct(vec_ty, values)); + }); + return fn; + }); + } + + core::ir::Function* TransposeArrayHelper(const core::type::Type* in_type) { + // The helper function will look like this: + // fn tint_transpose_array(from: array, 4>) -> array, 4> { + // var result : array, 4>; + // for (var i = 0; i < 4; i++) { + // result[i] = transpose(from[i]); + // } + // return result; + // } + TINT_ASSERT(in_type); + + return load_functions.GetOrAdd(in_type, [&] { + auto* outer_ty = in_type->As(); + TINT_ASSERT(outer_ty); + + auto* from_ty = outer_ty; + auto* to_ty = RewriteType(in_type, true)->As(); + TINT_ASSERT(from_ty); + + auto* fn = b.Function(kTintTransposeRowMajorArray, to_ty); + auto* in = b.FunctionParam(in_type); + fn->SetParams({in}); + + auto count = from_ty->ConstantCount(); + + b.Append(fn->Block(), [&] { + auto* res = b.Var(ty.ptr(function, to_ty)); + b.LoopRange(u32(0), u32(*count), u32(1), [&](core::ir::Value* idx) { + core::ir::Value* transposed = nullptr; + auto* cur = b.Access(from_ty->ElemType(), in, idx); + if (auto* nested = outer_ty->ElemType()->As()) { + auto* inner_fn = TransposeArrayHelper(nested); + transposed = b.Call(to_ty->ElemType(), inner_fn, cur)->Result(); + } else { + transposed = + b.Call(to_ty->ElemType(), core::BuiltinFn::kTranspose, cur)->Result(); + } + + auto* slot = b.Access(ty.ptr(function, to_ty->ElemType()), res, idx); + b.Store(slot, transposed); + }); + auto* ld = b.Load(res); + b.Return(fn, ld); + }); + + return fn; + }); + } + + const core::type::Type* RewriteType(const core::type::Type* type, bool decorated_row_major) { + return original_to_transposed.GetOrAdd(TypeAndRowMajor{type, decorated_row_major}, [&] { + return tint::Switch( + type, + [&](const core::type::Array* arr) { + return RewriteArray(arr, decorated_row_major); + }, + [&](const core::type::Struct* str) { return RewriteStruct(str); }, + [&](const core::type::Matrix* mat) { + if (!decorated_row_major) { + return mat; + } + return ty.mat(mat->Type(), mat->Rows(), mat->Columns()); + }, + [&](const core::type::Pointer* ptr) { + return ty.ptr(ptr->AddressSpace(), + RewriteType(ptr->StoreType(), decorated_row_major), + ptr->Access()); + }, + [&](Default) { return type; }); + }); + } + + const core::type::Type* RewriteArray(const core::type::Array* arr, bool decorated_row_major) { + auto* elem_ty = RewriteType(arr->ElemType(), decorated_row_major); + if (elem_ty == arr->ElemType()) { + return arr; + } + + // The element type is the only thing that will change. That does not affect the stride of + // the array itself, which may either be the natural stride or an larger stride in the case + // of an explicitly laid out array. + if (auto* ex = arr->As()) { + return ty.Get(elem_ty, arr->Count(), arr->Size(), + ex->Stride()); + } + return ty.Get(elem_ty, arr->Count(), arr->Size()); + } + + const core::type::Type* RewriteStruct(const core::type::Struct* old_struct) { + bool made_changes = false; + + Vector new_members; + new_members.Reserve(old_struct->Members().Length()); + for (auto* member : old_struct->Members()) { + auto* new_member_type = RewriteType(member->Type(), member->RowMajor()); + if (member->RowMajor() || new_member_type != member->Type()) { + // Recreate the struct member without the row major attribute, using the new type. + auto* new_member = ty.Get( + member->Name(), new_member_type, member->Index(), member->Offset(), + member->Align(), member->Size(), member->Attributes()); + if (member->HasMatrixStride()) { + new_member->SetMatrixStride(member->MatrixStride()); + } + new_members.Push(new_member); + made_changes = true; + } else { + new_members.Push(member); + } + } + if (!made_changes) { + return old_struct; + } + + // Create the new struct and record the mapping to the old struct. + auto* new_struct = ty.Struct(sym.New(old_struct->Name().Name()), std::move(new_members)); + struct_to_original.Add(new_struct, old_struct); + + return new_struct; + } + + const core::constant::Value* RewriteConstant(const core::constant::Value* constant, + bool is_row_major) { + auto* orig_type = constant->Type(); + auto* new_type = RewriteType(orig_type, is_row_major); + if (new_type == orig_type) { + return constant; + } + + return tint::Switch( + new_type, // + [&](const core::type::Matrix* mat) { + if (!is_row_major) { + return constant; + } + + auto* orig_mat = orig_type->As(); + TINT_ASSERT(orig_mat); + TINT_ASSERT(constant->NumElements() == mat->Rows()); + + Vector columns; + for (size_t i = 0; i < mat->Columns(); ++i) { + auto* vec_ty = ty.vec(mat->Type(), mat->Rows()); + + Vector vec_elements; + for (uint32_t j = 0; j < mat->Rows(); ++j) { + auto* value = constant->Index(j); + TINT_ASSERT(value->NumElements() == mat->Columns()); + vec_elements.Push(value->Index(i)); + } + columns.Push(ir.constant_values.Composite(vec_ty, std::move(vec_elements))); + } + + return ir.constant_values.Composite(new_type, std::move(columns)); + }, + [&](const core::type::Array*) { + if (!is_row_major) { + return constant; + } + + Vector elements; + for (uint32_t i = 0; i < constant->NumElements(); i++) { + auto* value = constant->Index(i); + elements.Push(RewriteConstant(value, is_row_major)); + } + return ir.constant_values.Composite(new_type, std::move(elements)); + }, + [&](const core::type::Struct* str) { + TINT_ASSERT(constant->NumElements() == str->Members().Length()); + + Vector elements; + elements.Reserve(str->Members().Length()); + + auto* orig_str = orig_type->As(); + TINT_ASSERT(orig_str); + + for (size_t i = 0; i < orig_str->Members().Length(); ++i) { + auto& orig_mem = orig_str->Members()[i]; + auto& new_mem = str->Members()[i]; + auto* value = constant->Index(i); + + auto* new_member_type = new_mem->Type(); + if (new_member_type != value->Type()) { + elements.Push(RewriteConstant(value, orig_mem->RowMajor())); + } else { + elements.Push(value); + } + } + return ir.constant_values.Composite(new_type, std::move(elements)); + }, + [&](Default) { return constant; }); + } +}; + +} // namespace + +Result TransposeRowMajor(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.TransposeRowMajor", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowStructMatrixDecorations, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPointerToHandle, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.h new file mode 100644 index 000000000..ae1b88ee0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/transpose_row_major.h @@ -0,0 +1,49 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_TRANSPOSE_ROW_MAJOR_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_TRANSPOSE_ROW_MAJOR_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// TransposeRowMajor is a transform that converts matrices with the `RowMajor` attribute +/// to column major matrices. The access and types are updated as needed due to the +/// transposition. +/// @param module the module to transform +/// @returns success or failure +Result TransposeRowMajor(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_TRANSPOSE_ROW_MAJOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc new file mode 100644 index 000000000..adb690911 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc @@ -0,0 +1,176 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/lower/vector_element_pointer.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +namespace tint::spirv::reader::lower { + +namespace { + +using namespace tint::core::fluent_types; // NOLINT + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Access is an access instruction and the type of the vector that it produces a pointer to. + struct Access { + /// The access instruction. + core::ir::Access* inst; + /// The vector type being accessed. + const core::type::Type* type; + }; + + /// Process the module. + void Process() { + // Find the access instructions that need to be replaced. + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* access = inst->As()) { + auto* source_ty = access->Object()->Type(); + if (!source_ty->Is()) { + continue; + } + source_ty = source_ty->UnwrapPtr(); + + // Step through the indices of the access instruction to check for vector types. + for (auto* idx : access->Indices()) { + if (source_ty->Is()) { + // Found an access that is indexing into a vector pointer. + worklist.Push(Access{access, source_ty}); + break; + } + + // Update the current source type based on the next index. + if (auto* constant = idx->As()) { + auto i = constant->Value()->ValueAs(); + source_ty = source_ty->Element(i); + } else { + source_ty = source_ty->Elements().type; + } + } + } + } + + // Replace the access instructions that we found. + for (const auto& access : worklist) { + ReplaceAccess(access); + } + } + + /// Replace an access instruction with {load,store}_vector_element instructions. + /// @param access the access instruction to replace + void ReplaceAccess(const Access& access) { + auto* object = access.inst->Object(); + + if (access.inst->Indices().Length() > 1) { + // Create a new access instruction that stops at the vector pointer. + Vector partial_indices{access.inst->Indices()}; + partial_indices.Pop(); + + auto* ptr = object->Type()->As(); + auto addrspace = ptr->AddressSpace(); + auto* access_to_vec = + b.Access(ty.ptr(addrspace, access.type, ptr->Access()), object, partial_indices); + access_to_vec->InsertBefore(access.inst); + + object = access_to_vec->Result(); + } + + // Replace all uses of the original access instruction. + auto* index = access.inst->Indices().Back(); + ReplaceAccessUses(access.inst, object, index); + + // Destroy the original access instruction. + access.inst->Destroy(); + } + + /// Replace all uses of an access instruction with {load,store}_vector_element instructions. + /// @param access the access instruction to replace + /// @param object the pointer-to-vector source object + /// @param index the index of the vector element + void ReplaceAccessUses(core::ir::Access* access, + core::ir::Value* object, + core::ir::Value* index) { + Vector to_destroy; + access->Result()->ForEachUseUnsorted([&](core::ir::Usage use) { + Switch( + use.instruction, + [&](core::ir::Load* load) { + auto* lve = b.LoadVectorElementWithResult(load->DetachResult(), object, index); + lve->InsertBefore(load); + to_destroy.Push(load); + }, + [&](core::ir::Store* store) { + auto* sve = b.StoreVectorElement(object, index, store->From()); + sve->InsertBefore(store); + to_destroy.Push(store); + }, + TINT_ICE_ON_NO_MATCH); + }); + + // Clean up old instructions. + for (auto* inst : to_destroy) { + inst->Destroy(); + } + } +}; + +} // namespace + +Result VectorElementPointer(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.VectorElementPointer", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowVectorElementPointer, + core::ir::Capability::kAllowPhonyInstructions, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllowStructMatrixDecorations, + core::ir::Capability::kAllowLocationForNumericElements, + core::ir::Capability::kAllowPointerToHandle, + core::ir::Capability::kLoosenValidationForShaderIO, + })); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::reader::lower diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.h b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.h new file mode 100644 index 000000000..397c71045 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/lower/vector_element_pointer.h @@ -0,0 +1,48 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_LOWER_VECTOR_ELEMENT_POINTER_H_ +#define SRC_TINT_LANG_SPIRV_READER_LOWER_VECTOR_ELEMENT_POINTER_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader::lower { + +/// VectorElementPointer is a transform that removes pointers to vector elements by replacing access +/// instructions and their uses. +/// @param module the module to transform +/// @returns success or failure +Result VectorElementPointer(core::ir::Module& module); + +} // namespace tint::spirv::reader::lower + +#endif // SRC_TINT_LANG_SPIRV_READER_LOWER_VECTOR_ELEMENT_POINTER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.cc new file mode 100644 index 000000000..56314a23e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.cc @@ -0,0 +1,4657 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/parser/parser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPV_ENABLE_UTILITY_CODE +#include "spirv/unified1/spirv.hpp11" + +// This header is in an external dependency, so warnings cannot be fixed without upstream changes. +TINT_BEGIN_DISABLE_WARNING(NEWLINE_EOF); +TINT_BEGIN_DISABLE_WARNING(OLD_STYLE_CAST); +TINT_BEGIN_DISABLE_WARNING(SIGN_CONVERSION); +TINT_BEGIN_DISABLE_WARNING(WEAK_VTABLES); +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +#include "source/opt/build_module.h" +#include "source/opt/resolve_binding_conflicts_pass.h" +#include "source/opt/split_combined_image_sampler_pass.h" +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +TINT_END_DISABLE_WARNING(WEAK_VTABLES); +TINT_END_DISABLE_WARNING(SIGN_CONVERSION); +TINT_END_DISABLE_WARNING(OLD_STYLE_CAST); +TINT_END_DISABLE_WARNING(NEWLINE_EOF); + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/referenced_module_vars.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/spirv/builtin_fn.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/lang/spirv/type/explicit_layout_array.h" +#include "src/tint/lang/spirv/type/image.h" +#include "src/tint/lang/spirv/type/sampled_image.h" +#include "src/tint/lang/spirv/validate/validate.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::reader { + +namespace { + +// Stores information for operands which need to be calculated after a block is complete. Because +// a phi can store values which come after it, we can't calculate the value when the `OpPhi` is +// seen. +struct ReplacementValue { + // The terminator instruction the operand belongs to + core::ir::Terminator* terminator; + // The operand index in `terminator` to replace + uint32_t idx; + // The SPIR-V value id to create the value from + uint32_t value_id; +}; + +/// The SPIR-V environment that we validate against. +constexpr auto kTargetEnv = SPV_ENV_VULKAN_1_1; + +/// PIMPL class for SPIR-V parser. +/// Validates the SPIR-V module and then parses it to produce a Tint IR module. +class Parser { + public: + explicit Parser(const Options& options) : options_(options) {} + ~Parser() = default; + + /// @param spirv the SPIR-V binary data + /// @returns the generated SPIR-V IR module on success, or failure + Result Run(Slice spirv) { + // Validate the incoming SPIR-V binary. + TINT_CHECK_RESULT(validate::Validate(spirv, kTargetEnv)); + + // Build the SPIR-V tools internal representation of the SPIR-V module. + spvtools::Context context(kTargetEnv); + spirv_context_ = + spvtools::BuildModule(kTargetEnv, context.CContext()->consumer, spirv.data, spirv.len); + if (!spirv_context_) { + return Failure("failed to build the internal representation of the module"); + } + + // Run SPIR-V opt transforms to make the input friendlier for the SPIR-V frontend. + { + spvtools::opt::SplitCombinedImageSamplerPass pass; + auto status = pass.Run(spirv_context_.get()); + if (status == spvtools::opt::Pass::Status::Failure) { + return Failure("failed to run SplitCombinedImageSamplerPass in SPIR-V opt"); + } + } + if (options_.sampler_mappings.empty()) { + spvtools::opt::ResolveBindingConflictsPass pass; + auto status = pass.Run(spirv_context_.get()); + if (status == spvtools::opt::Pass::Status::Failure) { + return Failure("failed to run ResolveBindingConflictsPass in SPIR-V opt"); + } + } + + // Check for unsupported extensions. + for (const auto& ext : spirv_context_->extensions()) { + auto name = ext.GetOperand(0).AsString(); + if (name != "SPV_KHR_storage_buffer_storage_class" && + name != "SPV_KHR_non_semantic_info" && // + name != "SPV_KHR_16bit_storage" && // + name != "SPV_KHR_terminate_invocation" && // + // TODO(423644565): We assume the barriers are correct. We should check for any + // operation that makes barrier assumptions that aren't consistent with WGSL and + // generate the needed barriers. + name != "SPV_KHR_vulkan_memory_model") { + return Failure("SPIR-V extension '" + name + "' is not supported"); + } + } + + // Register imported instruction sets + for (const auto& import : spirv_context_->ext_inst_imports()) { + auto name = import.GetInOperand(0).AsString(); + + if (name == "GLSL.std.450") { + glsl_std_450_imports_.insert(import.result_id()); + } else if (name.find("NonSemantic.") == 0) { + ignored_imports_.insert(import.result_id()); + } else { + return Failure("Unrecognized extended instruction set: " + name); + } + } + + RegisterNames(); + + id_stack_.emplace_back(); + { + TINT_SCOPED_ASSIGNMENT(current_block_, ir_.root_block); + EmitSpecConstants(); + EmitModuleScopeVariables(); + } + + EmitFunctions(); + EmitEntryPointAttributes(); + + RemapSamplers(); + RemapBufferBlockAddressSpace(); + AddRefToOutputsIfNeeded(); + + return std::move(ir_); + } + + // If the spir-v struct was marked as `BufferBlock` then we always treat this as a storage + // address space. We do this as a post-pass because we have to propagate the change through all + // the types that derive from the buffer block, e.g. any access needs to change from `Uniform` + // to `Storage` address space. + void RemapBufferBlockAddressSpace() { + for (auto* inst : *ir_.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + + auto* ptr = var->Result()->Type()->As(); + TINT_ASSERT(ptr); + + auto* str = ptr->UnwrapPtr()->As(); + if (!str) { + continue; + } + if (!storage_buffer_types_.contains(str)) { + continue; + } + auto iter = var_to_original_access_mode_.find(var); + TINT_ASSERT(iter != var_to_original_access_mode_.end()); + auto access_mode = iter->second; + + // Handle the case of the struct members all being marked as `NonWritable` + if (consider_non_writable_.contains(str)) { + access_mode = core::Access::kRead; + } + + // Storage buffer can not be `write` only + if (access_mode == core::Access::kWrite) { + access_mode = core::Access::kReadWrite; + } + + var->Result()->SetType(ty_.ptr(core::AddressSpace::kStorage, str, access_mode)); + UpdateUsagesToStorageAddressSpace(var->Result(), access_mode); + } + } + + void UpdateUsagesToStorageAddressSpace(core::ir::Value* val, core::Access access_mode) { + for (auto& usage : val->UsagesUnsorted()) { + if (usage->instruction->Results().IsEmpty()) { + continue; + } + + auto* res = usage->instruction->Result(); + auto* ptr = res->Type()->As(); + if (!ptr) { + continue; + } + TINT_ASSERT(ptr->AddressSpace() == core::AddressSpace::kUniform); + + res->SetType(ty_.ptr(core::AddressSpace::kStorage, ptr->StoreType(), access_mode)); + UpdateUsagesToStorageAddressSpace(res, access_mode); + } + } + + void AddRefToOutputsIfNeeded() { + for (auto& entry_point : spirv_context_->module()->entry_points()) { + uint32_t spv_id = entry_point.GetSingleWordInOperand(1); + TINT_ASSERT(functions_.Contains(spv_id)); + + auto* func = *(functions_.Get(spv_id)); + for (uint32_t i = 3; i < entry_point.NumInOperands(); ++i) { + auto* val = Value(entry_point.GetSingleWordInOperand(i)); + b_.Phony(val)->InsertBefore(func->Block()->Front()); + } + } + } + + void RemapSamplers() { + for (auto* inst : *ir_.root_block) { + auto* var = inst->As(); + if (!var) { + continue; + } + auto* ptr = var->Result()->Type()->As(); + TINT_ASSERT(ptr); + + if (!ptr->StoreType()->As()) { + continue; + } + + TINT_ASSERT(var->BindingPoint().has_value()); + + auto bp = var->BindingPoint().value(); + auto used = used_bindings.GetOrAddZero(bp); + + // Only one use is the sampler itself. + if (used == 1) { + continue; + } + + auto& binding = max_binding.GetOrAddZero(bp.group); + binding += 1; + + var->SetBindingPoint(bp.group, binding); + } + } + + std::optional GetSpecId(const spvtools::opt::Instruction& inst) { + auto decos = + spirv_context_->get_decoration_mgr()->GetDecorationsFor(inst.result_id(), true); + for (const auto* deco_inst : decos) { + TINT_ASSERT(deco_inst->opcode() == spv::Op::OpDecorate); + + if (deco_inst->GetSingleWordInOperand(1) == + static_cast(spv::Decoration::SpecId)) { + return {static_cast(deco_inst->GetSingleWordInOperand(2))}; + } + } + return std::nullopt; + } + + void CreateOverride(const spvtools::opt::Instruction& inst, + core::ir::Value* value, + std::optional spec_id) { + auto* override_ = b_.Override(Type(inst.type_id())); + override_->SetInitializer(value); + + if (spec_id.has_value()) { + override_->SetOverrideId(OverrideId{spec_id.value()}); + } + + Emit(override_, inst.result_id()); + + Symbol name = GetSymbolFor(inst.result_id()); + if (name.IsValid()) { + ir_.SetName(override_, name); + } + } + + // Generate a module-scope const declaration for each instruction + // that is OpSpecConstantTrue, OpSpecConstantFalse, or OpSpecConstant. + void EmitSpecConstants() { + for (auto& inst : spirv_context_->types_values()) { + switch (inst.opcode()) { + case spv::Op::OpSpecConstantTrue: + case spv::Op::OpSpecConstantFalse: { + auto* value = b_.Value(inst.opcode() == spv::Op::OpSpecConstantTrue); + auto spec_id = GetSpecId(inst); + + if (spec_id.has_value()) { + CreateOverride(inst, value, spec_id); + } else { + // No spec_id means treat this as a constant. + AddValue(inst.result_id(), value); + } + break; + } + case spv::Op::OpSpecConstant: { + auto literal = inst.GetSingleWordInOperand(0); + auto* ty = spirv_context_->get_type_mgr()->GetType(inst.type_id()); + + auto* constant = + spirv_context_->get_constant_mgr()->GetConstant(ty, std::vector{literal}); + + core::ir::Value* value = tint::Switch( + Type(spirv_context_->get_type_mgr()->GetId(ty)), // + [&](const core::type::I32*) { + return b_.Constant(i32(constant->GetS32())); + }, + [&](const core::type::U32*) { + return b_.Constant(u32(constant->GetU32())); + }, + [&](const core::type::F32*) { + return b_.Constant(f32(constant->GetFloat())); + }, + [&](const core::type::F16*) { + auto bits = constant->AsScalarConstant()->GetU32BitValue(); + return b_.Constant(f16::FromBits(static_cast(bits))); + }, + TINT_ICE_ON_NO_MATCH); + + auto spec_id = GetSpecId(inst); + CreateOverride(inst, value, spec_id); + break; + } + case spv::Op::OpSpecConstantOp: { + auto op = inst.GetSingleWordInOperand(0); + + // Store the name away and remove it from the name list. + // This keeps any `Emit*` call in the switch below for + // gaining the name we want associated to the override. + std::string name; + auto iter = id_to_name_.find(inst.result_id()); + if (iter != id_to_name_.end()) { + name = iter->second; + id_to_name_.erase(inst.result_id()); + } + + switch (static_cast(op)) { + case spv::Op::OpBitwiseAnd: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseAnd, 3); + break; + case spv::Op::OpBitwiseOr: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseOr, 3); + break; + case spv::Op::OpBitwiseXor: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseXor, 3); + break; + case spv::Op::OpIEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kEqual, 3); + break; + case spv::Op::OpINotEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kNotEqual, 3); + break; + case spv::Op::OpSGreaterThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThan, 3); + break; + case spv::Op::OpSGreaterThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThanEqual, 3); + break; + case spv::Op::OpSLessThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThan, 3); + break; + case spv::Op::OpSLessThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThanEqual, 3); + break; + case spv::Op::OpUGreaterThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThan, 3); + break; + case spv::Op::OpUGreaterThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThanEqual, 3); + break; + case spv::Op::OpULessThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThan, 3); + break; + case spv::Op::OpULessThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThanEqual, 3); + break; + case spv::Op::OpLogicalAnd: + EmitBinary(inst, core::BinaryOp::kAnd, 3); + break; + case spv::Op::OpLogicalOr: + EmitBinary(inst, core::BinaryOp::kOr, 3); + break; + case spv::Op::OpLogicalNot: + EmitUnary(inst, core::UnaryOp::kNot, 3); + break; + case spv::Op::OpLogicalEqual: + EmitBinary(inst, core::BinaryOp::kEqual, 3); + break; + case spv::Op::OpLogicalNotEqual: + EmitBinary(inst, core::BinaryOp::kNotEqual, 3); + break; + case spv::Op::OpNot: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kNot, 3); + break; + case spv::Op::OpSConvert: + TINT_ICE() << "can't translate SConvert: WGSL does not have concrete " + "integer types of different widths"; + case spv::Op::OpUConvert: + TINT_ICE() << "can't translate UConvert: WGSL does not have concrete " + "integer types of different widths"; + case spv::Op::OpFConvert: + Emit(b_.Convert(Type(inst.type_id()), + Value(inst.GetSingleWordInOperand(1))), + inst.result_id()); + break; + case spv::Op::OpSNegate: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSNegate, 3); + break; + case spv::Op::OpIAdd: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kAdd, 3); + break; + case spv::Op::OpISub: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSub, 3); + break; + case spv::Op::OpIMul: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kMul, 3); + break; + case spv::Op::OpSDiv: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSDiv, 3); + break; + case spv::Op::OpUDiv: + EmitBinary(inst, core::BinaryOp::kDivide, 3); + break; + case spv::Op::OpUMod: + EmitBinary(inst, core::BinaryOp::kModulo, 3); + break; + case spv::Op::OpSMod: + case spv::Op::OpSRem: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSMod, 3); + break; + case spv::Op::OpShiftLeftLogical: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftLeftLogical, + 3); + break; + case spv::Op::OpShiftRightLogical: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftRightLogical, + 3); + break; + case spv::Op::OpShiftRightArithmetic: + EmitSpirvExplicitBuiltinCall( + inst, spirv::BuiltinFn::kShiftRightArithmetic, 3); + break; + case spv::Op::OpCompositeExtract: + EmitCompositeExtract(inst, 3); + break; + case spv::Op::OpCompositeInsert: + TINT_ICE() << "can't translate OpSpecConstantOp with CompositeInsert: " + "OpSpecConstantOp maps to a WGSL override declaration, " + "but WGSL overrides must have scalar type"; + case spv::Op::OpVectorShuffle: + TINT_ICE() << "can't translate OpSpecConstantOp with VectorShuffle: " + "OpSpecConstantOp maps to a WGSL override declaration, " + "but WGSL overrides must have scalar type"; + case spv::Op::OpSelect: + TINT_ASSERT(Type(inst.type_id())->IsScalar()) + << "can't translate OpSpecConstantOp with Select that returns " + "a vector: " + "OpSpecConstantOp maps to a WGSL override declaration, " + "but WGSL overrides must have scalar type"; + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSelect, 3); + break; + default: + TINT_ICE() << "Unknown spec constant operation: " << op; + } + + // Restore the saved name, if any, in order to provide that + // name to the override. + if (!name.empty()) { + id_to_name_.insert({inst.result_id(), name}); + } + + CreateOverride(inst, Value(inst.result_id()), std::nullopt); + break; + } + case spv::Op::OpSpecConstantComposite: { + auto spec_id = GetSpecId(inst); + TINT_ASSERT(!spec_id.has_value()) + << "OpSpecConstantCompositeOp not supported when set with a SpecId"; + + auto* cnst = SpvConstant(inst.result_id()); + if (cnst != nullptr) { + // The spec constant is made of literals, so it's return as a constant from + // SPIR-V Tools Opt. We can just ignore it and let the normal constant + // handling take over. + break; + } + + Vector args; + args.Reserve(inst.NumInOperands()); + + for (uint32_t i = 0; i < inst.NumInOperands(); ++i) { + uint32_t id = inst.GetSingleWordInOperand(i); + args.Push(id); + } + + spec_composites_.insert({inst.result_id(), SpecComposite{ + .type = Type(inst.type_id()), + .args = args, + }}); + break; + } + default: + break; + } + } + } + + void RegisterNames() { + // Register names from OpName + for (const auto& inst : spirv_context_->debugs2()) { + switch (inst.opcode()) { + case spv::Op::OpName: { + const auto name = inst.GetInOperand(1).AsString(); + if (!name.empty()) { + id_to_name_[inst.GetSingleWordInOperand(0)] = name; + } + break; + } + case spv::Op::OpMemberName: { + const auto name = inst.GetInOperand(2).AsString(); + if (!name.empty()) { + uint32_t struct_id = inst.GetSingleWordInOperand(0); + uint32_t member_idx = inst.GetSingleWordInOperand(1); + auto iter = struct_to_member_names_.insert({struct_id, {}}); + auto& members = (*(iter.first)).second; + + if (members.size() < (member_idx + 1)) { + members.resize(member_idx + 1); + } + members[member_idx] = name; + } + break; + } + default: + break; + } + } + } + + /// @param sc a SPIR-V storage class + /// @returns the Tint address space for a SPIR-V storage class + core::AddressSpace AddressSpace(spv::StorageClass sc) { + switch (sc) { + case spv::StorageClass::Input: + return core::AddressSpace::kIn; + case spv::StorageClass::Output: + return core::AddressSpace::kOut; + case spv::StorageClass::Function: + return core::AddressSpace::kFunction; + case spv::StorageClass::Private: + return core::AddressSpace::kPrivate; + case spv::StorageClass::StorageBuffer: + return core::AddressSpace::kStorage; + case spv::StorageClass::Uniform: + return core::AddressSpace::kUniform; + case spv::StorageClass::UniformConstant: + return core::AddressSpace::kHandle; + case spv::StorageClass::Workgroup: + return core::AddressSpace::kWorkgroup; + case spv::StorageClass::PushConstant: + return core::AddressSpace::kImmediate; + default: + TINT_UNIMPLEMENTED() + << "unhandled SPIR-V storage class: " << static_cast(sc); + } + } + + /// @param b a SPIR-V BuiltIn + /// @returns the Tint builtin value for a SPIR-V BuiltIn decoration + core::BuiltinValue Builtin(spv::BuiltIn b) { + switch (b) { + case spv::BuiltIn::FragCoord: + return core::BuiltinValue::kPosition; + case spv::BuiltIn::FragDepth: + return core::BuiltinValue::kFragDepth; + case spv::BuiltIn::FrontFacing: + return core::BuiltinValue::kFrontFacing; + case spv::BuiltIn::GlobalInvocationId: + return core::BuiltinValue::kGlobalInvocationId; + case spv::BuiltIn::InstanceIndex: + return core::BuiltinValue::kInstanceIndex; + case spv::BuiltIn::LocalInvocationId: + return core::BuiltinValue::kLocalInvocationId; + case spv::BuiltIn::LocalInvocationIndex: + return core::BuiltinValue::kLocalInvocationIndex; + case spv::BuiltIn::NumWorkgroups: + return core::BuiltinValue::kNumWorkgroups; + case spv::BuiltIn::PointSize: + return core::BuiltinValue::kPointSize; + case spv::BuiltIn::Position: + return core::BuiltinValue::kPosition; + case spv::BuiltIn::SampleId: + return core::BuiltinValue::kSampleIndex; + case spv::BuiltIn::SampleMask: + return core::BuiltinValue::kSampleMask; + case spv::BuiltIn::SubgroupId: + return core::BuiltinValue::kSubgroupId; + case spv::BuiltIn::SubgroupSize: + return core::BuiltinValue::kSubgroupSize; + case spv::BuiltIn::SubgroupLocalInvocationId: + return core::BuiltinValue::kSubgroupInvocationId; + case spv::BuiltIn::NumSubgroups: + return core::BuiltinValue::kNumSubgroups; + case spv::BuiltIn::VertexIndex: + return core::BuiltinValue::kVertexIndex; + case spv::BuiltIn::WorkgroupId: + return core::BuiltinValue::kWorkgroupId; + case spv::BuiltIn::ClipDistance: + return core::BuiltinValue::kClipDistances; + case spv::BuiltIn::CullDistance: + return core::BuiltinValue::kCullDistance; + case spv::BuiltIn::PrimitiveId: + return core::BuiltinValue::kPrimitiveIndex; + default: + TINT_UNIMPLEMENTED() << "unhandled SPIR-V BuiltIn: " << spv::BuiltInToString(b) + << " (val = " << static_cast(b) << ")"; + } + } + + /// @param id a SPIR-V result ID for a type declaration instruction + /// @param access_mode an optional access mode (for pointers) + /// @returns a Tint type object + const core::type::Type* Type(uint32_t id, core::Access access_mode = core::Access::kUndefined) { + auto* type = spirv_context_->get_type_mgr()->GetType(id); + + // Only use the access mode for the map key if it is used as part of the type in Tint IR. + auto key_mode = core::Access::kUndefined; + if (type->kind() == spvtools::opt::analysis::Type::kImage || + type->kind() == spvtools::opt::analysis::Type::kPointer) { + key_mode = access_mode; + } + + return types_.GetOrAdd(TypeKey{id, key_mode}, [&]() -> const core::type::Type* { + uint32_t array_stride = 0; + bool set_as_storage_buffer = false; + for (auto& deco : type->decorations()) { + switch (spv::Decoration(deco[0])) { + case spv::Decoration::Block: { + // Ignore, just means it's a memory block. + break; + } + case spv::Decoration::BufferBlock: { + set_as_storage_buffer = true; + break; + } + case spv::Decoration::ArrayStride: { + array_stride = deco[1]; + break; + } + default: { + TINT_UNIMPLEMENTED() << " unhandled type decoration " << deco[0]; + } + } + } + // Storage buffer is only set ons structs + if (set_as_storage_buffer) { + TINT_ASSERT(type->kind() == spvtools::opt::analysis::Type::kStruct); + } + // ArrayStride is only handled on the array type for now + if (array_stride > 0) { + if (type->kind() != spvtools::opt::analysis::Type::kArray && + type->kind() != spvtools::opt::analysis::Type::kRuntimeArray) { + TINT_UNREACHABLE() + << "ArrayStride is only accepted on an Array or RuntimeArray"; + } + } + + switch (type->kind()) { + case spvtools::opt::analysis::Type::kVoid: { + return ty_.void_(); + } + case spvtools::opt::analysis::Type::kBool: { + return ty_.bool_(); + } + case spvtools::opt::analysis::Type::kInteger: { + auto* int_ty = type->AsInteger(); + TINT_ASSERT(int_ty->width() == 32); + if (int_ty->IsSigned()) { + return ty_.i32(); + } else { + return ty_.u32(); + } + } + case spvtools::opt::analysis::Type::kFloat: { + auto* float_ty = type->AsFloat(); + if (float_ty->width() == 16) { + return ty_.f16(); + } else if (float_ty->width() == 32) { + return ty_.f32(); + } else { + TINT_UNREACHABLE() + << "unsupported floating point type width: " << float_ty->width(); + } + } + case spvtools::opt::analysis::Type::kVector: { + auto* vec_ty = type->AsVector(); + TINT_ASSERT(vec_ty->element_count() <= 4); + return ty_.vec( + Type(spirv_context_->get_type_mgr()->GetId(vec_ty->element_type())), + vec_ty->element_count()); + } + case spvtools::opt::analysis::Type::kMatrix: { + auto* mat_ty = type->AsMatrix(); + TINT_ASSERT(mat_ty->element_count() <= 4); + return ty_.mat( + As( + Type(spirv_context_->get_type_mgr()->GetId(mat_ty->element_type()))), + mat_ty->element_count()); + } + case spvtools::opt::analysis::Type::kArray: { + return EmitArray(id, array_stride); + } + case spvtools::opt::analysis::Type::kRuntimeArray: { + return EmitRuntimeArray(id, array_stride); + } + case spvtools::opt::analysis::Type::kStruct: { + const core::type::Struct* str_ty = EmitStruct(id); + if (set_as_storage_buffer) { + storage_buffer_types_.insert(str_ty); + } + return str_ty; + } + case spvtools::opt::analysis::Type::kPointer: { + return EmitPointer(id, access_mode); + } + case spvtools::opt::analysis::Type::kSampler: { + return ty_.sampler(); + } + case spvtools::opt::analysis::Type::kImage: { + auto* img = type->AsImage(); + + auto* sampled_ty = + Type(spirv_context_->get_type_mgr()->GetId(img->sampled_type())); + auto dim = static_cast(img->dim()); + auto depth = static_cast(img->depth()); + auto arrayed = + img->is_arrayed() ? type::Arrayed::kArrayed : type::Arrayed::kNonArrayed; + auto ms = img->is_multisampled() ? type::Multisampled::kMultisampled + : type::Multisampled::kSingleSampled; + auto sampled = static_cast(img->sampled()); + auto texel_format = ToTexelFormat(img->format()); + + // If the access mode is undefined then default to read/write for the image + access_mode = access_mode == core::Access::kUndefined ? core::Access::kReadWrite + : access_mode; + + if (img->dim() != spv::Dim::Dim1D && img->dim() != spv::Dim::Dim2D && + img->dim() != spv::Dim::Dim3D && img->dim() != spv::Dim::Cube && + img->dim() != spv::Dim::SubpassData) { + TINT_ICE() + << "Unsupported texture dimension: " << spv::DimToString(img->dim()) + << " (val = " << static_cast(img->dim()) << ")"; + } + TINT_ASSERT(img->sampled() != 0) + << "Unsupported texture sample setting: Known at Runtime"; + + if (depth == type::Depth::kDepth && !sampled_ty->Is()) { + TINT_ICE() << "Unsupported depth texture sampled type (must be f32)"; + } + + return ty_.Get(sampled_ty, dim, depth, arrayed, ms, sampled, + texel_format, access_mode); + } + case spvtools::opt::analysis::Type::kSampledImage: { + auto* sampled = type->AsSampledImage(); + return ty_.Get( + Type(spirv_context_->get_type_mgr()->GetId(sampled->image_type()))); + } + default: { + TINT_UNIMPLEMENTED() << "unhandled SPIR-V type: " << type->str(); + } + } + }); + } + + core::TexelFormat ToTexelFormat(spv::ImageFormat fmt) { + switch (fmt) { + case spv::ImageFormat::Unknown: + return core::TexelFormat::kUndefined; + + // 8 bit channels + case spv::ImageFormat::Rgba8: + return core::TexelFormat::kRgba8Unorm; + case spv::ImageFormat::Rgba8Snorm: + return core::TexelFormat::kRgba8Snorm; + case spv::ImageFormat::Rgba8ui: + return core::TexelFormat::kRgba8Uint; + case spv::ImageFormat::Rgba8i: + return core::TexelFormat::kRgba8Sint; + case spv::ImageFormat::R8: + return core::TexelFormat::kR8Unorm; + case spv::ImageFormat::R8i: + return core::TexelFormat::kR8Sint; + case spv::ImageFormat::R8ui: + return core::TexelFormat::kR8Uint; + case spv::ImageFormat::R8Snorm: + return core::TexelFormat::kR8Snorm; + case spv::ImageFormat::Rg8: + return core::TexelFormat::kRg8Unorm; + case spv::ImageFormat::Rg8Snorm: + return core::TexelFormat::kRg8Snorm; + case spv::ImageFormat::Rg8i: + return core::TexelFormat::kRg8Sint; + case spv::ImageFormat::Rg8ui: + return core::TexelFormat::kRg8Uint; + + // 16 bit channels + case spv::ImageFormat::R16: + return core::TexelFormat::kR16Unorm; + case spv::ImageFormat::R16f: + return core::TexelFormat::kR16Float; + case spv::ImageFormat::R16i: + return core::TexelFormat::kR16Sint; + case spv::ImageFormat::R16ui: + return core::TexelFormat::kR16Uint; + case spv::ImageFormat::R16Snorm: + return core::TexelFormat::kR16Snorm; + case spv::ImageFormat::Rgba16: + return core::TexelFormat::kRgba16Unorm; + case spv::ImageFormat::Rgba16ui: + return core::TexelFormat::kRgba16Uint; + case spv::ImageFormat::Rgba16i: + return core::TexelFormat::kRgba16Sint; + case spv::ImageFormat::Rgba16f: + return core::TexelFormat::kRgba16Float; + case spv::ImageFormat::Rgba16Snorm: + return core::TexelFormat::kRgba16Snorm; + case spv::ImageFormat::Rg16: + return core::TexelFormat::kRg16Unorm; + case spv::ImageFormat::Rg16i: + return core::TexelFormat::kRg16Sint; + case spv::ImageFormat::Rg16ui: + return core::TexelFormat::kRg16Uint; + case spv::ImageFormat::Rg16f: + return core::TexelFormat::kRg16Float; + case spv::ImageFormat::Rg16Snorm: + return core::TexelFormat::kRg16Snorm; + + // 32 bit channels + case spv::ImageFormat::R32ui: + return core::TexelFormat::kR32Uint; + case spv::ImageFormat::R32i: + return core::TexelFormat::kR32Sint; + case spv::ImageFormat::R32f: + return core::TexelFormat::kR32Float; + case spv::ImageFormat::Rg32ui: + return core::TexelFormat::kRg32Uint; + case spv::ImageFormat::Rg32i: + return core::TexelFormat::kRg32Sint; + case spv::ImageFormat::Rg32f: + return core::TexelFormat::kRg32Float; + case spv::ImageFormat::Rgba32ui: + return core::TexelFormat::kRgba32Uint; + case spv::ImageFormat::Rgba32i: + return core::TexelFormat::kRgba32Sint; + case spv::ImageFormat::Rgba32f: + return core::TexelFormat::kRgba32Float; + case spv::ImageFormat::Rgb10A2: + return core::TexelFormat::kRgb10A2Unorm; + case spv::ImageFormat::Rgb10a2ui: + return core::TexelFormat::kRgb10A2Uint; + case spv::ImageFormat::R11fG11fB10f: + return core::TexelFormat::kRg11B10Ufloat; + default: + break; + } + TINT_ICE() << "invalid image format: " << int(fmt); + } + + /// @param type_id the pointer result_id + /// @param access_mode the access mode + /// @returns a Tint pointer object + const core::type::Type* EmitPointer(uint32_t type_id, core::Access access_mode) { + auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id); + + auto* subtype = Type(inst->GetInOperand(1).AsId(), access_mode); + + // In a few cases we need to adjust the access mode. + // + // 1. Handle is always a read pointer + // 2. If the SPIR-V type should be considered NonWritable + if (subtype->IsHandle() || consider_non_writable_.contains(subtype)) { + access_mode = core::Access::kRead; + } + + // Using the deduplicated pointer should be fine because the storage classes must have + // matched if it was a duplicate. + auto* ptr_ty = spirv_context_->get_type_mgr()->GetType(type_id)->AsPointer(); + return ty_.ptr(AddressSpace(ptr_ty->storage_class()), subtype, access_mode); + } + + /// @param type_id the spirv result_id + /// @returns a Tint runtime array object + const core::type::Type* EmitRuntimeArray(uint32_t type_id, uint32_t array_stride) { + auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id); + + auto* elem_ty = Type(inst->GetInOperand(0).AsId()); + uint32_t implicit_stride = tint::RoundUp(elem_ty->Align(), elem_ty->Size()); + if (array_stride == 0 || array_stride == implicit_stride) { + return ty_.runtime_array(elem_ty); + } + + return ty_.Get( + elem_ty, ty_.Get(), static_cast(array_stride), + array_stride); + } + + /// @param type_id the spirv result_id for the type + /// @param array_stride the stride + /// @returns a Tint array object + const core::type::Type* EmitArray(uint32_t type_id, uint32_t array_stride) { + auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id); + + // Even deduplicated the length info must match, so safe to use the type manager info here. + auto* arr_ty = spirv_context_->get_type_mgr()->GetType(type_id)->AsArray(); + const auto& length = arr_ty->length_info(); + TINT_ASSERT(!length.words.empty()); + if (length.words[0] != spvtools::opt::analysis::Array::LengthInfo::kConstant) { + TINT_UNIMPLEMENTED() << "specialized array lengths"; + } + + // Get the value from the constant used for the element count. + const auto* count_const = + spirv_context_->get_constant_mgr()->FindDeclaredConstant(length.id); + TINT_ASSERT(count_const); + const uint64_t count_val = count_const->GetZeroExtendedValue(); + TINT_ASSERT(count_val <= UINT32_MAX); + + auto* elem_ty = Type(inst->GetInOperand(0).AsId()); + uint32_t implicit_stride = tint::RoundUp(elem_ty->Align(), elem_ty->Size()); + if (array_stride == 0 || array_stride == implicit_stride) { + return ty_.array(elem_ty, static_cast(count_val)); + } + + return ty_.Get( + elem_ty, ty_.Get(static_cast(count_val)), + static_cast(array_stride * count_val), array_stride); + } + + /// Calculate the size of a struct member type that has a matrix stride decoration. + uint32_t GetSizeOfTypeWithMatrixStride(const core::type::Type* type, + uint32_t stride, + bool is_row_major) { + return tint::Switch( + type, + [&](const core::type::Matrix* mat) { + return stride * (is_row_major ? mat->Rows() : mat->Columns()); + }, + [&](const core::type::Array* arr) { + auto size = GetSizeOfTypeWithMatrixStride(arr->ElemType(), stride, is_row_major); + // The size of a runtime-sized array is the size of a single element, so we only + // have to handle the fixed-sized array case here. + if (auto count = arr->ConstantCount()) { + size *= count.value(); + } + return size; + }, + TINT_ICE_ON_NO_MATCH); + } + + /// @param type_id the struct type id + /// @returns a Tint struct object + const core::type::Struct* EmitStruct(uint32_t type_id) { + auto* inst = spirv_context_->get_def_use_mgr()->GetDef(type_id); + + uint32_t member_count = inst->NumInOperandWords(); + TINT_ASSERT(member_count != 0) << "empty structures are not supported"; + + std::vector* member_names = nullptr; + auto struct_to_member_iter = struct_to_member_names_.find(type_id); + if (struct_to_member_iter != struct_to_member_names_.end()) { + member_names = &((*struct_to_member_iter).second); + } + + // We can use the struct type for the decorations, since even if it was deduplicated then + // the decorations must be the same. + auto* struct_ty = spirv_context_->get_type_mgr()->GetType(type_id)->AsStruct(); + + // Build a list of struct members. + uint32_t current_size = 0u; + uint32_t non_writable_members = 0; + Vector members; + for (uint32_t i = 0; i < member_count; i++) { + auto* member_ty = Type(inst->GetInOperand(i).AsId()); + uint32_t align = std::max(member_ty->Align(), 1u); + uint32_t offset = tint::RoundUp(align, current_size); + core::IOAttributes attributes; + auto interpolation = [&]() -> core::Interpolation& { + // Create the interpolation field with the default values on first call. + if (!attributes.interpolation.has_value()) { + attributes.interpolation = + core::Interpolation{core::InterpolationType::kPerspective, + core::InterpolationSampling::kUndefined}; + } + return attributes.interpolation.value(); + }; + + bool is_row_major = false; + uint32_t matrix_stride = 0; + // Handle member decorations that affect layout or attributes. + if (struct_ty->element_decorations().count(i)) { + for (auto& deco : struct_ty->element_decorations().at(i)) { + switch (spv::Decoration(deco[0])) { + case spv::Decoration::NonWritable: + // WGSL doesn't have a non-writable attribute on struct members, but, if + // the SPIR-V structure has NonWritable on all members then we treat the + // entire structure as non-writable. + non_writable_members += 1; + break; + + case spv::Decoration::ColMajor: // Do nothing, WGSL is column major + case spv::Decoration::NonReadable: // Not supported in WGSL + case spv::Decoration::RelaxedPrecision: // Not supported in WGSL + break; + case spv::Decoration::Coherent: + // Tint has coherent memory semantics, so this is a no-op. + break; + case spv::Decoration::RowMajor: + is_row_major = true; + break; + case spv::Decoration::MatrixStride: + matrix_stride = deco[1]; + break; + case spv::Decoration::Offset: + offset = deco[1]; + break; + case spv::Decoration::BuiltIn: + attributes.builtin = Builtin(spv::BuiltIn(deco[1])); + break; + case spv::Decoration::Invariant: + attributes.invariant = true; + break; + case spv::Decoration::Location: + attributes.location = deco[1]; + break; + case spv::Decoration::NoPerspective: + interpolation().type = core::InterpolationType::kLinear; + break; + case spv::Decoration::Flat: + interpolation().type = core::InterpolationType::kFlat; + break; + case spv::Decoration::Centroid: + interpolation().sampling = core::InterpolationSampling::kCentroid; + break; + case spv::Decoration::Sample: + interpolation().sampling = core::InterpolationSampling::kSample; + break; + + default: + TINT_UNIMPLEMENTED() << "unhandled member decoration: " << deco[0]; + } + } + } + + if (member_ty->IsIntegerScalarOrVector() && attributes.location.has_value()) { + interpolation().type = core::InterpolationType::kFlat; + } + + Symbol name; + if (member_names && member_names->size() > i) { + auto n = (*member_names)[i]; + if (!n.empty()) { + name = ir_.symbols.Register(n); + } + } + if (!name.IsValid()) { + name = ir_.symbols.New(); + } + + uint32_t size = member_ty->Size(); + if (matrix_stride > 0) { + size = GetSizeOfTypeWithMatrixStride(member_ty, matrix_stride, is_row_major); + } + + core::type::StructMember* member = ty_.Get( + name, member_ty, i, offset, align, size, std::move(attributes)); + if (is_row_major) { + member->SetRowMajor(); + } + if (matrix_stride > 0) { + member->SetMatrixStride(matrix_stride); + } + + members.Push(member); + + current_size = offset + size; + } + + Symbol name = GetUniqueSymbolFor(type_id); + if (!name.IsValid()) { + name = ir_.symbols.New(); + } + auto* strct = ty_.Struct(name, std::move(members)); + if (non_writable_members == member_count) { + consider_non_writable_.insert(strct); + } + return strct; + } + + Symbol GetUniqueSymbolFor(uint32_t id) { + auto iter = id_to_name_.find(id); + if (iter != id_to_name_.end()) { + return ir_.symbols.New(iter->second); + } + return Symbol{}; + } + + Symbol GetSymbolFor(uint32_t id) { + auto iter = id_to_name_.find(id); + if (iter != id_to_name_.end()) { + return ir_.symbols.Register(iter->second); + } + return Symbol{}; + } + + /// @param id a SPIR-V result ID for a function declaration instruction + /// @returns a Tint function object + core::ir::Function* Function(uint32_t id) { + return functions_.GetOrAdd(id, [&] { return b_.Function(ty_.void_()); }); + } + + // Passes a value up through control flow to make it visible in an outer scope. Because SPIR-V + // allows an id to be referenced as long as it's dominated, you can access a variable which is + // defined inside an if branch for example. In order for that to be accessed in IR, we have to + // propagate the value as a return of the control instruction (like the if). + // + // e.g. if the IR is similar to the following: + // ``` + // if (b) { + // %a:i32 = let 4; + // exit_if + // } + // %c:i32 = %a + %a; + // ``` + // + // We propagate to something like: + // ``` + // %d:i32 = if (b) { + // %a:i32 = let 4; // The spir-v ID refers to %a at this point + // exit_if %a + // } + // %c:i32 = %d + %d // The spir-v ID will now refer to %d instead of %a + // ``` + // + // We can end up propagating up through multiple levels, so we can end up with something like: + // ``` + // %k:i32 = if (true) { + // %l:i32 = if (false) { + // %m:i32 = if (true) { + // %n:i32 = switch 4 { + // default: { + // %o:i32 = loop { + // %a:i32 = let 4; + // exit_loop %a + // } + // exit_switch %o + // } + // } + // exit_if %n + // } + // exit_if %m + // } + // exit_if %l + // } + // %b:i32 = %k + %k + // ``` + // + // @param id the spir-v ID to propagate up + // @param src the source value being propagated + core::ir::Value* Propagate(uint32_t id, core::ir::Value* src) { + // Function params are always in scope so we should never need to propagate. + if (src->Is()) { + return src; + } + + auto* blk = tint::Switch( + src, // + [&](core::ir::BlockParam* bp) { return bp->Block(); }, + [&](core::ir::InstructionResult* res) { return res->Instruction()->Block(); }, + TINT_ICE_ON_NO_MATCH); + + // Walk up the set of control instructions from the current `blk`. We'll update the `src` + // instruction as the new result which is to be used for the given SPIR-V `id`. At each + // control instruction we'll add the current `src` as a result of each exit from the control + // instruction, making a new result which is available in the parent scope. + while (blk) { + if (InBlock(blk)) { + break; + } + + core::ir::ControlInstruction* ctrl = nullptr; + if (auto* mb = blk->As()) { + ctrl = mb->Parent()->As(); + TINT_ASSERT(ctrl); + + for (auto exit : ctrl->Exits()) { + tint::Switch( + exit.Value(), // + [&](core::ir::ExitLoop* el) { el->PushOperand(src); }, + [&](core::ir::BreakIf* bi) { bi->PushOperand(src); }, // + TINT_ICE_ON_NO_MATCH); + } + } else { + TINT_ASSERT(blk->Terminator()); + + ctrl = tint::Switch( + blk->Terminator(), // + [&](core::ir::ExitIf* ei) { return ei->If(); }, + [&](core::ir::ExitSwitch* es) { return es->Switch(); }, + [&](core::ir::ExitLoop* el) { return el->Loop(); }, + [&](core::ir::NextIteration* ni) { + ni->PushOperand(src); + return nullptr; + }, + [&](core::ir::Continue* cont) { + // The propagation is going through a `continue`. This means + // this is the only path to the continuing block, but it also + // means we're current in the continuing block. We can't do + // normal propagation here, we have to pass a block param + // instead. + + auto* param = b_.BlockParam(src->Type()); + + // We're in the continuing block, so make the block param available in the + // scope. + id_stack_.back().insert(id); + + auto* loop = cont->Loop(); + loop->Continuing()->AddParam(param); + cont->PushOperand(src); + + // Set `src` as the `param` so it's returned as the new value + src = param; + return nullptr; + }, // + [&](core::ir::Unreachable*) { return blk->Parent(); }, // + TINT_ICE_ON_NO_MATCH); + + if (!ctrl) { + break; + } + + for (auto& exit : ctrl->Exits()) { + exit->PushOperand(src); + } + } + + // If this control has no exits, then we don't need to add the result through the + // control as we're jumping over the control to its parent control. (This is an + // `if` inside a `loop` where the `if` is doing a `break`). + if (ctrl->Exits().IsEmpty()) { + if (ctrl->Is()) { + TINT_UNREACHABLE() + << "loop detected with no exits which means it's an infinite loop. " + "Infinite loops are not supported in WGSL"; + } + + TINT_ASSERT(ctrl->Is()); + blk = ctrl->Block(); + continue; + } + + // Add a new result to the control instruction + ctrl->AddResult(b_.InstructionResult(src->Type())); + // The source instruction is now the control result we just inserted + src = ctrl->Results().Back(); + // The SPIR-V ID now refers to the propagated value. + values_.Replace(id, src); + + blk = ctrl->Block(); + } + return src; + } + + // Returns true if the `blk` is the `parent_blk` or any of the ancestors of parent_blk + bool IsContainedInBlock(core::ir::Block* parent_blk, core::ir::Block* blk) { + while (parent_blk) { + if (parent_blk == blk) { + return true; + } + + if (!parent_blk->Parent()) { + break; + } + parent_blk = parent_blk->Parent()->Block(); + } + return false; + } + + // Propagate a value out of a control instruction. This isn't the same as the other + // propagate as we only need to pull it out through a single blocks exit for the control + // instruction. + core::ir::Value* PropagateTerm(core::ir::Terminator* term, + uint32_t spv_id_being_propagated, + core::ir::Value* source_value, + core::ir::Block* source_block) { + auto* current_ctrl = source_block->Parent(); + core::ir::Block* current_blk = source_block; + core::ir::Value* propagated_value = source_value; + auto* type = source_value->Type(); + + while (true) { + if (IsContainedInBlock(term->Block(), current_blk)) { + break; + } + TINT_ASSERT(current_ctrl); + + // If the terminator is an exit for this control instruction, we're done as the caller + // will handle adding the result. + bool done = false; + for (auto exit : current_ctrl->Exits()) { + if (exit.Value() == term) { + done = true; + break; + } + } + if (done) { + break; + } + + auto* res = b_.InstructionResult(type); + current_ctrl->AddResult(res); + + for (auto exit : current_ctrl->Exits()) { + if (IsContainedInBlock(exit->Block(), current_blk)) { + exit->PushOperand(propagated_value); + continue; + } + + // Special handling for loop-continuing blocks as the body is visible to the + // continuing so any block params from the body can pass through the exit. + if (auto* loop = current_ctrl->As()) { + if (exit->Block() == loop->Continuing() && + propagated_value->Is()) { + exit->PushOperand(propagated_value); + } + } + } + + propagated_value = res; + current_blk = current_ctrl->Block(); + current_ctrl = current_blk->Parent(); + } + + values_.Replace(spv_id_being_propagated, propagated_value); + return propagated_value; + } + + // Returns true if the value is a constant value + bool IdIsConstant(uint32_t id) { return SpvConstant(id) || spec_composites_.contains(id); } + + // Returns true if this value is currently in scope + bool IdIsInScope(uint32_t id) { + for (auto iter = id_stack_.rbegin(); iter != id_stack_.rend(); ++iter) { + if (iter->contains(id)) { + return true; + } + } + return false; + } + + // Get the spirv constant for the given `id`. `nullptr` if no constant exists. + const spvtools::opt::analysis::Constant* SpvConstant(uint32_t id) { + return spirv_context_->get_constant_mgr()->FindDeclaredConstant(id); + } + + /// Attempts to retrieve the current Tint IR value for `id`. This ignores scoping for the + /// variable, if it exists it's returned (or if it's constant it's created). The value will not + /// propagate up through control instructions. + /// + /// @param id a SPIR-V result ID + /// @returns a Tint value object + std::optional ValueNoPropagate(uint32_t id) { + auto v = values_.Get(id); + if (v) { + return *v; + } + + if (auto* c = SpvConstant(id)) { + auto* val = b_.Constant(Constant(c)); + values_.Add(id, val); + return val; + } + + // If we didn't have a value already, and this instruction is a constructed constant, then + // do the construction. + const spvtools::opt::Instruction* inst = spirv_context_->get_def_use_mgr()->GetDef(id); + if (inst->opcode() == spv::Op::OpConstantComposite) { + Vector args; + args.Reserve(inst->NumInOperands()); + + for (uint32_t i = 0; i < inst->NumInOperands(); ++i) { + auto* cnst = Value(inst->GetSingleWordInOperand(i))->As(); + TINT_ASSERT(cnst); + args.Push(cnst->Value()); + } + + auto* composite = b_.Composite(Type(inst->type_id()), args); + AddValue(id, composite); + return composite; + } + + // If this was a spec composite, then it currently isn't in scope, so we construct + // a new copy and assign the constant ID to the new construct in this scope. + auto iter = spec_composites_.find(id); + if (iter != spec_composites_.end()) { + Vector args; + for (auto arg : iter->second.args) { + args.Push(Value(arg)); + } + + auto* construct = b_.Construct(iter->second.type, args); + current_block_->Append(construct); + AddValue(id, construct->Result()); + return construct->Result(); + } + + return std::nullopt; + } + + /// Attempts to retrieve the current Tint IR value for `id`. If the value exists and is not in + /// scope it will propagate the value up through the control instructions. + /// + /// @param id a SPIR-V result ID + /// @returns a Tint value object + core::ir::Value* Value(uint32_t id, bool add_to_scope = true) { + auto v = ValueNoPropagate(id); + TINT_ASSERT(v.has_value()); + + if (v.value()->Is() || IdIsInScope(id)) { + return v.value(); + } + + auto* new_v = Propagate(id, v.value()); + if (add_to_scope) { + AddValue(id, new_v); + } + return new_v; + } + + /// Creates the Tint IR constant for the SPIR-V `constant` value. + /// + /// @param constant a SPIR-V constant object + /// @returns a Tint constant value + const core::constant::Value* Constant(const spvtools::opt::analysis::Constant* constant) { + // Handle OpConstantNull for all types. + if (constant->AsNullConstant()) { + return ir_.constant_values.Zero( + Type(spirv_context_->get_type_mgr()->GetId(constant->type()))); + } + + if (auto* bool_ = constant->AsBoolConstant()) { + return b_.ConstantValue(bool_->value()); + } + if (auto* i = constant->AsIntConstant()) { + auto* int_ty = i->type()->AsInteger(); + TINT_ASSERT(int_ty->width() == 32); + if (int_ty->IsSigned()) { + return b_.ConstantValue(i32(i->GetS32BitValue())); + } else { + return b_.ConstantValue(u32(i->GetU32BitValue())); + } + } + if (auto* f = constant->AsFloatConstant()) { + auto* float_ty = f->type()->AsFloat(); + if (float_ty->width() == 16) { + return b_.ConstantValue(f16::FromBits(static_cast(f->words()[0]))); + } else if (float_ty->width() == 32) { + return b_.ConstantValue(f32(f->GetFloat())); + } else { + TINT_UNREACHABLE() << "unsupported floating point type width"; + } + } + if (auto* v = constant->AsVectorConstant()) { + Vector elements; + for (auto& el : v->GetComponents()) { + elements.Push(Constant(el)); + } + return ir_.constant_values.Composite( + Type(spirv_context_->get_type_mgr()->GetId(v->type())), std::move(elements)); + } + if (auto* m = constant->AsMatrixConstant()) { + Vector columns; + for (auto& el : m->GetComponents()) { + columns.Push(Constant(el)); + } + return ir_.constant_values.Composite( + Type(spirv_context_->get_type_mgr()->GetId(m->type())), std::move(columns)); + } + if (auto* a = constant->AsArrayConstant()) { + Vector elements; + for (auto& el : a->GetComponents()) { + elements.Push(Constant(el)); + } + return ir_.constant_values.Composite( + Type(spirv_context_->get_type_mgr()->GetId(a->type())), std::move(elements)); + } + if (auto* s = constant->AsStructConstant()) { + Vector elements; + for (auto& el : s->GetComponents()) { + elements.Push(Constant(el)); + } + return ir_.constant_values.Composite( + Type(spirv_context_->get_type_mgr()->GetId(s->type())), std::move(elements)); + } + TINT_UNIMPLEMENTED() << "unhandled constant type"; + } + + /// Register an IR value for a SPIR-V result ID. + /// @param result_id the SPIR-V result ID + /// @param value the IR value + void AddValue(uint32_t result_id, core::ir::Value* value) { + id_stack_.back().insert(result_id); + values_.Replace(result_id, value); + } + + /// Emit an instruction to the current block and associates the result to + /// the spirv result id. + /// @param inst the instruction to emit + /// @param result_id the SPIR-V result ID to register the instruction result for + void Emit(core::ir::Instruction* inst, uint32_t result_id) { + current_block_->Append(inst); + TINT_ASSERT(inst->Results().Length() == 1u); + AddValue(result_id, inst->Result()); + + Symbol name = GetSymbolFor(result_id); + if (name.IsValid() && !inst->Result()->Type()->Is()) { + ir_.SetName(inst, name); + } + } + + /// Emit an instruction to the current block. + /// @param inst the instruction to emit + void EmitWithoutSpvResult(core::ir::Instruction* inst) { + current_block_->Append(inst); + TINT_ASSERT(inst->Results().Length() == 1u); + } + + /// Emit an instruction to the current block. + /// @param inst the instruction to emit + void EmitWithoutResult(core::ir::Instruction* inst) { + TINT_ASSERT(inst->Results().IsEmpty()); + current_block_->Append(inst); + } + + /// Emit the module-scope variables. + void EmitModuleScopeVariables() { + for (auto& inst : spirv_context_->module()->types_values()) { + switch (inst.opcode()) { + case spv::Op::OpVariable: + EmitVar(inst); + break; + case spv::Op::OpUndef: { + auto* ty = Type(inst.type_id()); + + TINT_ASSERT(!ty->Is()) + << "cannot create an undef memory view in WGSL"; + + AddValue(inst.result_id(), b_.Zero(ty)); + break; + } + default: + break; + } + } + } + + /// Emit the functions. + void EmitFunctions() { + // Add all the functions in a first pass and then fill in the function bodies. This means + // the function will exist fixing an issues where calling a function that hasn't been seen + // generates the wrong signature. + for (auto& func : *spirv_context_->module()) { + current_spirv_function_ = &func; + + Vector params; + func.ForEachParam([&](spvtools::opt::Instruction* spirv_param) { + auto* param = b_.FunctionParam(Type(spirv_param->type_id())); + values_.Add(spirv_param->result_id(), param); + + Symbol name = GetSymbolFor(spirv_param->result_id()); + if (name.IsValid()) { + ir_.SetName(param, name); + } + + params.Push(param); + }); + + current_function_ = Function(func.result_id()); + current_function_->SetParams(std::move(params)); + current_function_->SetReturnType(Type(func.type_id())); + + Symbol name = GetSymbolFor(func.result_id()); + if (name.IsValid()) { + ir_.SetName(current_function_, name); + } + + functions_.Add(func.result_id(), current_function_); + current_spirv_function_ = nullptr; + } + + for (auto& func : *spirv_context_->module()) { + current_spirv_function_ = &func; + + current_function_ = Function(func.result_id()); + EmitBlockParent(current_function_->Block(), *func.entry()); + + // No terminator was emitted, that means then end of block is + // unreachable. Mark as such. + if (!current_function_->Block()->Terminator()) { + current_function_->Block()->Append(b_.Unreachable()); + } + current_spirv_function_ = nullptr; + } + } + + /// Emit entry point attributes. + void EmitEntryPointAttributes() { + // Handle OpEntryPoint declarations. + for (auto& entry_point : spirv_context_->module()->entry_points()) { + auto model = entry_point.GetSingleWordInOperand(0); + auto* func = Function(entry_point.GetSingleWordInOperand(1)); + + // Set the pipeline stage. + switch (spv::ExecutionModel(model)) { + case spv::ExecutionModel::GLCompute: + func->SetStage(core::ir::Function::PipelineStage::kCompute); + break; + case spv::ExecutionModel::Fragment: + func->SetStage(core::ir::Function::PipelineStage::kFragment); + break; + case spv::ExecutionModel::Vertex: + func->SetStage(core::ir::Function::PipelineStage::kVertex); + break; + default: + TINT_UNIMPLEMENTED() << "unhandled execution model: " << model; + } + + // Set the entry point name. + ir_.SetName(func, entry_point.GetOperand(2).AsString()); + + if (func->IsCompute()) { + // Search for `WorkgroupSize` decorated Ids + for (const spvtools::opt::Instruction& inst : + spirv_context_->module()->annotations()) { + if (inst.opcode() != spv::Op::OpDecorate || + inst.GetSingleWordInOperand(1) != uint32_t(spv::Decoration::BuiltIn) || + inst.GetSingleWordInOperand(2) != uint32_t(spv::BuiltIn::WorkgroupSize)) { + continue; + } + uint32_t id = inst.GetSingleWordInOperand(0); + + Vector args; + if (auto* c = SpvConstant(id)) { + auto* vals = c->AsVectorConstant(); + TINT_ASSERT(vals); + + for (auto& el : vals->GetComponents()) { + args.Push(b_.Constant(Constant(el))); + } + } else { + TINT_ASSERT(spec_composites_.contains(id)); + + auto info = spec_composites_[id]; + TINT_ASSERT(info.args.Length() == 3); + + for (auto arg : info.args) { + args.Push(Value(arg)); + } + } + func->SetWorkgroupSize(args[0], args[1], args[2]); + + break; + } + } + } + + // Handle OpExecutionMode declarations. + for (auto& execution_mode : spirv_context_->module()->execution_modes()) { + auto* func = functions_.GetOr(execution_mode.GetSingleWordInOperand(0), nullptr); + auto mode = execution_mode.GetSingleWordInOperand(1); + TINT_ASSERT(func); + + switch (spv::ExecutionMode(mode)) { + case spv::ExecutionMode::LocalSize: + func->SetWorkgroupSize( + b_.Constant(u32(execution_mode.GetSingleWordInOperand(2))), + b_.Constant(u32(execution_mode.GetSingleWordInOperand(3))), + b_.Constant(u32(execution_mode.GetSingleWordInOperand(4)))); + break; + case spv::ExecutionMode::DepthGreater: + TINT_ICE() << "ExecutionMode DepthGreater is not supported in WGSL"; + /* Ice aborts, so this doesn't fallthrough */ + case spv::ExecutionMode::DepthLess: + TINT_ICE() << "ExecutionMode DepthLess is not supported in WGSL"; + /* Ice aborts, so this doesn't fallthrough */ + case spv::ExecutionMode::DepthUnchanged: + TINT_ICE() << "ExecutionMode DepthUnchanged is not supported in WGSL"; + /* Ice aborts, so this doesn't fallthrough */ + case spv::ExecutionMode::EarlyFragmentTests: + TINT_ICE() << "ExecutionMode EarlyFragmentTests is not supported in WGSL"; + /* Ice aborts, so this doesn't fallthrough */ + case spv::ExecutionMode::DepthReplacing: + case spv::ExecutionMode::OriginUpperLeft: + // These are ignored as they are implicitly supported by Tint IR. + break; + default: + TINT_UNIMPLEMENTED() << "unhandled execution mode: " << mode; + } + } + } + + bool InBlock(core::ir::Block* blk) { return current_blocks_.contains(blk); } + + // A block parent is a container for a scope, like a `{}`d section in code. It controls the + // block addition to the current blocks and the ID stack entry for the block. + void EmitBlockParent(core::ir::Block* dst, spvtools::opt::BasicBlock& src) { + TINT_ASSERT(!InBlock(dst)); + + id_stack_.emplace_back(); + current_blocks_.insert(dst); + + EmitBlock(dst, src); + + current_blocks_.erase(dst); + id_stack_.pop_back(); + } + + /// Emit the contents of SPIR-V block @p src into Tint IR block @p dst. + /// @param dst the Tint IR block to append to + /// @param src the SPIR-V block to emit + void EmitBlock(core::ir::Block* dst, spvtools::opt::BasicBlock& src) { + TINT_SCOPED_ASSIGNMENT(current_block_, dst); + + // Register the merge if this is a header block + auto* merge_inst = src.GetMergeInst(); + if (merge_inst) { + auto merge_id = merge_inst->GetSingleWordInOperand(0); + spirv_merge_id_to_header_id_.insert({merge_id, src.id()}); + } + + values_to_replace_.push_back({}); + + // If this is a loop merge block, so we need to treat it as a Loop. + auto* loop_merge_inst = src.GetLoopMergeInst(); + core::ir::Loop* loop = nullptr; + if (loop_merge_inst) { + // Emit the loop instruction into the current block. + EmitLoop(src); + + // The loop header is a walk stop block, which was created in the emit loop method. Get + // the loop back so we can change the current insertion block. + loop = StopWalkingAt(src.id())->As(); + TINT_ASSERT(loop); + + id_stack_.emplace_back(); + current_blocks_.insert(loop->Body()); + + // Now emit the remainder of the block into the loop body. We do this now so the loop + // emitted above is in the parent block. + current_block_ = loop->Body(); + } + + // Note, this comes after the loop code since the current block is set to the loop body + spirv_id_to_block_.insert({src.id(), current_block_}); + + ProcessInstructions(src); + + // Add the body terminator if necessary + if (loop && !loop->Body()->Terminator()) { + loop->Body()->Append(b_.Unreachable()); + } + + // For any `OpPhi` values we saw, insert their `Value` now. We do this at the end of the + // processing of instructions because a phi can refer to instructions defined after it + // in the block. + auto replace = values_to_replace_.back(); + for (auto& val : replace) { + auto v = ValueNoPropagate(val.value_id); + TINT_ASSERT(v.has_value()); + val.terminator->SetOperand(val.idx, v.value()); + } + + values_to_replace_.pop_back(); + + if (!loop) { + return; + } + + // Emit the continuing block. The continue block is within the scope of the body block, + // so we don't pop the id stack yet. + auto continue_id = loop_merge_inst->GetSingleWordInOperand(1); + + // Capture any continue PHi header values before emitting the continue because the value + // will get re-written to be the continue block param, so we have to capture first. + auto continue_loop_phi_ids = block_phi_values_[continue_id]; + std::vector continue_loop_phi_values; + if (!continue_loop_phi_ids.empty()) { + continue_loop_phi_values.reserve(continue_loop_phi_ids.size()); + for (auto& id : continue_loop_phi_ids) { + auto v = ValueNoPropagate(id); + if (v.has_value()) { + continue_loop_phi_values.push_back(v.value()); + } + } + } + + EmitContinueBlock(src.id(), continue_id, loop); + + // Remove the body block id stack before emitting the merge block. + current_blocks_.erase(loop->Body()); + id_stack_.pop_back(); + + // If we added phi's to the continuing block, we may have exits from the body which + // aren't valid. + if (loop->Continuing()->Params().Length() > 0) { + for (auto incoming : loop->Continuing()->InboundSiblingBranches()) { + TINT_ASSERT(incoming->Is()); + + if (incoming->Args().Length() == loop->Continuing()->Params().Length()) { + continue; + } + + // Check if the block this instruction exists in has default phi result that we + // can append. + auto inst_to_blk_iter = inst_to_spirv_block_.find(incoming); + if (inst_to_blk_iter != inst_to_spirv_block_.end()) { + uint32_t spirv_blk = inst_to_blk_iter->second; + + auto phi_values_from_loop_header = block_phi_values_[spirv_blk]; + + // We require a PHI value, but the current block doesn't have any from the + // header. In this case, check the `continue` target to see if it has header + // provided phi values. If so, use that one. + if (phi_values_from_loop_header.empty()) { + TINT_ASSERT(!continue_loop_phi_values.empty()); + + for (auto* value : continue_loop_phi_values) { + incoming->PushOperand(value); + } + + } else { + // If there were phi values, push them to this instruction + for (auto value_id : phi_values_from_loop_header) { + auto* value = Value(value_id); + incoming->PushOperand(value); + } + } + } else { + TINT_UNREACHABLE() << "unable to provide needed continue arguments"; + } + } + } + + // Emit the merge block + auto merge_id = loop_merge_inst->GetSingleWordInOperand(0); + const auto& merge_bb = current_spirv_function_->FindBlock(merge_id); + EmitBlock(dst, *merge_bb); + } + + void EmitContinueBlock(uint32_t src_id, uint32_t continue_id, core::ir::Loop* loop) { + // We're emitting the continue block, so remove it from the continue targets as it can no + // longer be a target for this loop. This will allow it to be _reused_ as the continue + // target for a single block loop if needed (which may have this same block as the + // continue). + continue_targets_.erase(continue_id); + + // Push id stack entry for the continuing block. We don't use EmitBlockParent to do this + // because we need the scope to exist until after we process any `continue_blk_phis_`. + id_stack_.emplace_back(); + + // We only need to emit the continuing block if: + // a) It is not the loop header + // b) It has inbound branches. This works around a case where you can have a continuing + // where uses values which are very difficult to propagate, but the continuing is never + // reached anyway, so the propagation is useless. + bool skipped_continue = true; + if (continue_id != src_id && !loop->Continuing()->InboundSiblingBranches().IsEmpty()) { + skipped_continue = false; + + const auto& bb_continue = current_spirv_function_->FindBlock(continue_id); + + current_blocks_.insert(loop->Continuing()); + EmitBlock(loop->Continuing(), *bb_continue); + current_blocks_.erase(loop->Continuing()); + } + + if (!loop->Continuing()->Terminator()) { + loop->Continuing()->Append(b_.NextIteration(loop)); + } + + // If this continue block needs to pass any `phi` instructions back to the main loop body. + // + // We have to do this here because we need to have emitted the loop body before we can get + // the values used in the continue block. + auto phis = continue_blk_phis_.find(continue_id); + if (phis != continue_blk_phis_.end()) { + for (auto value_id : phis->second) { + auto* value = skipped_continue ? nullptr : Value(value_id, false); + + tint::Switch( + loop->Continuing()->Terminator(), // + [&](core::ir::NextIteration* ni) { ni->PushOperand(value); }, + [&](core::ir::BreakIf* bi) { + // TODO(dsinclair): Need to change the break-if insertion if there happens + // to be exit values, but those are rare, so leave this for when we have + // test case. + TINT_ASSERT(bi->ExitValues().empty()); + + auto len = bi->NextIterValues().size(); + bi->PushOperand(value); + bi->SetNumNextIterValues(len + 1); + }, + TINT_ICE_ON_NO_MATCH); + } + } + + id_stack_.pop_back(); + } + + void ProcessInstructions(spvtools::opt::BasicBlock& src) { + for (auto& inst : src) { + switch (inst.opcode()) { + case spv::Op::OpNop: + break; + case spv::Op::OpUndef: + AddValue(inst.result_id(), b_.Zero(Type(inst.type_id()))); + break; + case spv::Op::OpBranch: + EmitBranch(inst); + break; + case spv::Op::OpBranchConditional: + EmitBranchConditional(src, inst); + break; + case spv::Op::OpSwitch: + EmitSwitch(src, inst); + break; + case spv::Op::OpLoopMerge: + EmitLoopMerge(src, inst); + break; + case spv::Op::OpSelectionMerge: + // Do nothing, the selection merge will be handled in the following + // OpBranchCondition or OpSwitch instruction + break; + case spv::Op::OpExtInst: + EmitExtInst(inst); + break; + case spv::Op::OpCopyObject: + EmitCopyObject(inst); + break; + case spv::Op::OpConvertFToS: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kConvertFToS); + break; + case spv::Op::OpConvertFToU: + Emit(b_.Convert(Type(inst.type_id()), Value(inst.GetSingleWordOperand(2))), + inst.result_id()); + break; + case spv::Op::OpConvertSToF: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kConvertSToF); + break; + case spv::Op::OpConvertUToF: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kConvertUToF); + break; + case spv::Op::OpFConvert: + Emit(b_.Convert(Type(inst.type_id()), Value(inst.GetSingleWordOperand(2))), + inst.result_id()); + break; + case spv::Op::OpBitwiseAnd: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseAnd); + break; + case spv::Op::OpBitwiseOr: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseOr); + break; + case spv::Op::OpBitwiseXor: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kBitwiseXor); + break; + case spv::Op::OpAccessChain: + case spv::Op::OpInBoundsAccessChain: + EmitAccess(inst); + break; + case spv::Op::OpCompositeInsert: + EmitCompositeInsert(inst); + break; + case spv::Op::OpCompositeConstruct: + EmitConstruct(inst); + break; + case spv::Op::OpCompositeExtract: + EmitCompositeExtract(inst); + break; + case spv::Op::OpVectorInsertDynamic: + EmitVectorInsertDynamic(inst); + break; + case spv::Op::OpFAdd: + EmitBinary(inst, core::BinaryOp::kAdd); + break; + case spv::Op::OpIAdd: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kAdd); + break; + case spv::Op::OpSDiv: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSDiv); + break; + case spv::Op::OpFDiv: + case spv::Op::OpUDiv: + EmitBinary(inst, core::BinaryOp::kDivide); + break; + case spv::Op::OpIMul: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kMul); + break; + case spv::Op::OpFMul: + case spv::Op::OpVectorTimesScalar: + case spv::Op::OpMatrixTimesScalar: + case spv::Op::OpVectorTimesMatrix: + case spv::Op::OpMatrixTimesVector: + case spv::Op::OpMatrixTimesMatrix: + EmitBinary(inst, core::BinaryOp::kMultiply); + break; + case spv::Op::OpFRem: + case spv::Op::OpUMod: + EmitBinary(inst, core::BinaryOp::kModulo); + break; + case spv::Op::OpSMod: + case spv::Op::OpSRem: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSMod); + break; + case spv::Op::OpFSub: + EmitBinary(inst, core::BinaryOp::kSubtract); + break; + case spv::Op::OpFOrdEqual: + EmitBinary(inst, core::BinaryOp::kEqual); + break; + case spv::Op::OpFOrdNotEqual: + EmitBinary(inst, core::BinaryOp::kNotEqual); + break; + case spv::Op::OpFOrdGreaterThan: + EmitBinary(inst, core::BinaryOp::kGreaterThan); + break; + case spv::Op::OpFOrdGreaterThanEqual: + EmitBinary(inst, core::BinaryOp::kGreaterThanEqual); + break; + case spv::Op::OpFOrdLessThan: + EmitBinary(inst, core::BinaryOp::kLessThan); + break; + case spv::Op::OpFOrdLessThanEqual: + EmitBinary(inst, core::BinaryOp::kLessThanEqual); + break; + case spv::Op::OpFUnordEqual: + EmitInvertedBinary(inst, core::BinaryOp::kNotEqual); + break; + case spv::Op::OpFUnordNotEqual: + EmitInvertedBinary(inst, core::BinaryOp::kEqual); + break; + case spv::Op::OpFUnordGreaterThan: + EmitInvertedBinary(inst, core::BinaryOp::kLessThanEqual); + break; + case spv::Op::OpFUnordGreaterThanEqual: + EmitInvertedBinary(inst, core::BinaryOp::kLessThan); + break; + case spv::Op::OpFUnordLessThan: + EmitInvertedBinary(inst, core::BinaryOp::kGreaterThanEqual); + break; + case spv::Op::OpFUnordLessThanEqual: + EmitInvertedBinary(inst, core::BinaryOp::kGreaterThan); + break; + case spv::Op::OpIEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kEqual); + break; + case spv::Op::OpINotEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kNotEqual); + break; + case spv::Op::OpSGreaterThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThan); + break; + case spv::Op::OpSGreaterThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSGreaterThanEqual); + break; + case spv::Op::OpSLessThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThan); + break; + case spv::Op::OpSLessThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSLessThanEqual); + break; + case spv::Op::OpUGreaterThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThan); + break; + case spv::Op::OpUGreaterThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kUGreaterThanEqual); + break; + case spv::Op::OpULessThan: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThan); + break; + case spv::Op::OpULessThanEqual: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kULessThanEqual); + break; + case spv::Op::OpISub: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSub); + break; + case spv::Op::OpFunctionCall: + EmitFunctionCall(inst); + break; + case spv::Op::OpLoad: + Emit(b_.Load(Value(inst.GetSingleWordOperand(2))), inst.result_id()); + break; + case spv::Op::OpReturn: + EmitWithoutResult(b_.Return(current_function_)); + break; + case spv::Op::OpReturnValue: + EmitWithoutResult( + b_.Return(current_function_, Value(inst.GetSingleWordOperand(0)))); + break; + case spv::Op::OpStore: + EmitWithoutResult(b_.Store(Value(inst.GetSingleWordOperand(0)), + Value(inst.GetSingleWordOperand(1)))); + break; + case spv::Op::OpCopyMemory: + EmitCopyMemory(inst); + break; + case spv::Op::OpVariable: + EmitVar(inst); + break; + case spv::Op::OpUnreachable: + EmitWithoutResult(b_.Unreachable()); + break; + case spv::Op::OpKill: + case spv::Op::OpTerminateInvocation: + EmitKill(inst); + break; + case spv::Op::OpDot: + EmitBuiltinCall(inst, core::BuiltinFn::kDot); + break; + case spv::Op::OpBitCount: + EmitBitCount(inst); + break; + case spv::Op::OpBitFieldInsert: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kBitFieldInsert); + break; + case spv::Op::OpBitFieldSExtract: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kBitFieldSExtract); + break; + case spv::Op::OpBitFieldUExtract: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kBitFieldUExtract); + break; + case spv::Op::OpBitReverse: + EmitBuiltinCall(inst, core::BuiltinFn::kReverseBits); + break; + case spv::Op::OpAll: + EmitBuiltinCall(inst, core::BuiltinFn::kAll); + break; + case spv::Op::OpAny: + EmitBuiltinCall(inst, core::BuiltinFn::kAny); + break; + case spv::Op::OpDPdx: + EmitBuiltinCall(inst, core::BuiltinFn::kDpdx); + break; + case spv::Op::OpDPdy: + EmitBuiltinCall(inst, core::BuiltinFn::kDpdy); + break; + case spv::Op::OpFwidth: + EmitBuiltinCall(inst, core::BuiltinFn::kFwidth); + break; + case spv::Op::OpDPdxFine: + EmitBuiltinCall(inst, core::BuiltinFn::kDpdxFine); + break; + case spv::Op::OpDPdyFine: + EmitBuiltinCall(inst, core::BuiltinFn::kDpdyFine); + break; + case spv::Op::OpFwidthFine: + EmitBuiltinCall(inst, core::BuiltinFn::kFwidthFine); + break; + case spv::Op::OpDPdxCoarse: + EmitBuiltinCall(inst, core::BuiltinFn::kDpdxCoarse); + break; + case spv::Op::OpDPdyCoarse: + EmitBuiltinCall(inst, core::BuiltinFn::kDpdyCoarse); + break; + case spv::Op::OpFwidthCoarse: + EmitBuiltinCall(inst, core::BuiltinFn::kFwidthCoarse); + break; + case spv::Op::OpLogicalAnd: + EmitBinary(inst, core::BinaryOp::kAnd); + break; + case spv::Op::OpLogicalOr: + EmitBinary(inst, core::BinaryOp::kOr); + break; + case spv::Op::OpLogicalEqual: + EmitBinary(inst, core::BinaryOp::kEqual); + break; + case spv::Op::OpLogicalNotEqual: + EmitBinary(inst, core::BinaryOp::kNotEqual); + break; + case spv::Op::OpLogicalNot: + EmitUnary(inst, core::UnaryOp::kNot); + break; + case spv::Op::OpFNegate: + EmitUnary(inst, core::UnaryOp::kNegation); + break; + case spv::Op::OpNot: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kNot); + break; + case spv::Op::OpShiftLeftLogical: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftLeftLogical); + break; + case spv::Op::OpShiftRightLogical: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftRightLogical); + break; + case spv::Op::OpShiftRightArithmetic: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kShiftRightArithmetic); + break; + case spv::Op::OpBitcast: + EmitBitcast(inst); + break; + case spv::Op::OpQuantizeToF16: + EmitBuiltinCall(inst, core::BuiltinFn::kQuantizeToF16); + break; + case spv::Op::OpTranspose: + EmitBuiltinCall(inst, core::BuiltinFn::kTranspose); + break; + case spv::Op::OpSNegate: + EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kSNegate); + break; + case spv::Op::OpFMod: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kFMod); + break; + case spv::Op::OpSelect: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kSelect); + break; + case spv::Op::OpVectorExtractDynamic: + EmitAccess(inst); + break; + case spv::Op::OpOuterProduct: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kOuterProduct); + break; + case spv::Op::OpVectorShuffle: + EmitVectorShuffle(inst); + break; + case spv::Op::OpAtomicStore: + EmitAtomicStore(inst); + break; + case spv::Op::OpAtomicLoad: + CheckAtomicNotFloat(inst); + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicLoad); + break; + case spv::Op::OpAtomicIAdd: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIAdd); + break; + case spv::Op::OpAtomicISub: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicISub); + break; + case spv::Op::OpAtomicAnd: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicAnd); + break; + case spv::Op::OpAtomicOr: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicOr); + break; + case spv::Op::OpAtomicXor: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicXor); + break; + case spv::Op::OpAtomicSMin: + EmitAtomicSigned(inst, spirv::BuiltinFn::kAtomicSMin); + break; + case spv::Op::OpAtomicUMin: + EmitAtomicUnsigned(inst, spirv::BuiltinFn::kAtomicUMin); + break; + case spv::Op::OpAtomicSMax: + EmitAtomicSigned(inst, spirv::BuiltinFn::kAtomicSMax); + break; + case spv::Op::OpAtomicUMax: + EmitAtomicUnsigned(inst, spirv::BuiltinFn::kAtomicUMax); + break; + case spv::Op::OpAtomicExchange: + CheckAtomicNotFloat(inst); + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicExchange); + break; + case spv::Op::OpAtomicCompareExchange: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicCompareExchange); + break; + case spv::Op::OpAtomicIIncrement: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIIncrement); + break; + case spv::Op::OpAtomicIDecrement: + EmitSpirvBuiltinCall(inst, spirv::BuiltinFn::kAtomicIDecrement); + break; + case spv::Op::OpControlBarrier: + EmitControlBarrier(inst); + break; + case spv::Op::OpArrayLength: + EmitArrayLength(inst); + break; + case spv::Op::OpSampledImage: + EmitSampledImage(inst); + break; + case spv::Op::OpImage: + EmitImage(inst); + break; + case spv::Op::OpImageFetch: + EmitImageFetchOrRead(inst, spirv::BuiltinFn::kImageFetch); + break; + case spv::Op::OpImageRead: + EmitImageFetchOrRead(inst, spirv::BuiltinFn::kImageRead); + break; + case spv::Op::OpImageGather: + EmitImageGather(inst); + break; + case spv::Op::OpImageQueryLevels: + EmitImageQuery(inst, spirv::BuiltinFn::kImageQueryLevels); + break; + case spv::Op::OpImageQuerySamples: + EmitImageQuery(inst, spirv::BuiltinFn::kImageQuerySamples); + break; + case spv::Op::OpImageQuerySize: + EmitImageQuery(inst, spirv::BuiltinFn::kImageQuerySize); + break; + case spv::Op::OpImageQuerySizeLod: + EmitImageQuerySizeLod(inst); + break; + case spv::Op::OpImageSampleExplicitLod: + EmitImageSample(inst, spirv::BuiltinFn::kImageSampleExplicitLod); + break; + case spv::Op::OpImageSampleImplicitLod: + EmitImageSample(inst, spirv::BuiltinFn::kImageSampleImplicitLod); + break; + case spv::Op::OpImageSampleProjImplicitLod: + EmitImageSample(inst, spirv::BuiltinFn::kImageSampleProjImplicitLod); + break; + case spv::Op::OpImageSampleProjExplicitLod: + EmitImageSample(inst, spirv::BuiltinFn::kImageSampleProjExplicitLod); + break; + case spv::Op::OpImageWrite: + EmitImageWrite(inst); + break; + case spv::Op::OpImageSampleDrefImplicitLod: + EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleDrefImplicitLod); + break; + case spv::Op::OpImageSampleDrefExplicitLod: + EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleDrefExplicitLod); + break; + case spv::Op::OpImageSampleProjDrefImplicitLod: + EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleProjDrefImplicitLod); + break; + case spv::Op::OpImageSampleProjDrefExplicitLod: + EmitImageSampleDepth(inst, spirv::BuiltinFn::kImageSampleProjDrefExplicitLod); + break; + case spv::Op::OpImageDrefGather: + EmitImageGatherDref(inst); + break; + case spv::Op::OpPhi: + EmitPhi(inst); + break; + + case spv::Op::OpGroupNonUniformBroadcast: + EmitSubgroupBuiltinConstantId(inst, + spirv::BuiltinFn::kGroupNonUniformBroadcast); + break; + case spv::Op::OpGroupNonUniformQuadBroadcast: + EmitSubgroupBuiltinConstantId(inst, + spirv::BuiltinFn::kGroupNonUniformQuadBroadcast); + break; + case spv::Op::OpGroupNonUniformQuadSwap: + EmitSubgroupBuiltinConstantId(inst, spirv::BuiltinFn::kGroupNonUniformQuadSwap); + break; + case spv::Op::OpGroupNonUniformAll: + EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupAll); + break; + case spv::Op::OpGroupNonUniformAny: + EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupAny); + break; + case spv::Op::OpGroupNonUniformElect: + EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupElect); + break; + case spv::Op::OpGroupNonUniformBallot: + EmitSubgroupBuiltin(inst, core::BuiltinFn::kSubgroupBallot); + break; + case spv::Op::OpGroupNonUniformBroadcastFirst: + EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformBroadcastFirst); + break; + case spv::Op::OpGroupNonUniformShuffle: + EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffle); + break; + case spv::Op::OpGroupNonUniformShuffleXor: + EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffleXor); + break; + case spv::Op::OpGroupNonUniformShuffleDown: + EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffleDown); + break; + case spv::Op::OpGroupNonUniformShuffleUp: + EmitSubgroupBuiltin(inst, spirv::BuiltinFn::kGroupNonUniformShuffleUp); + break; + case spv::Op::OpGroupNonUniformSMin: + EmitSubgroupMinMax(inst, spirv::BuiltinFn::kGroupNonUniformSMin); + break; + case spv::Op::OpGroupNonUniformSMax: + EmitSubgroupMinMax(inst, spirv::BuiltinFn::kGroupNonUniformSMax); + break; + case spv::Op::OpGroupNonUniformUMin: + case spv::Op::OpGroupNonUniformFMin: + EmitSubgroupMinMax(inst, core::BuiltinFn::kSubgroupMin); + break; + case spv::Op::OpGroupNonUniformUMax: + case spv::Op::OpGroupNonUniformFMax: + EmitSubgroupMinMax(inst, core::BuiltinFn::kSubgroupMax); + break; + case spv::Op::OpGroupNonUniformIAdd: + case spv::Op::OpGroupNonUniformFAdd: + EmitSubgroupAdd(inst); + break; + case spv::Op::OpGroupNonUniformIMul: + case spv::Op::OpGroupNonUniformFMul: + EmitSubgroupMul(inst); + break; + case spv::Op::OpGroupNonUniformBitwiseAnd: + EmitSubgroupBitwise(inst, core::BuiltinFn::kSubgroupAnd); + break; + case spv::Op::OpGroupNonUniformBitwiseOr: + EmitSubgroupBitwise(inst, core::BuiltinFn::kSubgroupOr); + break; + case spv::Op::OpGroupNonUniformBitwiseXor: + EmitSubgroupBitwise(inst, core::BuiltinFn::kSubgroupXor); + break; + default: + TINT_UNIMPLEMENTED() + << "unhandled SPIR-V instruction: " << spv::OpToString(inst.opcode()) + << " (val = " << static_cast(inst.opcode()) << ")"; + } + } + } + + void ValidateScope(spvtools::opt::Instruction& inst) { + auto scope_val = Value(inst.GetSingleWordInOperand(0)); + auto* cnst = scope_val->As(); + TINT_ASSERT(cnst); + + uint32_t scope = cnst->Value()->ValueAs(); + TINT_ASSERT(static_cast(scope) == spv::Scope::Subgroup) + << "subgroup scope required for GroupNonUniform instructions"; + } + + void EmitSubgroupBitwise(spvtools::opt::Instruction& inst, core::BuiltinFn fn) { + ValidateScope(inst); + + auto group = inst.GetSingleWordInOperand(1); + TINT_ASSERT(static_cast(group) == spv::GroupOperation::Reduce) + << "GroupNonUniformBitwise operations require a Reduce group operation"; + + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id()); + } + + void EmitSubgroupMul(spvtools::opt::Instruction& inst) { + ValidateScope(inst); + + core::BuiltinFn fn = core::BuiltinFn::kNone; + + auto group = inst.GetSingleWordInOperand(1); + if (static_cast(group) == spv::GroupOperation::Reduce) { + fn = core::BuiltinFn::kSubgroupMul; + } else if (static_cast(group) == spv::GroupOperation::InclusiveScan) { + fn = core::BuiltinFn::kSubgroupInclusiveMul; + } else if (static_cast(group) == spv::GroupOperation::ExclusiveScan) { + fn = core::BuiltinFn::kSubgroupExclusiveMul; + } else { + TINT_ICE() << "GroupNonUniform Mul instruction must have a group of `Reduce`, " + "`InclusiveScan`, or `ExclusiveScan`"; + } + + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id()); + } + + void EmitSubgroupAdd(spvtools::opt::Instruction& inst) { + ValidateScope(inst); + + core::BuiltinFn fn = core::BuiltinFn::kNone; + + auto group = inst.GetSingleWordInOperand(1); + if (static_cast(group) == spv::GroupOperation::Reduce) { + fn = core::BuiltinFn::kSubgroupAdd; + } else if (static_cast(group) == spv::GroupOperation::InclusiveScan) { + fn = core::BuiltinFn::kSubgroupInclusiveAdd; + } else if (static_cast(group) == spv::GroupOperation::ExclusiveScan) { + fn = core::BuiltinFn::kSubgroupExclusiveAdd; + } else { + TINT_ICE() << "GroupNonUniform Add instruction must have a group of `Reduce`, " + "`InclusiveScan`, or `ExclusiveScan`"; + } + + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id()); + } + + void EmitSubgroupMinMax(spvtools::opt::Instruction& inst, core::BuiltinFn fn) { + ValidateScope(inst); + + auto group = inst.GetSingleWordInOperand(1); + TINT_ASSERT(static_cast(group) == spv::GroupOperation::Reduce) + << "group operand Reduce required for `Min`/`Max` instructions"; + + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 4)), inst.result_id()); + } + + void EmitSubgroupMinMax(spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + ValidateScope(inst); + + auto group = inst.GetSingleWordInOperand(1); + TINT_ASSERT(static_cast(group) == spv::GroupOperation::Reduce) + << "group operand Reduce required for `Min`/`Max` instructions"; + + Emit( + b_.Call(Type(inst.type_id()), fn, // + Vector{Value(inst.GetSingleWordInOperand(0)), // + b_.Constant(u32(inst.GetSingleWordInOperand(1))), + Value(inst.GetSingleWordInOperand(2))}), + inst.result_id()); + } + + void EmitSubgroupBuiltinConstantId(spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + auto id = Value(inst.GetSingleWordInOperand(2)); + + // TODO(431054356): Convert core::BuiltinFn::kSubgroupBroadcast non-constant values into a + // `subgroupShuffle` when we support SPIR-V >= 1.5 source. + // + // For QuadBroadcast this will remain an error as there is no WGSL equivalent. + // For QuadSwap this will remain an error as there is no WGSL equivalent. + TINT_ASSERT(id->Is()) + << "non-constant GroupNonUniform `Invocation Id` not supported"; + + ValidateScope(inst); + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 2)), + inst.result_id()); + } + + void EmitSubgroupBuiltin(spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + ValidateScope(inst); + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 2)), + inst.result_id()); + } + + void EmitSubgroupBuiltin(spvtools::opt::Instruction& inst, core::BuiltinFn fn) { + ValidateScope(inst); + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 3)), inst.result_id()); + } + + struct IfBranchValue { + core::ir::Value* value; + core::ir::If* if_; + }; + + void EmitPhi(spvtools::opt::Instruction& inst) { + auto num_ops = inst.NumInOperands(); + + // If there are no operands, then the phi is in a unreachable block, ignore it. + if (num_ops == 0) { + return; + } + + // If there are only 2 arguments, that means we came directly from a block, so just emit the + // value directly. + if (num_ops == 2) { + AddValue(inst.result_id(), Value(inst.GetSingleWordInOperand(0))); + return; + } + + auto* phi_containing_spirv_block = spirv_context_->get_instr_block(&inst); + auto iter = spirv_merge_id_to_header_id_.find(phi_containing_spirv_block->id()); + + // We're in a merge block for some construct which could be a loop, switch or if. + if (iter != spirv_merge_id_to_header_id_.end()) { + auto parent_blk_id = iter->second; + auto* parent_blk = spirv_context_->get_instr_block(parent_blk_id); + + if (parent_blk->terminator()->opcode() == spv::Op::OpSwitch) { + EmitPhiInSwitchMerge(inst, parent_blk_id); + return; + } + if (!parent_blk->IsLoopHeader()) { + EmitPhiInIfMerge(inst, parent_blk_id); + return; + } + } + + // At this point, we must be dealing with an OpPhi in some kind of loop context, the loop + // header, loop continuing or loop merge construct. + EmitPhiInLoop(inst); + } + + void EmitPhiInLoop(spvtools::opt::Instruction& inst) { + auto* phi_containing_spirv_block = spirv_context_->get_instr_block(&inst); + + auto iter = spirv_merge_id_to_header_id_.find(phi_containing_spirv_block->id()); + // We're in the merge block for the loop + if (iter != spirv_merge_id_to_header_id_.end()) { + EmitPhiInLoopMerge(inst); + return; + } + + // The OpPhi is in the loop header, which means it's the body of the loop. The OpPhi can + // receive values from the parent block, in which case we need to push them through the + // initializer, or from the continuing block, which we will not have emitted yet. + if (phi_containing_spirv_block->IsLoopHeader()) { + EmitPhiInLoopHeader(inst, phi_containing_spirv_block); + return; + } + + auto containing_loop_header_id = spirv_context_->GetStructuredCFGAnalysis()->ContainingLoop( + phi_containing_spirv_block->id()); + auto* loop_header_block = spirv_context_->get_instr_block(containing_loop_header_id); + TINT_ASSERT(loop_header_block); + + auto* loop_merge_inst = loop_header_block->GetLoopMergeInst(); + auto continue_id = loop_merge_inst->GetSingleWordInOperand(1); + + // If the spirv-id to block table contains an entry for the continue id then we must have + // started emitting the continue. + bool has_continue_emitted = spirv_id_to_block_.contains(continue_id); + if (!has_continue_emitted) { + EmitPhiInLoopBody(inst, loop_merge_inst); + return; + } + + // The OpPhi is in the continue block of the loop. + EmitPhiInLoopContinue(inst); + } + + void AddOperandToTerminator(core::ir::Terminator* term, uint32_t id) { + // If the ID is a constant, then we just directly emit it, it isn't an OpPhi value + if (IdIsConstant(id)) { + term->PushOperand(Value(id, false)); + return; + } + // If we've already seen the value, then we can emit it as this isn't referencing a later + // value. + auto val = values_.Get(id); + if (val) { + // If we've already seen the value, and it's still in scope, then we can just emit as it + // isn't referencing a later value. + if (IdIsInScope(id)) { + term->PushOperand(Value(id, false)); + return; + } + + // The value was a block param, that means it was a Phi which we've removed and + // converted. We need to pass that Phi out of the control instruction, but we only want + // to add it to exit instructions, not all terminators, so this isn't a full + // Propagation. + if (auto* bp = (*val)->As()) { + auto* v = PropagateTerm(term, id, bp, bp->Block()); + term->PushOperand(v); + return; + } + // The value is defined by an instruction inside an inner block. Propagate it out of + // that block, then push that propagated value onto this terminator. + if (auto* res = (*val)->As()) { + auto* v = PropagateTerm(term, id, *val, res->Instruction()->Block()); + term->PushOperand(v); + return; + } + } + + // Value isn't known, or isn't in scope, push a placeholder for the operand value. We store + // away the terminator/index pair along with the required value and then fill it in at the + // end of the block emission. + auto operand_idx = term->PushOperand(nullptr); + values_to_replace_.back().push_back(ReplacementValue{ + .terminator = term, + .idx = operand_idx, + .value_id = id, + }); + } + + void EmitPhiInLoopMerge(spvtools::opt::Instruction& inst) { + // All of the source blocks should exist as they will either be the loop header, if we + // happened to jump out early, the body if we break or the continuing if we break-if. + auto* type = Type(inst.type_id()); + + auto* phi_spirv_block = spirv_context_->get_instr_block(&inst); + auto phi_blk_id = phi_spirv_block->id(); + + // The merge target (which is the OpPhi SPIR-V block) is a walk stop block + auto* loop = StopWalkingAt(phi_spirv_block->id())->As(); + TINT_ASSERT(loop); + + std::optional default_value = std::nullopt; + + // The only way into the continue should be through `continue` calls out of the loop body, + // which should all exist at this point as we emit the body first. + for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) { + auto value_id = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + core::ir::Terminator* term = nullptr; + + // If the basic block ends in a branch conditional, then we really need to update the + // branch which goes to the current block, not the terminator of the block we emitted + // into. This difference is because the merge block will _also_ end up in the same IR + // block and we can't tell the difference if we just get the terminator. + const auto& bb = current_spirv_function_->FindBlock(blk_id); + auto* terminator = (*bb).terminator(); + if (terminator->opcode() == spv::Op::OpBranchConditional) { + uint32_t true_id = terminator->GetSingleWordInOperand(1); + uint32_t false_id = terminator->GetSingleWordInOperand(2); + + auto iter = branch_conditional_to_if_.find(terminator); + if (iter != branch_conditional_to_if_.end()) { + auto* if_ = iter->second; + if (true_id == phi_blk_id) { + term = if_->True()->Terminator(); + } else if (false_id == phi_blk_id) { + term = if_->False()->Terminator(); + } + } + } + + if (term == nullptr) { + auto value_blk_iter = spirv_id_to_block_.find(blk_id); + auto* value_ir_blk = value_blk_iter->second; + term = value_ir_blk->Terminator(); + } + + if (term->Is()) { + default_value = value_id; + continue; + } + // Continue isn't a terminator into a merge. So, we must have had a branch conditional + // where one branch continued and the other exited. We need to update the exiting block + // as the terminator. + if (term->Is()) { + auto* if_ = term->prev->As(); + TINT_ASSERT(if_); + + if (if_->True()->Terminator()->Is()) { + term = if_->True()->Terminator(); + } else { + term = if_->False()->Terminator(); + TINT_ASSERT(term->Is()); + } + } + + AddOperandToTerminator(term, value_id); + } + + auto* res = b_.InstructionResult(type); + loop->AddResult(res); + AddValue(inst.result_id(), res); + + // If there is a default value, then one of the blocks was an unreachable at the end. We + // need to find exits where we haven't set all the params and add the default. + if (default_value) { + auto result_count = loop->Results().Length(); + for (auto iter : loop->Exits()) { + if (iter->Operands().Length() >= result_count) { + continue; + } + + // We haven't updated the exit yet + auto* term = iter->As(); + TINT_ASSERT(term); + + AddOperandToTerminator(term, default_value.value()); + } + } + } + + void EmitPhiInLoopContinue(spvtools::opt::Instruction& inst) { + auto* type = Type(inst.type_id()); + + auto* phi_spirv_block = spirv_context_->get_instr_block(&inst); + + // The continue target is a walk stop block + auto* loop = StopWalkingAt(phi_spirv_block->id())->As(); + TINT_ASSERT(loop); + + std::optional default_value = std::nullopt; + + // The only way into the continue should be through `continue` calls out of the loop body, + // which should all exist at this point as we emit the body first. + for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) { + auto value_id = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + auto value_blk_iter = spirv_id_to_block_.find(blk_id); + auto* value_ir_blk = value_blk_iter->second; + auto* term = value_ir_blk->Terminator(); + + if (term->Is()) { + default_value = value_id; + continue; + } + + AddOperandToTerminator(term, value_id); + } + + // Add the block param to the continuing block + auto* p = b_.BlockParam(type); + loop->Continuing()->AddParam(p); + AddValue(inst.result_id(), p); + + // If there is a default value, then one of the blocks was an unreachable at the end, this + // can happen if the `OpBranchConditional` has one of the branches to the continue block. We + // need to find incoming sibling branches where we haven't set all the params and add the + // default. + if (default_value) { + auto param_count = loop->Continuing()->Params().Length(); + for (auto* sibling : loop->Continuing()->InboundSiblingBranches()) { + if (sibling->Operands().Length() >= param_count) { + continue; + } + // We haven't updated the sibling yet + auto* term = sibling->As(); + TINT_ASSERT(term); + + AddOperandToTerminator(term, default_value.value()); + } + } + } + + void EmitPhiInLoopBody(spvtools::opt::Instruction& inst, + spvtools::opt::Instruction* loop_merge_inst) { + auto continue_id = loop_merge_inst->GetSingleWordInOperand(1); + + auto* loop_header_block = spirv_context_->get_instr_block(loop_merge_inst); + + // The loop continue is a walk stop block. Since we're in the loop body itself we would have + // added the continue target to the stop blocks when processing the header loop merge. + auto* loop = StopWalkingAt(continue_id)->As(); + TINT_ASSERT(loop); + + // The only phi incoming block that makes sense on the body is from the loop header itself. + // Any other incoming branches must be from unreachable blocks, otherwise it would have had + // to have come from the loop header which is where the continue target will loop back too, + // not the body label directly. + std::optional value = std::nullopt; + for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) { + auto value_id = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + if (blk_id != loop_header_block->id()) { + continue; + } + + value = Value(value_id); + } + TINT_ASSERT(value.has_value()); + AddValue(inst.result_id(), value.value()); + } + + void EmitPhiInLoopHeader(spvtools::opt::Instruction& inst, + spvtools::opt::BasicBlock* loop_header) { + // Incoming branches should be from the parent block into the loop, and from the loop + // continuing back into the header, each with a block_id and a value_id. + TINT_ASSERT(inst.NumInOperands() == 4); + + auto* type = Type(inst.type_id()); + + auto* phi_spirv_block = spirv_context_->get_instr_block(&inst); + + auto* loop_merge_inst = loop_header->GetLoopMergeInst(); + auto continue_id = loop_merge_inst->GetSingleWordInOperand(1); + + // The loop header is a walk stop block. + auto* loop = StopWalkingAt(phi_spirv_block->id())->As(); + TINT_ASSERT(loop); + + for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) { + auto value_id = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + if (block_phi_values_.contains(blk_id)) { + block_phi_values_[blk_id].push_back(value_id); + } else { + block_phi_values_[blk_id] = {value_id}; + } + + auto v = values_.Get(value_id); + if (v) { + // If the value exists, then try to get it to force the propagation. If it doesn't + // exist, then it will come later in the header and we'll deal with it later. + Value(value_id); + } + + core::ir::Terminator* term = nullptr; + // The referenced block hasn't been emitted yet (continue blocks have this + // behaviour). So, store the fact that it needs to return a given value away for + // when we do emit the block. + // + // We check both if we've seen the continue block, which if it's a separate block we + // won't have seen, or if we have seen it (then it's the header itself) if the block is + // the continue id. + if (!spirv_id_to_block_.contains(blk_id) || blk_id == continue_id) { + // If the continue is a separate target, we'll emit it later so just store this + // value away to add to the next iteration. + if (continue_id != phi_spirv_block->id()) { + continue_blk_phis_[continue_id].push_back(value_id); + continue; + } + + // The loop header is the terminator, so synthesize a continue block and append + // to that a next iteration. + if (loop->Continuing()->IsEmpty()) { + b_.Append(loop->Continuing(), [&] { term = b_.NextIteration(loop); }); + } else { + // With multiple phis we may have already created the continuing + // block, so just get the terminator. + term = loop->Continuing()->Terminator(); + TINT_ASSERT(term->Is()); + } + + } else { + // This is the parent block, push this into the next iteration of the initializer. + if (loop->Initializer()->IsEmpty()) { + b_.Append(loop->Initializer(), [&] { term = b_.NextIteration(loop); }); + } else { + term = loop->Initializer()->Terminator(); + TINT_ASSERT(term->Is()); + } + } + + AddOperandToTerminator(term, value_id); + } + + // Add the block param to the body + auto* p = b_.BlockParam(type); + loop->Body()->AddParam(p); + AddValue(inst.result_id(), p); + } + + // Emit an OpPhi which is inside the merge block for a if. + void EmitPhiInIfMerge(spvtools::opt::Instruction& inst, uint32_t header_id) { + auto* type = Type(inst.type_id()); + core::ir::If* ctrl = nullptr; + std::optional value_for_default_block = std::nullopt; + + for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) { + auto value_id = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + auto value_blk_iter = spirv_id_to_block_.find(blk_id); + auto* value_ir_blk = value_blk_iter->second; + + // The block refers to the header itself, so it was the true or false branching directly + // to the merge. + // + // We store this away as we may not know the if yet, we need to wait until we get the + // control instruction and do the work later. + if (blk_id == header_id) { + value_for_default_block = Value(value_id); + continue; + } + + auto* term = value_ir_blk->Terminator(); + AddOperandToTerminator(term, value_id); + + if (auto* exit = term->As()) { + if (ctrl) { + TINT_ASSERT(ctrl == exit->ControlInstruction()); + } else { + ctrl = exit->ControlInstruction()->As(); + TINT_ASSERT(ctrl); + } + } else { + TINT_UNREACHABLE(); + } + } + // No control instruction means that both true/false branches are the merge itself, so we + // can just ignore the if, if we have a default then assign it straight through. + if (!ctrl) { + if (value_for_default_block) { + AddValue(inst.result_id(), value_for_default_block.value()); + } + return; + } + + // If the default block needs to be assigned a value + if (value_for_default_block) { + core::ir::Terminator* term = nullptr; + if (ctrl->True()->Terminator()->Operands().Length() < + ctrl->False()->Terminator()->Operands().Length()) { + term = ctrl->True()->Terminator(); + } else { + term = ctrl->False()->Terminator(); + } + term->PushOperand(value_for_default_block.value()); + } + + // Push the result into the parent + auto* res = b_.InstructionResult(type); + ctrl->AddResult(res); + AddValue(inst.result_id(), res); + } + + // Emit an OpPhi which is inside the merge block for a switch. + void EmitPhiInSwitchMerge(spvtools::opt::Instruction& inst, uint32_t header_id) { + auto* type = Type(inst.type_id()); + + core::ir::Switch* ctrl = nullptr; + std::optional value_for_default_block = std::nullopt; + + auto phi_blk_id = spirv_context_->get_instr_block(&inst)->id(); + + for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) { + auto value_id = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + core::ir::Terminator* term = nullptr; + + // If the basic block ends in a branch conditional, then we really need to update the + // branch which goes to the current block, not the terminator of the block we emitted + // into. This difference is because the merge block will _also_ end up in the same IR + // block and we can't tell the difference if we just get the terminator. + const auto& bb = current_spirv_function_->FindBlock(blk_id); + auto* terminator = (*bb).terminator(); + if (terminator->opcode() == spv::Op::OpBranchConditional) { + uint32_t true_id = terminator->GetSingleWordInOperand(1); + uint32_t false_id = terminator->GetSingleWordInOperand(2); + + auto iter = branch_conditional_to_if_.find(terminator); + TINT_ASSERT(iter != branch_conditional_to_if_.end()); + + auto* if_ = iter->second; + if (true_id == phi_blk_id) { + term = if_->True()->Terminator(); + } else if (false_id == phi_blk_id) { + term = if_->False()->Terminator(); + } + } + + if (term == nullptr) { + auto value_blk_iter = spirv_id_to_block_.find(blk_id); + auto* value_ir_blk = value_blk_iter->second; + + // In the case of a switch, the block can refer to the header of the switch, in this + // case it means we don't have a default block and we jump over the switch itself, + // so we need to insert this value into the terminator of the default block of the + // switch. + // + // We store this away as we may not know the switch yet, we need to wait until we + // get the control instruction and do the work later. + if (blk_id == header_id) { + value_for_default_block = Value(value_id); + continue; + } + + term = value_ir_blk->Terminator(); + } + + AddOperandToTerminator(term, value_id); + + if (auto* exit = term->As()) { + if (ctrl) { + TINT_ASSERT(ctrl == exit->ControlInstruction()); + } else { + ctrl = exit->ControlInstruction()->As(); + TINT_ASSERT(ctrl); + } + } else { + TINT_UNREACHABLE(); + } + } + + // No control instruction means there were no cases, so we can just ignore the switch, if we + // have a default then assign it straight through. + if (!ctrl) { + if (value_for_default_block) { + AddValue(inst.result_id(), value_for_default_block.value()); + } + return; + } + + // If the default block needs to be assigned a value + if (value_for_default_block) { + ctrl->DefaultBlock()->Terminator()->PushOperand(value_for_default_block.value()); + } + + // Push the result into the switch + auto* res = b_.InstructionResult(type); + ctrl->AddResult(res); + AddValue(inst.result_id(), res); + } + + void EmitImage(const spvtools::opt::Instruction& inst) { + auto* si = Value(inst.GetSingleWordInOperand(0)); + Emit(b_.CallExplicit( + Type(inst.type_id()), spirv::BuiltinFn::kOpImage, + Vector{si->Type()->As()->Image()}, Args(inst, 2)), + inst.result_id()); + } + + void EmitSampledImage(const spvtools::opt::Instruction& inst) { + auto* tex = Value(inst.GetSingleWordInOperand(0)); + auto* img_type = tex->Type()->As(); + TINT_ASSERT(img_type); + TINT_ASSERT(img_type->GetMultisampled() != type::Multisampled::kMultisampled) + << "Creating an OpTypeSampledImage from a multisampled image is not supported"; + Emit(b_.CallExplicit(Type(inst.type_id()), + spirv::BuiltinFn::kOpSampledImage, + Vector{tex->Type()}, Args(inst, 2)), + inst.result_id()); + } + + void EmitImageFetchOrRead(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + auto sampled_image = Value(inst.GetSingleWordInOperand(0)); + auto* coord = Value(inst.GetSingleWordInOperand(1)); + + Vector args = {sampled_image, coord}; + + if (inst.NumInOperands() > 2) { + uint32_t literal_mask = inst.GetSingleWordInOperand(2); + args.Push(b_.Constant(u32(literal_mask))); + + if (literal_mask != 0) { + args.Push(Value(inst.GetSingleWordInOperand(3))); + } + } else { + args.Push(b_.Zero(ty_.u32())); + } + + Emit(b_.Call(Type(inst.type_id()), fn, args), inst.result_id()); + } + + void EmitImageGatherDref(const spvtools::opt::Instruction& inst) { + auto sampled_image = Value(inst.GetSingleWordInOperand(0)); + auto* coord = Value(inst.GetSingleWordInOperand(1)); + auto* dref = Value(inst.GetSingleWordInOperand(2)); + + Vector args = {sampled_image, coord, dref}; + + if (inst.NumInOperands() > 3) { + uint32_t literal_mask = inst.GetSingleWordInOperand(3); + args.Push(b_.Constant(u32(literal_mask))); + + if (literal_mask != 0) { + TINT_ASSERT(static_cast(literal_mask) == + spv::ImageOperandsMask::ConstOffset); + TINT_ASSERT(inst.NumInOperands() > 4); + args.Push(Value(inst.GetSingleWordInOperand(4))); + } + } else { + args.Push(b_.Zero(ty_.u32())); + } + + Emit(b_.Call(Type(inst.type_id()), + spirv::BuiltinFn::kImageDrefGather, args), + inst.result_id()); + } + + void EmitImageGather(const spvtools::opt::Instruction& inst) { + auto sampled_image = Value(inst.GetSingleWordInOperand(0)); + auto* coord = Value(inst.GetSingleWordInOperand(1)); + auto* comp = Value(inst.GetSingleWordInOperand(2)); + + Vector args = {sampled_image, coord, comp}; + + if (inst.NumInOperands() > 3) { + uint32_t literal_mask = inst.GetSingleWordInOperand(3); + args.Push(b_.Constant(u32(literal_mask))); + + if (literal_mask != 0) { + TINT_ASSERT(static_cast(literal_mask) == + spv::ImageOperandsMask::ConstOffset); + TINT_ASSERT(inst.NumInOperands() > 4); + args.Push(Value(inst.GetSingleWordInOperand(4))); + } + } else { + args.Push(b_.Zero(ty_.u32())); + } + + Emit(b_.Call(Type(inst.type_id()), spirv::BuiltinFn::kImageGather, + args), + inst.result_id()); + } + + void EmitImageSample(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + auto sampled_image = Value(inst.GetSingleWordInOperand(0)); + auto* coord = Value(inst.GetSingleWordInOperand(1)); + + Vector args = {sampled_image, coord}; + + if (inst.NumInOperands() > 2) { + uint32_t literal_mask = inst.GetSingleWordInOperand(2); + args.Push(b_.Constant(u32(literal_mask))); + + if (literal_mask != 0) { + TINT_ASSERT(inst.NumInOperands() > 3); + } + + for (uint32_t i = 3; i < inst.NumInOperands(); ++i) { + args.Push(Value(inst.GetSingleWordInOperand(i))); + } + } else { + args.Push(b_.Zero(ty_.u32())); + } + + Emit(b_.Call(Type(inst.type_id()), fn, args), inst.result_id()); + } + + bool HasLod(uint32_t mask) { + return (mask & static_cast(spv::ImageOperandsMask::Lod)) != 0; + } + + void EmitImageSampleDepth(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + auto sampled_image = Value(inst.GetSingleWordInOperand(0)); + auto* coord = Value(inst.GetSingleWordInOperand(1)); + auto* dref = Value(inst.GetSingleWordInOperand(2)); + + Vector args = {sampled_image, coord, dref}; + + if (inst.NumInOperands() > 3) { + uint32_t literal_mask = inst.GetSingleWordInOperand(3); + args.Push(b_.Constant(u32(literal_mask))); + + if (literal_mask != 0) { + TINT_ASSERT(inst.NumInOperands() > 4); + } + + for (uint32_t i = 4; i < inst.NumInOperands(); ++i) { + args.Push(Value(inst.GetSingleWordInOperand(i))); + } + + if (HasLod(literal_mask)) { + core::ir::Value* lod = args[4]; + TINT_ASSERT(lod->Is()); + TINT_ASSERT(lod->Type()->As()); + + auto v = lod->As()->Value()->ValueAs(); + TINT_ASSERT(v == 0.0f) << "Dref LOD values must be 0.0"; + } + } else { + args.Push(b_.Zero(ty_.u32())); + } + + Emit(b_.Call(Type(inst.type_id()), fn, args), inst.result_id()); + } + + void EmitImageWrite(const spvtools::opt::Instruction& inst) { + auto* image = Value(inst.GetSingleWordInOperand(0)); + auto* coord = Value(inst.GetSingleWordInOperand(1)); + core::ir::Value* texel = Value(inst.GetSingleWordInOperand(2)); + + // Our intrinsic has a vec4 type, which matches what WGSL expects. Instead of creating more + // intrinsic entries, just turn the texel into a vec4. + auto* texel_ty = texel->Type(); + if (texel_ty->IsScalar()) { + auto* c = b_.Construct(ty_.vec4(texel_ty), texel); + EmitWithoutSpvResult(c); + texel = c->Result(); + } else { + auto* vec_ty = texel_ty->As(); + TINT_ASSERT(vec_ty); + + core::ir::Instruction* c = nullptr; + if (vec_ty->Width() == 2) { + c = b_.Construct(ty_.vec4(vec_ty->Type()), texel, b_.Zero(vec_ty)); + } else if (vec_ty->Width() == 3) { + c = b_.Construct(ty_.vec4(vec_ty->Type()), texel, b_.Zero(vec_ty->Type())); + } + if (c != nullptr) { + EmitWithoutSpvResult(c); + texel = c->Result(); + } + } + + Vector args = {image, coord, texel}; + if (inst.NumInOperands() > 3) { + uint32_t literal_mask = inst.GetSingleWordInOperand(3); + args.Push(b_.Constant(u32(literal_mask))); + TINT_ASSERT(literal_mask == 0); + } else { + args.Push(b_.Zero(ty_.u32())); + } + + Emit(b_.Call(ty_.void_(), spirv::BuiltinFn::kImageWrite, args), + inst.result_id()); + } + + void EmitImageQuery(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + auto* image = Value(inst.GetSingleWordInOperand(0)); + + auto* ty = Type(inst.type_id()); + Emit(b_.CallExplicit(ty, fn, Vector{ty->DeepestElement()}, image), + inst.result_id()); + } + + void EmitImageQuerySizeLod(const spvtools::opt::Instruction& inst) { + auto* image = Value(inst.GetSingleWordInOperand(0)); + auto* level = Value(inst.GetSingleWordInOperand(1)); + + auto* ty = Type(inst.type_id()); + Emit(b_.CallExplicit(ty, spirv::BuiltinFn::kImageQuerySizeLod, + Vector{ty->DeepestElement()}, image, level), + inst.result_id()); + } + + void EmitAtomicSigned(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + core::ir::Value* v = Value(inst.GetSingleWordOperand(2)); + TINT_ASSERT(v->Type()->UnwrapPtr()->Is()); + EmitSpirvBuiltinCall(inst, fn); + } + + void EmitAtomicUnsigned(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) { + core::ir::Value* v = Value(inst.GetSingleWordOperand(2)); + TINT_ASSERT(v->Type()->UnwrapPtr()->Is()); + EmitSpirvBuiltinCall(inst, fn); + } + + void EmitArrayLength(const spvtools::opt::Instruction& inst) { + auto strct = Value(inst.GetSingleWordInOperand(0)); + auto field_index = inst.GetSingleWordInOperand(1); + + auto* ptr = strct->Type()->As(); + TINT_ASSERT(ptr); + + auto* ty = ptr->StoreType()->As(); + TINT_ASSERT(ty); + + auto* access = + b_.Access(ty_.ptr(ptr->AddressSpace(), ty->Members().Back()->Type(), ptr->Access()), + strct, u32(field_index)); + EmitWithoutSpvResult(access); + + Emit(b_.Call(Type(inst.type_id()), core::BuiltinFn::kArrayLength, Vector{access->Result()}), + inst.result_id()); + } + + void EmitControlBarrier(const spvtools::opt::Instruction& inst) { + auto get_constant = [&](uint32_t idx) { + uint32_t id = inst.GetSingleWordOperand(idx); + if (auto* constant = spirv_context_->get_constant_mgr()->FindDeclaredConstant(id)) { + return constant->GetU32(); + } + TINT_ICE() << "invalid or missing operands for control barrier"; + }; + + uint32_t execution = get_constant(0); + uint32_t memory = get_constant(1); + uint32_t semantics = get_constant(2); + + TINT_ASSERT(execution == uint32_t(spv::Scope::Workgroup)) + << "unsupported control barrier execution scope: " + << "expected Workgroup (2), got: " << execution; + + if (semantics & uint32_t(spv::MemorySemanticsMask::AcquireRelease)) { + semantics &= ~static_cast(spv::MemorySemanticsMask::AcquireRelease); + } else { + TINT_ICE() << "control barrier semantics requires acquire and release"; + } + TINT_ASSERT(memory == uint32_t(spv::Scope::Workgroup)) + << "control barrier requires workgroup memory scope"; + + if (semantics & uint32_t(spv::MemorySemanticsMask::WorkgroupMemory)) { + EmitWithoutSpvResult(b_.Call(ty_.void_(), core::BuiltinFn::kWorkgroupBarrier)); + semantics &= ~static_cast(spv::MemorySemanticsMask::WorkgroupMemory); + } + + if (semantics & uint32_t(spv::MemorySemanticsMask::UniformMemory)) { + EmitWithoutSpvResult(b_.Call(ty_.void_(), core::BuiltinFn::kStorageBarrier)); + semantics &= ~static_cast(spv::MemorySemanticsMask::UniformMemory); + } + + if (semantics & uint32_t(spv::MemorySemanticsMask::ImageMemory)) { + EmitWithoutSpvResult(b_.Call(ty_.void_(), core::BuiltinFn::kTextureBarrier)); + semantics &= ~static_cast(spv::MemorySemanticsMask::ImageMemory); + } + + TINT_ASSERT(!semantics) << "unsupported control barrier semantics: " << semantics; + } + + void CheckAtomicNotFloat(const spvtools::opt::Instruction& inst) { + auto* ty = Type(inst.type_id()); + TINT_ASSERT(!ty->UnwrapPtr()->IsFloatScalar()) + << "Atomic operations on floating point values not supported."; + } + + void EmitAtomicStore(const spvtools::opt::Instruction& inst) { + auto* v = Value(inst.GetSingleWordInOperand(0)); + auto* ty = v->Type()->UnwrapPtr(); + TINT_ASSERT(!ty->IsFloatScalar()) + << "Atomic operations on floating point values not supported."; + + EmitWithoutSpvResult(b_.Call( + ty_.void_(), spirv::BuiltinFn::kAtomicStore, Args(inst, 0))); + } + + void EmitBitcast(const spvtools::opt::Instruction& inst) { + auto val = Value(inst.GetSingleWordInOperand(0)); + auto ty = Type(inst.type_id()); + Emit(b_.Bitcast(ty, val), inst.result_id()); + } + + core::ir::ControlInstruction* StopWalkingAt(uint32_t id) { + auto iter = walk_stop_blocks_.find(id); + if (iter != walk_stop_blocks_.end()) { + return iter->second; + } + return nullptr; + } + + core::ir::Loop* ContinueTarget(uint32_t id) { + auto iter = continue_targets_.find(id); + if (iter != continue_targets_.end()) { + return iter->second; + } + return nullptr; + } + + void EmitBranch(spvtools::opt::Instruction& inst) { + auto dest_id = inst.GetSingleWordInOperand(0); + + // Disallow fallthrough + for (auto& switch_blocks : current_switch_blocks_) { + TINT_ASSERT(switch_blocks.count(dest_id) == 0) + << "switch fallthrough not supported by the SPIR-V reader"; + } + + // The destination is a continuing block, so insert a `continue` + if (auto* loop = ContinueTarget(dest_id)) { + auto* new_inst = b_.Continue(loop); + auto id = spirv_context_->get_instr_block(&inst)->id(); + inst_to_spirv_block_[new_inst] = id; + EmitWithoutResult(new_inst); + return; + } + // If this is branching to a previous merge block then we're done. It can be a previous + // merge block in the case of an `if` breaking out of a `switch` or `loop`. + if (auto* ctrl_inst = StopWalkingAt(dest_id)) { + if (auto* loop = ctrl_inst->As()) { + // Going to the merge in a loop body has to be a break regardless of nesting level. + + if (InBlock(loop->Body()) && !InBlock(loop->Continuing())) { + EmitWithoutResult(b_.Exit(ctrl_inst)); + } + } else if (ctrl_inst->Is()) { + EmitWithoutResult(b_.Exit(ctrl_inst)); + } + return; + } + + TINT_ASSERT(current_spirv_function_); + const auto& bb = current_spirv_function_->FindBlock(dest_id); + + EmitBlock(current_block_, *bb); + } + + // Given a true and false branch find if there is a common convergence point before the merge + // block. + std::optional FindPremergeId(uint32_t true_id, + uint32_t false_id, + std::optional merge_id) { + auto* cfg = spirv_context_->cfg(); + + // We need a merge block, the true and false to be unique and the true and false to not be + // the merge. + if (!merge_id || true_id == false_id || true_id == merge_id || false_id == merge_id) { + return std::nullopt; + } + + // Get the list of blocks from the true branch to the merge + std::list true_blocks; + cfg->ComputeStructuredOrder( + current_spirv_function_, &*(current_spirv_function_->FindBlock(true_id)), + &*(current_spirv_function_->FindBlock(merge_id.value())), &true_blocks); + + // Get the list of blocks from the false branch to the merge + std::list false_blocks; + cfg->ComputeStructuredOrder( + current_spirv_function_, &*(current_spirv_function_->FindBlock(false_id)), + &*(current_spirv_function_->FindBlock(merge_id.value())), &false_blocks); + + auto& true_end = true_blocks.back(); + auto& false_end = false_blocks.back(); + + // We only consider the block as returning if it didn't return through + // the merge block. (I.e. it's a direct exit from inside the branch + // itself. + bool true_returns = true_end->id() != merge_id && true_end->IsReturn(); + bool false_returns = false_end->id() != merge_id && false_end->IsReturn(); + // If one of the blocks returns but the other doesn't, then we can't + // have a premerge block. + if (true_returns != false_returns) { + return std::nullopt; + } + + // If they don't return, both blocks must merge to the same place. + if (!true_returns && (true_end->id() != false_end->id())) { + return std::nullopt; + } + + // If these aren't returns, then remove the merge blocks. + if (!true_returns) { + true_blocks.pop_back(); + false_blocks.pop_back(); + } + + std::optional id = std::nullopt; + while (!true_blocks.empty() && !false_blocks.empty()) { + auto* tb = true_blocks.back(); + if (tb != false_blocks.back()) { + break; + } + + id = tb->id(); + + true_blocks.pop_back(); + false_blocks.pop_back(); + } + + // If this is already a stop block, so it can't be a premerge + if (id.has_value() && walk_stop_blocks_.contains(id.value())) { + return std::nullopt; + } + return id; + } + + core::ir::ControlInstruction* ExitFor(core::ir::ControlInstruction* ctrl, + core::ir::ControlInstruction* parent) { + // If you have a BranchConditional inside a BranchConditional where + // the inner does not have a merge block, it can branch out to the + // merge of the outer conditional. But, WGSL doesn't allow that, so + // just treat it as an exit of the inner block. + if (ctrl->Is() && parent->Is()) { + return parent; + } + return ctrl; + } + + core::ir::Instruction* EmitBranchStopBlock(core::ir::ControlInstruction* ctrl, + core::ir::If* if_, + core::ir::Block* blk, + uint32_t target) { + if (auto* loop = ContinueTarget(target)) { + auto* cont = b_.Continue(loop); + blk->Append(cont); + return cont; + } + + auto iter = merge_to_premerge_.find(target); + if (iter != merge_to_premerge_.end()) { + // Branch to a merge block, but skipping over an expected premerge block + // so we need a guard. + if (!iter->second.condition) { + b_.InsertBefore(iter->second.parent, + [&] { iter->second.condition = b_.Var("execute_premerge", true); }); + } + b_.Append(blk, [&] { b_.Store(iter->second.condition, false); }); + } + + auto* exit = b_.Exit(ExitFor(ctrl, if_)); + blk->Append(exit); + return exit; + } + + bool ProcessBranchAsLoopHeader(core::ir::Value* cond, uint32_t true_id, uint32_t false_id) { + bool true_is_header = loop_headers_.count(true_id) > 0; + bool false_is_header = loop_headers_.count(false_id) > 0; + + if (!true_is_header && !false_is_header) { + return false; + } + + core::ir::Loop* loop = nullptr; + uint32_t merge_id = 0; + + if (true_is_header) { + const auto& bb_header = current_spirv_function_->FindBlock(true_id); + merge_id = (*bb_header).MergeBlockIdIfAny(); + + loop = loop_headers_[true_id]; + + } else { + const auto& bb_header = current_spirv_function_->FindBlock(false_id); + merge_id = (*bb_header).MergeBlockIdIfAny(); + + loop = loop_headers_[false_id]; + } + TINT_ASSERT(merge_id > 0); + + // The only time a loop continuing will be in current blocks is if + // we're inside the continuing block itself. + // + // Note, we may _not_ be in the IR continuing block. This can happen + // in the case of a SPIR-V loop where the header_id and continue_id + // are the same. We'll be emitting into the IR body, but branch to + // the header because that's also the continuing in SPIR-V. + if (current_blocks_.count(loop->Continuing()) != 0u) { + if (true_id == merge_id && false_is_header) { + EmitWithoutResult(b_.BreakIf(loop, cond)); + return true; + } + if (false_id == merge_id && true_is_header) { + auto* val = b_.Not(cond); + EmitWithoutSpvResult(val); + EmitWithoutResult(b_.BreakIf(loop, val)); + return true; + } + } + return false; + } + + void EmitPremergeBlock(uint32_t merge_id, + uint32_t premerge_start_id, + core::ir::If* premerge_if_) { + auto iter = merge_to_premerge_.find(merge_id); + TINT_ASSERT(iter != merge_to_premerge_.end()); + + // If we created a condition guard, we need to swap the premerge `true` condition with + // the condition variable. + if (iter->second.condition) { + auto* premerge_cond = b_.Load(iter->second.condition); + EmitWithoutSpvResult(premerge_cond); + premerge_if_->SetOperand(core::ir::If::kConditionOperandOffset, + premerge_cond->Result()); + } + merge_to_premerge_.erase(iter); + + EmitWithoutResult(premerge_if_); + + const auto& bb_premerge = current_spirv_function_->FindBlock(premerge_start_id); + EmitBlockParent(premerge_if_->True(), *bb_premerge); + if (!premerge_if_->True()->Terminator()) { + premerge_if_->True()->Append(b_.Exit(premerge_if_)); + } + + premerge_if_->False()->Append(b_.Unreachable()); + } + + void EmitIfBranch(uint32_t id, core::ir::If* if_, core::ir::Block* blk) { + const auto& bb = current_spirv_function_->FindBlock(id); + EmitBlockParent(blk, *bb); + if (!blk->Terminator()) { + blk->Append(b_.Exit(if_)); + } + } + + void EmitBranchConditional(const spvtools::opt::BasicBlock& bb, + const spvtools::opt::Instruction& inst) { + auto cond = Value(inst.GetSingleWordInOperand(0)); + auto true_id = inst.GetSingleWordInOperand(1); + auto false_id = inst.GetSingleWordInOperand(2); + + if (ProcessBranchAsLoopHeader(cond, true_id, false_id)) { + return; + } + + // If the true and false block are the same, then we change the condition into + // `cond || true` so that we always take the true block, the false block will be marked + // unreachable. + if (true_id == false_id) { + auto* binary = b_.Binary(core::BinaryOp::kOr, cond->Type(), cond, b_.Constant(true)); + EmitWithoutSpvResult(binary); + cond = binary->Result(); + } + + auto* if_ = b_.If(cond); + EmitWithoutResult(if_); + + branch_conditional_to_if_.insert({&inst, if_}); + + std::optional merge_id = std::nullopt; + + auto* merge_inst = bb.GetMergeInst(); + if (bb.GetLoopMergeInst()) { + // If this is a loop merge block, then the merge instruction is for + // the loop, not the branch conditional. + merge_inst = nullptr; + } else if (merge_inst != nullptr) { + merge_id = merge_inst->GetSingleWordInOperand(0); + walk_stop_blocks_.insert({merge_id.value(), if_}); + } + + TINT_ASSERT(current_spirv_function_); + + // Determine if there is a premerge block to handle + std::optional premerge_start_id = FindPremergeId(true_id, false_id, merge_id); + + // If we found the start of a premerge, push it onto the merge stack so this ends up being a + // temporary merge block for the if branches. + core::ir::If* premerge_if_ = nullptr; + if (premerge_start_id.has_value()) { + // Must have a merge to have a premerge + merge_to_premerge_.insert({merge_id.value(), PremergeInfo{if_, {}}}); + premerge_if_ = b_.If(b_.Constant(true)); + walk_stop_blocks_.insert({premerge_start_id.value(), premerge_if_}); + } + if (auto* ctrl = StopWalkingAt(true_id)) { + auto* new_inst = EmitBranchStopBlock(ctrl, if_, if_->True(), true_id); + inst_to_spirv_block_[new_inst] = bb.id(); + } else { + EmitIfBranch(true_id, if_, if_->True()); + } + + // Pre-SPIRV 1.6 the true and false blocks could be the same. If that's the case then we + // will have changed the condition and the false block is now unreachable. + if (false_id == true_id) { + if_->False()->Append(b_.Unreachable()); + } else if (auto* ctrl = StopWalkingAt(false_id)) { + auto* new_inst = EmitBranchStopBlock(ctrl, if_, if_->False(), false_id); + inst_to_spirv_block_[new_inst] = bb.id(); + } else { + EmitIfBranch(false_id, if_, if_->False()); + } + + // There was a premerge, remove it from the merge stack and then emit the premerge into an + // `if true` block in order to maintain re-convergence guarantees. The premerge will contain + // all the blocks up to the merge block. + if (premerge_start_id.has_value()) { + EmitPremergeBlock(merge_id.value(), premerge_start_id.value(), premerge_if_); + } + + // Emit the merge block if it exists. + if (merge_id.has_value()) { + const auto& bb_merge = current_spirv_function_->FindBlock(merge_id.value()); + EmitBlock(current_block_, *bb_merge); + } + } + + void EmitLoop(const spvtools::opt::BasicBlock& bb) { + // This just handles creating the loop itself, the rest of the processing + // of the continue and merge blocks will be handled when we deal with the + // LoopMerge instruction itself. We have to setup the loop early in order + // to capture instructions which come in the header before the LoopMerge. + auto* loop = b_.Loop(); + EmitWithoutResult(loop); + + // A `loop` header block can also be the merge block for an `if`. In that the case, replace + // the `if` information in the stop blocks with the loop as this must be the `if` merge + // block and the `if` is complete. + walk_stop_blocks_[bb.id()] = loop; + } + + void EmitLoopMerge(const spvtools::opt::BasicBlock& bb, + const spvtools::opt::Instruction& inst) { + auto merge_id = inst.GetSingleWordInOperand(0); + auto continue_id = inst.GetSingleWordInOperand(1); + auto header_id = bb.id(); + + // The loop was created in `EmitLoop` and set as the stop block value for + // the header block. Retrieve the loop from the stop list. + auto* loop = StopWalkingAt(header_id)->As(); + TINT_ASSERT(loop); + + loop_headers_.insert({header_id, loop}); + continue_targets_.insert({continue_id, loop}); + + // Insert the stop blocks + walk_stop_blocks_.insert({merge_id, loop}); + if (continue_id != header_id) { + walk_stop_blocks_.insert({continue_id, loop}); + } + + // The remainder of the loop body will process when we hit the + // BranchConditional or Branch after the LoopMerge. We're already + // processing into the loop body from the `EmitLoop` code above so just + // continue emitting. + + // The merge block will be emitted by the `EmitBlock` code after the + // instructions in the loop header are emitted. + } + + void EmitSwitch(const spvtools::opt::BasicBlock& bb, const spvtools::opt::Instruction& inst) { + auto* selector = Value(inst.GetSingleWordInOperand(0)); + auto default_id = inst.GetSingleWordInOperand(1); + + auto* switch_ = b_.Switch(selector); + EmitWithoutResult(switch_); + + auto* merge_inst = bb.GetMergeInst(); + TINT_ASSERT(merge_inst); + + auto merge_id = merge_inst->GetSingleWordInOperand(0); + walk_stop_blocks_.insert({merge_id, switch_}); + + size_t switch_blocks_id = current_switch_blocks_.size(); + current_switch_blocks_.push_back({}); + + auto* default_blk = b_.DefaultCase(switch_); + if (default_id != merge_id) { + current_switch_blocks_[switch_blocks_id].emplace(default_id); + + const auto& bb_default = current_spirv_function_->FindBlock(default_id); + EmitBlockParent(default_blk, *bb_default); + } + if (!default_blk->Terminator()) { + default_blk->Append(b_.ExitSwitch(switch_)); + } + + std::unordered_map block_id_to_case; + block_id_to_case[default_id] = &(switch_->Cases().Back()); + + for (uint32_t i = 2; i < inst.NumInOperandWords(); i += 2) { + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + if (blk_id != merge_id) { + current_switch_blocks_[switch_blocks_id].emplace(blk_id); + } + } + + // For each selector. + for (uint32_t i = 2; i < inst.NumInOperandWords(); i += 2) { + auto literal = inst.GetSingleWordInOperand(i); + auto blk_id = inst.GetSingleWordInOperand(i + 1); + + core::ir::Constant* sel = nullptr; + if (selector->Type()->Is()) { + sel = b_.Constant(i32(literal)); + } else { + sel = b_.Constant(u32(literal)); + } + + // Determine if we've seen this block and should combine selectors + auto iter = block_id_to_case.find(blk_id); + if (iter != block_id_to_case.end()) { + iter->second->selectors.Push(core::ir::Switch::CaseSelector{sel}); + continue; + } + + core::ir::Block* blk = b_.Case(switch_, Vector{sel}); + if (blk_id != merge_id) { + const auto& basic_block = current_spirv_function_->FindBlock(blk_id); + EmitBlockParent(blk, *basic_block); + } + if (!blk->Terminator()) { + blk->Append(b_.ExitSwitch(switch_)); + } + block_id_to_case[blk_id] = &(switch_->Cases().Back()); + } + + current_switch_blocks_.pop_back(); + + const auto& bb_merge = current_spirv_function_->FindBlock(merge_id); + EmitBlock(current_block_, *bb_merge); + } + + Vector Args(const spvtools::opt::Instruction& inst, uint32_t start) { + Vector args; + for (uint32_t i = start; i < inst.NumOperandWords(); i++) { + args.Push(Value(inst.GetSingleWordOperand(i))); + } + return args; + } + + void EmitBuiltinCall(const spvtools::opt::Instruction& inst, core::BuiltinFn fn) { + Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 2)), inst.result_id()); + } + + void EmitSpirvExplicitBuiltinCall(const spvtools::opt::Instruction& inst, + spirv::BuiltinFn fn, + uint32_t first_operand_idx = 2) { + Emit(b_.CallExplicit(Type(inst.type_id()), fn, + Vector{Type(inst.type_id())->DeepestElement()}, + Args(inst, first_operand_idx)), + inst.result_id()); + } + + void EmitSpirvBuiltinCall(const spvtools::opt::Instruction& inst, + spirv::BuiltinFn fn, + uint32_t first_operand_idx = 2) { + Emit(b_.Call(Type(inst.type_id()), fn, + Args(inst, first_operand_idx)), + inst.result_id()); + } + + void EmitBitCount(const spvtools::opt::Instruction& inst) { + auto* res_ty = Type(inst.type_id()); + Emit(b_.CallExplicit(res_ty, spirv::BuiltinFn::kBitCount, + Vector{res_ty->DeepestElement()}, + Args(inst, 2)), + inst.result_id()); + } + + /// @param inst the SPIR-V instruction + /// Note: This isn't technically correct, but there is no `kill` equivalent in WGSL. The closets + /// we have is `discard` which maps to `OpDemoteToHelperInvocation` in SPIR-V. + void EmitKill([[maybe_unused]] const spvtools::opt::Instruction& inst) { + // TODO(430084563): Log a warning that the `OpKill` or `OpTerminateInvocation` will not have + // the same semantics as the original SPIR-V. + EmitWithoutResult(b_.Discard()); + + // An `OpKill` is a terminator in SPIR-V. `discard` is not a terminator in WGSL. After the + // `discard` we inject a `return` for the current function. This is similar in spirit to + // what `OpKill` does although not totally correct (i.e. we don't early return from calling + // functions, just the function where `OpKill` was emitted. There are also limited places in + // which `OpKill` can be used. So, we don't have to worry about it in a `continuing` block + // because the continuing must end with a branching terminator which `OpKill` does not + // branch. + if (current_function_->ReturnType()->Is()) { + EmitWithoutResult(b_.Return(current_function_)); + } else { + EmitWithoutResult( + b_.Return(current_function_, b_.Zero(current_function_->ReturnType()))); + } + } + + /// @param inst the SPIR-V instruction for OpCopyObject + void EmitCopyObject(const spvtools::opt::Instruction& inst) { + // Make the result Id a pointer to the original copied value. + auto* v = Value(inst.GetSingleWordOperand(2)); + + if (v->Type()->IsHandle() || v->Type()->Is()) { + values_.Add(inst.result_id(), v); + } else { + auto* l = b_.Let(v); + Emit(l, inst.result_id()); + } + } + + /// @param inst the SPIR-V instruction for OpCopyMemory + void EmitCopyMemory(const spvtools::opt::Instruction& inst) { + auto load = b_.Load(Value(inst.GetSingleWordOperand(1))); + EmitWithoutSpvResult(load); + EmitWithoutResult(b_.Store(Value(inst.GetSingleWordOperand(0)), load)); + } + + /// @param inst the SPIR-V instruction for OpExtInst + void EmitExtInst(const spvtools::opt::Instruction& inst) { + auto inst_set = inst.GetSingleWordInOperand(0); + if (ignored_imports_.count(inst_set) > 0) { + // Ignore it but don't error out. + return; + } + if (glsl_std_450_imports_.count(inst_set) > 0) { + EmitGlslStd450ExtInst(inst); + return; + } + + TINT_UNIMPLEMENTED() << "unhandled extended instruction import with ID " + << inst.GetSingleWordInOperand(0); + } + + // Returns the WGSL standard library function for the given GLSL.std.450 extended instruction + // operation code. This handles GLSL functions which directly translate to the WGSL equivalent. + // Any non-direct translation is returned as `kNone`. + core::BuiltinFn GetGlslStd450WgslEquivalentFuncName(uint32_t ext_opcode) { + switch (ext_opcode) { + case GLSLstd450Acos: + return core::BuiltinFn::kAcos; + case GLSLstd450Acosh: + return core::BuiltinFn::kAcosh; + case GLSLstd450Asin: + return core::BuiltinFn::kAsin; + case GLSLstd450Asinh: + return core::BuiltinFn::kAsinh; + case GLSLstd450Atan: + return core::BuiltinFn::kAtan; + case GLSLstd450Atanh: + return core::BuiltinFn::kAtanh; + case GLSLstd450Atan2: + return core::BuiltinFn::kAtan2; + case GLSLstd450Ceil: + return core::BuiltinFn::kCeil; + case GLSLstd450Cos: + return core::BuiltinFn::kCos; + case GLSLstd450Cosh: + return core::BuiltinFn::kCosh; + case GLSLstd450Cross: + return core::BuiltinFn::kCross; + case GLSLstd450Degrees: + return core::BuiltinFn::kDegrees; + case GLSLstd450Determinant: + return core::BuiltinFn::kDeterminant; + case GLSLstd450Distance: + return core::BuiltinFn::kDistance; + case GLSLstd450Exp: + return core::BuiltinFn::kExp; + case GLSLstd450Exp2: + return core::BuiltinFn::kExp2; + case GLSLstd450FAbs: + return core::BuiltinFn::kAbs; + case GLSLstd450FSign: + return core::BuiltinFn::kSign; + case GLSLstd450Floor: + return core::BuiltinFn::kFloor; + case GLSLstd450Fract: + return core::BuiltinFn::kFract; + case GLSLstd450Fma: + return core::BuiltinFn::kFma; + case GLSLstd450InverseSqrt: + return core::BuiltinFn::kInverseSqrt; + case GLSLstd450Length: + return core::BuiltinFn::kLength; + case GLSLstd450Log: + return core::BuiltinFn::kLog; + case GLSLstd450Log2: + return core::BuiltinFn::kLog2; + case GLSLstd450NClamp: + case GLSLstd450FClamp: // FClamp is less prescriptive about NaN operands + return core::BuiltinFn::kClamp; + case GLSLstd450ModfStruct: + return core::BuiltinFn::kModf; + case GLSLstd450FrexpStruct: + return core::BuiltinFn::kFrexp; + case GLSLstd450NMin: + case GLSLstd450FMin: // FMin is less prescriptive about NaN operands + return core::BuiltinFn::kMin; + case GLSLstd450NMax: + case GLSLstd450FMax: // FMax is less prescriptive about NaN operands + return core::BuiltinFn::kMax; + case GLSLstd450FMix: + return core::BuiltinFn::kMix; + case GLSLstd450PackSnorm4x8: + return core::BuiltinFn::kPack4X8Snorm; + case GLSLstd450PackUnorm4x8: + return core::BuiltinFn::kPack4X8Unorm; + case GLSLstd450PackSnorm2x16: + return core::BuiltinFn::kPack2X16Snorm; + case GLSLstd450PackUnorm2x16: + return core::BuiltinFn::kPack2X16Unorm; + case GLSLstd450PackHalf2x16: + return core::BuiltinFn::kPack2X16Float; + case GLSLstd450Pow: + return core::BuiltinFn::kPow; + case GLSLstd450Radians: + return core::BuiltinFn::kRadians; + case GLSLstd450Round: + case GLSLstd450RoundEven: + return core::BuiltinFn::kRound; + case GLSLstd450Sin: + return core::BuiltinFn::kSin; + case GLSLstd450Sinh: + return core::BuiltinFn::kSinh; + case GLSLstd450SmoothStep: + return core::BuiltinFn::kSmoothstep; + case GLSLstd450Sqrt: + return core::BuiltinFn::kSqrt; + case GLSLstd450Step: + return core::BuiltinFn::kStep; + case GLSLstd450Tan: + return core::BuiltinFn::kTan; + case GLSLstd450Tanh: + return core::BuiltinFn::kTanh; + case GLSLstd450Trunc: + return core::BuiltinFn::kTrunc; + case GLSLstd450UnpackSnorm4x8: + return core::BuiltinFn::kUnpack4X8Snorm; + case GLSLstd450UnpackUnorm4x8: + return core::BuiltinFn::kUnpack4X8Unorm; + case GLSLstd450UnpackSnorm2x16: + return core::BuiltinFn::kUnpack2X16Snorm; + case GLSLstd450UnpackUnorm2x16: + return core::BuiltinFn::kUnpack2X16Unorm; + case GLSLstd450UnpackHalf2x16: + return core::BuiltinFn::kUnpack2X16Float; + + default: + break; + } + return core::BuiltinFn::kNone; + } + + spirv::BuiltinFn GetGlslStd450SpirvEquivalentFuncName(uint32_t ext_opcode) { + switch (ext_opcode) { + case GLSLstd450SAbs: + return spirv::BuiltinFn::kAbs; + case GLSLstd450SSign: + return spirv::BuiltinFn::kSign; + case GLSLstd450Normalize: + return spirv::BuiltinFn::kNormalize; + case GLSLstd450MatrixInverse: + return spirv::BuiltinFn::kInverse; + case GLSLstd450SMax: + return spirv::BuiltinFn::kSMax; + case GLSLstd450SMin: + return spirv::BuiltinFn::kSMin; + case GLSLstd450SClamp: + return spirv::BuiltinFn::kSClamp; + case GLSLstd450UMax: + return spirv::BuiltinFn::kUMax; + case GLSLstd450UMin: + return spirv::BuiltinFn::kUMin; + case GLSLstd450UClamp: + return spirv::BuiltinFn::kUClamp; + case GLSLstd450FindILsb: + return spirv::BuiltinFn::kFindILsb; + case GLSLstd450FindSMsb: + return spirv::BuiltinFn::kFindSMsb; + case GLSLstd450FindUMsb: + return spirv::BuiltinFn::kFindUMsb; + case GLSLstd450Refract: + return spirv::BuiltinFn::kRefract; + case GLSLstd450Reflect: + return spirv::BuiltinFn::kReflect; + case GLSLstd450FaceForward: + return spirv::BuiltinFn::kFaceForward; + case GLSLstd450Ldexp: + return spirv::BuiltinFn::kLdexp; + case GLSLstd450Modf: + return spirv::BuiltinFn::kModf; + case GLSLstd450Frexp: + return spirv::BuiltinFn::kFrexp; + default: + break; + } + return spirv::BuiltinFn::kNone; + } + + Vector GlslStd450ExplicitParams(uint32_t ext_opcode, + const core::type::Type* result_ty) { + if (ext_opcode == GLSLstd450SSign || ext_opcode == GLSLstd450SAbs || + ext_opcode == GLSLstd450SMax || ext_opcode == GLSLstd450SMin || + ext_opcode == GLSLstd450SClamp || ext_opcode == GLSLstd450UMax || + ext_opcode == GLSLstd450UMin || ext_opcode == GLSLstd450UClamp || + ext_opcode == GLSLstd450FindILsb || ext_opcode == GLSLstd450FindSMsb || + ext_opcode == GLSLstd450FindUMsb) { + return {result_ty->DeepestElement()}; + } + return {}; + } + + /// @param inst the SPIR-V instruction for OpAccessChain + void EmitGlslStd450ExtInst(const spvtools::opt::Instruction& inst) { + const auto ext_opcode = inst.GetSingleWordInOperand(1); + auto* spv_ty = Type(inst.type_id()); + + Vector operands; + // All parameters to GLSL.std.450 extended instructions are IDs. + for (uint32_t idx = 2; idx < inst.NumInOperands(); ++idx) { + operands.Push(Value(inst.GetSingleWordInOperand(idx))); + } + + const auto wgsl_fn = GetGlslStd450WgslEquivalentFuncName(ext_opcode); + if (wgsl_fn == core::BuiltinFn::kModf) { + // For `ModfStruct`, which is, essentially, a WGSL `modf` instruction + // we need some special handling. The result type that we produce + // must be the SPIR-V type as we don't know how the result is used + // later. So, we need to make the WGSL query and re-construct an + // object of the right SPIR-V type. We can't, easily, do this later + // as we lose the SPIR-V type as soon as we replace the result of the + // `modf`. So, inline the work here to generate the correct results. + + auto* mem_ty = operands[0]->Type(); + auto* result_ty = core::type::CreateModfResult(ty_, ir_.symbols, mem_ty); + + auto* call = b_.Call(result_ty, wgsl_fn, operands); + auto* fract = b_.Access(mem_ty, call, 0_u); + auto* whole = b_.Access(mem_ty, call, 1_u); + + EmitWithoutSpvResult(call); + EmitWithoutSpvResult(fract); + EmitWithoutSpvResult(whole); + Emit(b_.Construct(spv_ty, fract, whole), inst.result_id()); + return; + } + if (wgsl_fn == core::BuiltinFn::kFrexp) { + // For `FrexpStruct`, which is, essentially, a WGSL `frexp` + // instruction we need some special handling. The result type that we + // produce must be the SPIR-V type as we don't know how the result is + // used later. So, we need to make the WGSL query and re-construct an + // object of the right SPIR-V type. We can't, easily, do this later + // as we lose the SPIR-V type as soon as we replace the result of the + // `frexp`. So, inline the work here to generate the correct results. + + auto* mem_ty = operands[0]->Type(); + auto* result_ty = core::type::CreateFrexpResult(ty_, ir_.symbols, mem_ty); + + auto* call = b_.Call(result_ty, wgsl_fn, operands); + auto* fract = b_.Access(mem_ty, call, 0_u); + auto* exp = b_.Access(ty_.MatchWidth(ty_.i32(), mem_ty), call, 1_u); + auto* exp_res = exp->Result(); + + EmitWithoutSpvResult(call); + EmitWithoutSpvResult(fract); + EmitWithoutSpvResult(exp); + + if (auto* str = spv_ty->As()) { + auto* exp_ty = str->Members()[1]->Type(); + if (exp_ty->DeepestElement()->IsUnsignedIntegerScalar()) { + auto* uexp = b_.Bitcast(exp_ty, exp); + exp_res = uexp->Result(); + EmitWithoutSpvResult(uexp); + } + } + + Emit(b_.Construct(spv_ty, fract, exp_res), inst.result_id()); + return; + } + if (wgsl_fn != core::BuiltinFn::kNone) { + Emit(b_.Call(spv_ty, wgsl_fn, operands), inst.result_id()); + return; + } + + const auto spv_fn = GetGlslStd450SpirvEquivalentFuncName(ext_opcode); + if (spv_fn != spirv::BuiltinFn::kNone) { + auto explicit_params = GlslStd450ExplicitParams(ext_opcode, spv_ty); + Emit(b_.CallExplicit(spv_ty, spv_fn, explicit_params, operands), + inst.result_id()); + return; + } + + TINT_UNIMPLEMENTED() << "unhandled GLSL.std.450 instruction " << ext_opcode; + } + + /// @param inst the SPIR-V instruction for OpAccessChain + void EmitAccess(const spvtools::opt::Instruction& inst) { + Vector indices = Args(inst, 3); + auto* base = Value(inst.GetSingleWordOperand(2)); + + if (indices.IsEmpty()) { + // There are no indices, so just forward the base object. + AddValue(inst.result_id(), base); + return; + } + + // Propagate the access mode of the base object. + auto access_mode = core::Access::kUndefined; + if (auto* ptr = base->Type()->As()) { + access_mode = ptr->Access(); + } + + auto* access = b_.Access(Type(inst.type_id(), access_mode), base, std::move(indices)); + Emit(access, inst.result_id()); + } + + /// @param inst the SPIR-V instruction + /// @param op the unary operator to use + void EmitUnary(const spvtools::opt::Instruction& inst, + core::UnaryOp op, + uint32_t first_operand_idx = 2) { + auto* val = Value(inst.GetSingleWordOperand(first_operand_idx)); + auto* unary = b_.Unary(op, val); + Emit(unary, inst.result_id()); + } + + /// @param inst the SPIR-V instruction + /// @param op the binary operator to use + void EmitBinary(const spvtools::opt::Instruction& inst, + core::BinaryOp op, + uint32_t first_operand_idx = 2) { + auto* lhs = Value(inst.GetSingleWordOperand(first_operand_idx)); + auto* rhs = Value(inst.GetSingleWordOperand(first_operand_idx + 1)); + auto* binary = b_.Binary(op, Type(inst.type_id()), lhs, rhs); + Emit(binary, inst.result_id()); + } + + /// Emits the logical negation of the result of the given SPIR-V instruction. + /// @param inst the SPIR-V instruction + /// @param op the binary operator to use + void EmitInvertedBinary(const spvtools::opt::Instruction& inst, core::BinaryOp op) { + auto* lhs = Value(inst.GetSingleWordOperand(2)); + auto* rhs = Value(inst.GetSingleWordOperand(3)); + auto* binary = b_.Binary(op, Type(inst.type_id()), lhs, rhs); + EmitWithoutSpvResult(binary); + + auto* res = b_.Not(binary); + Emit(res, inst.result_id()); + } + + /// @param inst the SPIR-V instruction for OpCompositeExtract + void EmitCompositeExtract(const spvtools::opt::Instruction& inst, + uint32_t composite_index = 2) { + Vector indices; + for (uint32_t i = composite_index + 1; i < inst.NumOperandWords(); i++) { + indices.Push(b_.Constant(u32(inst.GetSingleWordOperand(i)))); + } + auto* object = Value(inst.GetSingleWordOperand(composite_index)); + auto* access = b_.Access(Type(inst.type_id()), object, std::move(indices)); + Emit(access, inst.result_id()); + } + + /// @param inst the SPIR-V instruction for OpCompositeInsert + void EmitCompositeInsert(const spvtools::opt::Instruction& inst) { + auto* object = Value(inst.GetSingleWordOperand(2)); + auto* composite = Value(inst.GetSingleWordOperand(3)); + Vector indices; + for (uint32_t i = 4; i < inst.NumOperandWords(); i++) { + indices.Push(b_.Constant(u32(inst.GetSingleWordOperand(i)))); + } + + auto* tmp = b_.Var(ty_.ptr(function, Type(inst.type_id()))); + tmp->SetInitializer(composite); + auto* ptr_ty = ty_.ptr(function, object->Type()); + auto* access = b_.Access(ptr_ty, tmp, std::move(indices)); + + EmitWithoutSpvResult(tmp); + EmitWithoutSpvResult(access); + EmitWithoutResult(b_.Store(access, object)); + Emit(b_.Load(tmp), inst.result_id()); + } + + /// @param inst the SPIR-V instruction for OpCompositeConstruct + void EmitConstruct(const spvtools::opt::Instruction& inst) { + auto* construct = b_.Construct(Type(inst.type_id()), Args(inst, 2)); + Emit(construct, inst.result_id()); + } + + /// @param inst the SPIR-V instruction for OpVectorInsertDynamic + void EmitVectorInsertDynamic(const spvtools::opt::Instruction& inst) { + auto vector = Value(inst.GetSingleWordOperand(2)); + auto component = Value(inst.GetSingleWordOperand(3)); + auto index = Value(inst.GetSingleWordOperand(4)); + auto* tmp = b_.Var( + ty_.ptr(core::AddressSpace::kFunction, Type(inst.type_id()), core::Access::kReadWrite)); + tmp->SetInitializer(vector); + EmitWithoutSpvResult(tmp); + EmitWithoutResult(b_.StoreVectorElement(tmp, index, component)); + Emit(b_.Load(tmp), inst.result_id()); + } + + /// @param inst the SPIR-V instruction for OpVectorShuffle + void EmitVectorShuffle(const spvtools::opt::Instruction& inst) { + auto* vector1 = Value(inst.GetSingleWordOperand(2)); + auto* vector2 = Value(inst.GetSingleWordOperand(3)); + auto* result_ty = Type(inst.type_id()); + auto* el_ty = result_ty->DeepestElement(); + + uint32_t n1 = vector1->Type()->As()->Width(); + uint32_t n2 = vector2->Type()->As()->Width(); + + Vector swizzles; + + // Track the current swizzle that we are building from consecutive indices that fall within + // the same vector. + Vector current_indices; + core::ir::Value* current_vector = nullptr; + + // Emit the current swizzle that we have constructed so far, and add it to the list. + auto flush_swizzle = [&] { + if (current_vector == nullptr) { + return; + } + auto* swizzle_type = ty_.MatchWidth(el_ty, current_indices.Length()); + auto* swizzle = b_.Swizzle(swizzle_type, current_vector, current_indices); + EmitWithoutSpvResult(swizzle); + swizzles.Push(swizzle->Result()); + current_indices.Clear(); + }; + + for (uint32_t i = 4; i < inst.NumOperandWords(); i++) { + uint32_t literal = inst.GetSingleWordOperand(i); + + // Determine which vector this index falls within. + uint32_t next_index; + core::ir::Value* next_vector = nullptr; + if (literal == 0xFFFFFFFF) { + // Undefined component, so just use the first component of the first vector. + next_vector = vector1; + next_index = 0; + } else if (literal < n1) { + next_vector = vector1; + next_index = literal; + } else if (literal < n1 + n2) { + next_vector = vector2; + next_index = literal - n1; + } else { + TINT_ICE() << "invalid vector shuffle index"; + } + + // If the vector has changed from the previous index, flush the swizzle. + if (next_vector != current_vector) { + flush_swizzle(); + } + current_vector = next_vector; + current_indices.Push(next_index); + } + + flush_swizzle(); + + if (swizzles.Length() == 1) { + // There was only one swizzle, so we can just use it directly. + AddValue(inst.result_id(), swizzles[0]); + } else { + // There were multiple swizzles, so we combine them all to produce the final result. + Emit(b_.Construct(result_ty, swizzles), inst.result_id()); + } + } + + /// @param inst the SPIR-V instruction for OpFunctionCall + void EmitFunctionCall(const spvtools::opt::Instruction& inst) { + Emit(b_.Call(Function(inst.GetSingleWordInOperand(0)), Args(inst, 3)), inst.result_id()); + } + + /// @param inst the SPIR-V instruction for OpVariable + void EmitVar(const spvtools::opt::Instruction& inst) { + // Handle decorations. + std::optional group; + std::optional binding; + core::Access access_mode = core::Access::kUndefined; + core::IOAttributes io_attributes; + auto interpolation = [&]() -> core::Interpolation& { + // Create the interpolation field with the default values on first call. + if (!io_attributes.interpolation.has_value()) { + io_attributes.interpolation = core::Interpolation{ + .type = core::InterpolationType::kPerspective, + .sampling = core::InterpolationSampling::kUndefined, + }; + } + return io_attributes.interpolation.value(); + }; + for (auto* deco : + spirv_context_->get_decoration_mgr()->GetDecorationsFor(inst.result_id(), false)) { + auto d = deco->GetSingleWordOperand(1); + switch (spv::Decoration(d)) { + case spv::Decoration::RelaxedPrecision: // WGSL is relaxed precision by default + break; + case spv::Decoration::NonReadable: + access_mode = core::Access::kWrite; + break; + case spv::Decoration::NonWritable: + access_mode = core::Access::kRead; + break; + case spv::Decoration::DescriptorSet: + group = deco->GetSingleWordOperand(2); + break; + case spv::Decoration::Binding: + binding = deco->GetSingleWordOperand(2); + break; + case spv::Decoration::BuiltIn: + io_attributes.builtin = Builtin(spv::BuiltIn(deco->GetSingleWordOperand(2))); + break; + case spv::Decoration::Invariant: + io_attributes.invariant = true; + break; + case spv::Decoration::Location: + io_attributes.location = deco->GetSingleWordOperand(2); + break; + case spv::Decoration::NoPerspective: + interpolation().type = core::InterpolationType::kLinear; + break; + case spv::Decoration::Flat: + interpolation().type = core::InterpolationType::kFlat; + break; + case spv::Decoration::Centroid: + interpolation().sampling = core::InterpolationSampling::kCentroid; + break; + case spv::Decoration::Sample: + interpolation().sampling = core::InterpolationSampling::kSample; + break; + case spv::Decoration::Index: + io_attributes.blend_src = deco->GetSingleWordOperand(2); + break; + case spv::Decoration::Coherent: + // Tint has coherent memory semantics, so this is a no-op. + break; + case spv::Decoration::Restrict: + // Hint to the compiler that it may compile as if there is no aliasing. Ignore. + break; + default: + TINT_UNIMPLEMENTED() << "unhandled decoration " << d; + } + } + + if (io_attributes.interpolation.has_value()) { + // WGSL requires that '@interpolate(flat)' needs to be paired with '@location', however + // SPIR-V requires all fragment shader integer Inputs are 'flat'. If the decorations do + // not contain a spv::Decoration::Location, then remove the interpolation decoration. + // + // The `perspective,center` interpolation is the default value if one isn't provided. + // Just strip it off. This keeps us from accidentally applying interpolation where it + // isn't permitted, and it isn't necessary. + if ((io_attributes.interpolation->type == core::InterpolationType::kFlat && + !io_attributes.location.has_value()) || + (io_attributes.interpolation->type == core::InterpolationType::kPerspective && + io_attributes.interpolation->sampling == core::InterpolationSampling::kCenter)) { + io_attributes.interpolation = std::nullopt; + } + } + + auto* element_ty = Type(inst.type_id(), access_mode)->As(); + if (element_ty->AddressSpace() == core::AddressSpace::kOut && + element_ty->StoreType()->IsIntegerScalarOrVector()) { + io_attributes.interpolation = { + .type = core::InterpolationType::kFlat, + .sampling = core::InterpolationSampling::kUndefined, + }; + } + + auto* var = b_.Var(element_ty); + if (inst.NumOperands() > 3) { + var->SetInitializer(Value(inst.GetSingleWordOperand(3))); + } + + if (group || binding) { + TINT_ASSERT(group && binding); + + // Remap any samplers which match an entry in the sampler mappings + // table. + if (element_ty->StoreType()->Is()) { + auto it = + options_.sampler_mappings.find(BindingPoint{group.value(), binding.value()}); + if (it != options_.sampler_mappings.end()) { + auto bp = it->second; + group = bp.group; + binding = bp.binding; + } + } + + auto& grp = max_binding.GetOrAddZero(group.value()); + grp = std::max(grp, binding.value()); + + auto& used = used_bindings.GetOrAddZero(BindingPoint{group.value(), binding.value()}); + used += 1; + + io_attributes.binding_point = {group.value(), binding.value()}; + } + var->SetAttributes(std::move(io_attributes)); + var_to_original_access_mode_.insert({var, access_mode}); + + Emit(var, inst.result_id()); + } + + private: + /// TypeKey describes a SPIR-V type with an access mode. + struct TypeKey { + /// The SPIR-V type object. + uint32_t type_id; + /// The access mode. + core::Access access_mode; + + // Equality operator for TypeKey. + bool operator==(const TypeKey& other) const { + return type_id == other.type_id && access_mode == other.access_mode; + } + + /// @returns the hash code of the TypeKey + tint::HashCode HashCode() const { return Hash(type_id, access_mode); } + }; + + /// The parser options + const Options& options_; + + /// The generated IR module. + core::ir::Module ir_; + /// The Tint IR builder. + core::ir::Builder b_{ir_}; + /// The Tint type manager. + core::type::Manager& ty_{ir_.Types()}; + + /// The Tint IR function that is currently being emitted. + core::ir::Function* current_function_ = nullptr; + /// The Tint IR block that is currently being emitted. + core::ir::Block* current_block_ = nullptr; + /// A map from a SPIR-V type declaration to the corresponding Tint type object. + Hashmap types_; + /// A map from a SPIR-V function definition result ID to the corresponding Tint function object. + Hashmap functions_; + /// A map from a SPIR-V result ID to the corresponding Tint value object. + Hashmap values_; + /// Maps a `group` number to the largest seen `binding` value for that group + Hashmap max_binding; + /// A map of binding point to the count of usages + Hashmap used_bindings; + + /// The SPIR-V context containing the SPIR-V tools intermediate representation. + std::unique_ptr spirv_context_; + /// The current SPIR-V function being emitted + spvtools::opt::Function* current_spirv_function_ = nullptr; + + // The set of IDs that are imports of the GLSL.std.450 extended instruction sets. + std::unordered_set glsl_std_450_imports_; + // The set of IDs of imports that are ignored. For example, any "NonSemanticInfo." import is + // ignored. + std::unordered_set ignored_imports_; + + // Map of SPIR-V IDs to string names + std::unordered_map id_to_name_; + // Map of SPIR-V Struct IDs to a list of member string names + std::unordered_map> struct_to_member_names_; + + // Set of types which should be considered `NonWritable` even if no decoration is present + std::unordered_set consider_non_writable_; + + // Set of SPIR-V block ids where we'll stop a `Branch` instruction walk. These could be merge + // blocks, premerge blocks, continuing blocks, etc. + std::unordered_map walk_stop_blocks_; + // Map of continue target ID to the controlling IR loop. + std::unordered_map continue_targets_; + // Map of header target ID to the controlling IR loop. + std::unordered_map loop_headers_; + + struct PremergeInfo { + core::ir::If* parent = nullptr; + core::ir::Var* condition = nullptr; + }; + // Map of merge ID to an associated premerge_id, if any + std::unordered_map merge_to_premerge_; + + std::unordered_set current_blocks_; + + // For each block, we keep a set of SPIR-V `id`s which are known in that scope. + std::vector> id_stack_; + + // If we're in a switch, is populated with the IDs of the blocks for each of the switch + // selectors. This lets us watch for fallthrough when emitting branch instructions. + std::vector> current_switch_blocks_; + + /// Maps from a spirv-v block id to the corresponding block in the IR + std::unordered_map spirv_id_to_block_; + + // Map of continue block id to the phi types which need to be returned by + // the continue target + std::unordered_map> continue_blk_phis_; + + // A stack of values which need to be replaced as we finish processing a + // block. Used to store `phi` information so we can retrieve values which + // are defined after the `OpPhi` instruction. + std::vector> values_to_replace_; + + // A map of block to phi values returned by the loop header + std::unordered_map> block_phi_values_; + + // Map of certain instructions back to their originating spirv block + std::unordered_map inst_to_spirv_block_; + + // Map of merge block id's back to the block which contains the header + std::unordered_map spirv_merge_id_to_header_id_; + + // Structure hold spec composite information + struct SpecComposite { + // The composite type + const core::type::Type* type; + // The composite arguments + Vector args; + }; + + // The set of SPIR-V IDs which map to `OpSpecConstantComposite` information + std::unordered_map spec_composites_; + + // Structures which are marked with `BufferBlock` and need to be reported as `Storage` address + // space + std::unordered_set storage_buffer_types_; + + // Map of `var` to the access mode it was originally created with. This may be different from + // the current mode if we needed to set a default mode. + std::unordered_map var_to_original_access_mode_; + + // Map of spir-v branch conditional instructions to the related IR if instruction. + std::unordered_map branch_conditional_to_if_; +}; + +} // namespace + +Result Parse(Slice spirv, const Options& options) { + return Parser(options).Run(spirv); +} + +} // namespace tint::spirv::reader diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.h b/3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.h new file mode 100644 index 000000000..02a92c39e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/parser/parser.h @@ -0,0 +1,52 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_PARSER_PARSER_H_ +#define SRC_TINT_LANG_SPIRV_READER_PARSER_PARSER_H_ + +#include + +#include "src/tint/lang/spirv/reader/common/options.h" +#include "src/tint/utils/containers/slice.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::spirv::reader { + +/// Parse a SPIR-V binary to produce a SPIR-V IR module. +/// @param spirv the SPIR-V binary data +/// @param options the parser options +/// @returns the SPIR-V IR module on success, or failure +Result Parse(Slice spirv, const Options& options = {}); + +} // namespace tint::spirv::reader + +#endif // SRC_TINT_LANG_SPIRV_READER_PARSER_PARSER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/reader.cc b/3rdparty/dawn/src/tint/lang/spirv/reader/reader.cc new file mode 100644 index 000000000..f08c7c37a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/reader.cc @@ -0,0 +1,54 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/reader/reader.h" + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/reader/lower/lower.h" +#include "src/tint/lang/spirv/reader/parser/parser.h" + +namespace tint::spirv::reader { + +Result ReadIR(const std::vector& input, const Options& options) { + // Parse the input SPIR-V to the SPIR-V dialect of the IR. + TINT_CHECK_RESULT_UNWRAP(mod, Parse(Slice(input.data(), input.size()), options)); + + // Lower the module to the core dialect of the IR. + TINT_CHECK_RESULT(Lower(mod)); + + // Always validate the core IR, so that we fail somewhat gracefully on invalid inputs instead of + // just ICEing later on. + TINT_CHECK_RESULT(core::ir::Validate(mod, core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + })); + + return mod; +} + +} // namespace tint::spirv::reader diff --git a/3rdparty/dawn/src/tint/lang/spirv/reader/reader.h b/3rdparty/dawn/src/tint/lang/spirv/reader/reader.h new file mode 100644 index 000000000..dd7c70572 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/reader/reader.h @@ -0,0 +1,52 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_READER_READER_H_ +#define SRC_TINT_LANG_SPIRV_READER_READER_H_ + +#include + +#include "src/tint/lang/spirv/reader/common/options.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::reader { + +/// Reads the SPIR-V source data, returning a core IR module. +/// If the SPIR-V binary fails to parse then the result will contain error messages. +/// TODO(crbug.com/tint/1907): Rename when we remove the AST path. +/// @param input the SPIR-V binary data +/// @param options the parser options +/// @returns the Tint IR module +Result ReadIR(const std::vector& input, const Options& options = {}); + +} // namespace tint::spirv::reader + +#endif // SRC_TINT_LANG_SPIRV_READER_READER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.cc b/3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.cc new file mode 100644 index 000000000..09a3bb5b4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.cc @@ -0,0 +1,70 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/type/explicit_layout_array.h" + +#include + +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/string_stream.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::type::ExplicitLayoutArray); + +namespace tint::spirv::type { + +ExplicitLayoutArray::ExplicitLayoutArray(const Type* element, + const core::type::ArrayCount* count, + uint32_t size, + uint32_t stride) + : Base(Hash(tint::TypeCode::Of().bits, count), element, count, size), + stride_(stride) {} + +bool ExplicitLayoutArray::Equals(const UniqueNode& other) const { + if (other.Is()) { + return Array::Equals(other); + } + return false; +} + +std::string ExplicitLayoutArray::FriendlyName() const { + StringStream out; + out << "spirv.explicit_layout_array<" << element_->FriendlyName(); + if (!count_->Is()) { + out << ", " << count_->FriendlyName(); + } + out << ", stride=" << stride_ << ">"; + return out.str(); +} + +ExplicitLayoutArray* ExplicitLayoutArray::Clone(core::type::CloneContext& ctx) const { + auto* elem_ty = element_->Clone(ctx); + auto* count = count_->Clone(ctx); + return ctx.dst.mgr->Get(elem_ty, count, size_, stride_); +} + +} // namespace tint::spirv::type diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.h b/3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.h new file mode 100644 index 000000000..29094f702 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/explicit_layout_array.h @@ -0,0 +1,79 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_TYPE_EXPLICIT_LAYOUT_ARRAY_H_ +#define SRC_TINT_LANG_SPIRV_TYPE_EXPLICIT_LAYOUT_ARRAY_H_ + +#include +#include + +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::spirv::type { + +/// ExplicitLayoutArray holds the type information for ExplicitLayoutArray nodes. +class ExplicitLayoutArray : public Castable { + public: + /// Constructor + /// @param element the array element type + /// @param count the number of elements in the array. + /// @param size the byte size of the array. + /// @param stride the number of bytes from the start of one element of the array to the start of + /// the next element + ExplicitLayoutArray(Type const* element, + const core::type::ArrayCount* count, + uint32_t size, + uint32_t stride); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns true if the stride is implicit + bool IsStrideImplicit() const { return ImplicitStride() == stride_; } + + /// @returns the stride + uint32_t Stride() const { return stride_; } + + /// @returns the name for this type that closely resembles how it would be + /// declared in WGSL. + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + ExplicitLayoutArray* Clone(core::type::CloneContext& ctx) const override; + + private: + // The explicit stride + uint32_t stride_; +}; + +} // namespace tint::spirv::type + +#endif // SRC_TINT_LANG_SPIRV_TYPE_EXPLICIT_LAYOUT_ARRAY_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/image.cc b/3rdparty/dawn/src/tint/lang/spirv/type/image.cc new file mode 100644 index 000000000..eae58cd5a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/image.cc @@ -0,0 +1,169 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/type/image.h" + +#include + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::type::Image); + +namespace tint::spirv::type { +namespace { + +std::ostream& operator<<(std::ostream& out, const Dim dim) { + switch (dim) { + case Dim::kD1: + out << "1d"; + break; + case Dim::kD2: + out << "2d"; + break; + case Dim::kD3: + out << "3d"; + break; + case Dim::kCube: + out << "cube"; + break; + case Dim::kBuffer: + out << "buffer"; + break; + case Dim::kSubpassData: + out << "subpass_data"; + break; + } + return out; +} + +std::ostream& operator<<(std::ostream& out, const Depth depth) { + switch (depth) { + case Depth::kNotDepth: + out << "not_depth"; + break; + case Depth::kDepth: + out << "depth"; + break; + case Depth::kUnknown: + out << "depth_unknown"; + break; + } + return out; +} + +std::ostream& operator<<(std::ostream& out, const Arrayed arrayed) { + switch (arrayed) { + case Arrayed::kNonArrayed: + out << "non_arrayed"; + break; + case Arrayed::kArrayed: + out << "arrayed"; + break; + } + return out; +} + +std::ostream& operator<<(std::ostream& out, const Multisampled ms) { + switch (ms) { + case Multisampled::kSingleSampled: + out << "single_sampled"; + break; + case Multisampled::kMultisampled: + out << "multi_sampled"; + break; + } + return out; +} + +std::ostream& operator<<(std::ostream& out, const Sampled sampled) { + switch (sampled) { + case Sampled::kSamplingCompatible: + out << "sampling_compatible"; + break; + case Sampled::kReadWriteOpCompatible: + out << "rw_op_compatible"; + break; + } + return out; +} + +} // namespace + +Image::Image(const core::type::Type* sampled_type, + Dim dim, + Depth depth, + Arrayed arrayed, + Multisampled ms, + Sampled sampled, + core::TexelFormat fmt, + core::Access access) + : Base(static_cast(Hash(tint::TypeCode::Of().bits, + sampled_type, + dim, + depth, + arrayed, + ms, + sampled, + fmt, + access)), + core::type::Flags{}), + sampled_type_(sampled_type), + dim_(dim), + depth_(depth), + arrayed_(arrayed), + ms_(ms), + sampled_(sampled), + fmt_(fmt), + access_(access) {} + +bool Image::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->sampled_type_ == sampled_type_ && o->dim_ == dim_ && o->depth_ == depth_ && + o->arrayed_ == arrayed_ && o->ms_ == ms_ && o->sampled_ == sampled_ && + o->fmt_ == fmt_ && o->access_ == access_; + } + return false; +} + +std::string Image::FriendlyName() const { + std::stringstream str; + + str << "spirv.image<" << sampled_type_->FriendlyName(); + str << ", " << dim_ << ", " << depth_ << ", " << arrayed_; + str << ", " << ms_ << ", " << sampled_ << ", " << fmt_ << ", " << access_; + str << ">"; + + return str.str(); +} + +Image* Image::Clone(core::type::CloneContext& ctx) const { + auto* sampled_type = sampled_type_->Clone(ctx); + return ctx.dst.mgr->Get(sampled_type, dim_, depth_, arrayed_, ms_, sampled_, fmt_, + access_); +} + +} // namespace tint::spirv::type diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/image.h b/3rdparty/dawn/src/tint/lang/spirv/type/image.h new file mode 100644 index 000000000..8e83fa75e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/image.h @@ -0,0 +1,127 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_TYPE_IMAGE_H_ +#define SRC_TINT_LANG_SPIRV_TYPE_IMAGE_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::spirv::type { + +enum class Dim : uint8_t { + kD1 = 0, + kD2 = 1, + kD3 = 2, + kCube = 3, + // Not used in WGSL + // Rect = 4, + kBuffer = 5, + kSubpassData = 6, +}; + +enum class Depth : uint8_t { + kNotDepth = 0, + kDepth = 1, + kUnknown = 2, +}; + +enum class Arrayed : uint8_t { + kNonArrayed = 0, + kArrayed = 1, +}; + +enum class Multisampled : uint8_t { + kSingleSampled = 0, + kMultisampled = 1, +}; + +enum class Sampled : uint8_t { + // KnownAtRuntime is not allowed in Vulkan environment, so ignore it + kSamplingCompatible = 1, + kReadWriteOpCompatible = 2, +}; + +/// Image represents an OpTypeImage in SPIR-V. +class Image final : public Castable { + public: + /// Constructor + /// @param sampled_type the type of the components that result from sampling or reading + /// @param dim the image dimensionality + /// @param depth image depth information + /// @param arrayed image arrayed information + /// @param ms the image multisampled information + /// @param sampled the image sampled information + /// @param fmt the image format + /// @param access the image access qualifier + Image(const core::type::Type* sampled_type, + Dim dim, + Depth depth, + Arrayed arrayed, + Multisampled ms, + Sampled sampled, + core::TexelFormat fmt, + core::Access access); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + const core::type::Type* GetSampledType() const { return sampled_type_; } + Dim GetDim() const { return dim_; } + Depth GetDepth() const { return depth_; } + Arrayed GetArrayed() const { return arrayed_; } + Multisampled GetMultisampled() const { return ms_; } + Sampled GetSampled() const { return sampled_; } + core::TexelFormat GetTexelFormat() const { return fmt_; } + core::Access GetAccess() const { return access_; } + + /// @returns the friendly name for this type + std::string FriendlyName() const override; + + bool IsHandle() const override { return true; } + + /// @param ctx the clone context + /// @returns a clone of this type + Image* Clone(core::type::CloneContext& ctx) const override; + + private: + const core::type::Type* sampled_type_; + Dim dim_; + Depth depth_; + Arrayed arrayed_; + Multisampled ms_; + Sampled sampled_; + core::TexelFormat fmt_; + core::Access access_; +}; + +} // namespace tint::spirv::type + +#endif // SRC_TINT_LANG_SPIRV_TYPE_IMAGE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/resource_table.cc b/3rdparty/dawn/src/tint/lang/spirv/type/resource_table.cc new file mode 100644 index 000000000..070cace9c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/resource_table.cc @@ -0,0 +1,71 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/type/resource_table.h" + +#include + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::type::ResourceTable); + +namespace tint::spirv::type { + +ResourceTable::ResourceTable(const core::type::Type* binding_type) + : Base(static_cast(Hash(tint::TypeCode::Of().bits, binding_type)), + core::type::Flags{}), + binding_type_(binding_type) {} + +bool ResourceTable::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->binding_type_ == binding_type_; + } + return false; +} + +std::string ResourceTable::FriendlyName() const { + std::stringstream str; + str << "spirv.resource_table<" << binding_type_->FriendlyName() << ">"; + return str.str(); +} + +core::type::TypeAndCount ResourceTable::Elements( + [[maybe_unused]] const core::type::Type* type_if_unused, + uint32_t count_if_invalid) const { + return {binding_type_, count_if_invalid}; +} + +const core::type::Type* ResourceTable::Element([[maybe_unused]] uint32_t index) const { + return binding_type_; +} + +ResourceTable* ResourceTable::Clone(core::type::CloneContext& ctx) const { + auto* binding_type = binding_type_->Clone(ctx); + return ctx.dst.mgr->Get(binding_type); +} + +} // namespace tint::spirv::type diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/resource_table.h b/3rdparty/dawn/src/tint/lang/spirv/type/resource_table.h new file mode 100644 index 000000000..d13ad7360 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/resource_table.h @@ -0,0 +1,73 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_TYPE_RESOURCE_TABLE_H_ +#define SRC_TINT_LANG_SPIRV_TYPE_RESOURCE_TABLE_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::spirv::type { + +/// ResourceTable represents an OpTypeRuntimeArray of resources +class ResourceTable final : public Castable { + public: + /// Constructor + /// @param binding_type the type of the table + explicit ResourceTable(const core::type::Type* binding_type); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + const core::type::Type* GetBindingType() const { return binding_type_; } + + /// @copydoc core::type::Type::Elements + core::type::TypeAndCount Elements(const core::type::Type* type_if_invalid = nullptr, + uint32_t count_if_invalid = 0) const override; + + /// @copydoc core::type::Type::Element + const core::type::Type* Element(uint32_t index) const override; + + /// @returns the friendly name for this type + std::string FriendlyName() const override; + + bool IsHandle() const override { return true; } + + /// @param ctx the clone context + /// @returns a clone of this type + ResourceTable* Clone(core::type::CloneContext& ctx) const override; + + private: + const core::type::Type* binding_type_; +}; + +} // namespace tint::spirv::type + +#endif // SRC_TINT_LANG_SPIRV_TYPE_RESOURCE_TABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.cc b/3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.cc new file mode 100644 index 000000000..36f175740 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.cc @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/type/sampled_image.h" + +#include "src/tint/lang/core/type/manager.h" + +TINT_INSTANTIATE_TYPEINFO(tint::spirv::type::SampledImage); + +namespace tint::spirv::type { + +SampledImage::SampledImage(const core::type::Type* image) + : Base(static_cast(Hash(tint::TypeCode::Of().bits, image)), + core::type::Flags{}), + image_(image->As()) { + TINT_ASSERT(image_); +} + +bool SampledImage::Equals(const UniqueNode& other) const { + if (auto* o = other.As()) { + return o->image_ == image_; + } + return false; +} + +std::string SampledImage::FriendlyName() const { + return "spirv.sampled_image<" + image_->FriendlyName() + ">"; +} + +SampledImage* SampledImage::Clone(core::type::CloneContext& ctx) const { + auto* image = image_->Clone(ctx); + return ctx.dst.mgr->Get(image); +} + +} // namespace tint::spirv::type diff --git a/3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.h b/3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.h new file mode 100644 index 000000000..29aa4ebd8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/type/sampled_image.h @@ -0,0 +1,66 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_TYPE_SAMPLED_IMAGE_H_ +#define SRC_TINT_LANG_SPIRV_TYPE_SAMPLED_IMAGE_H_ + +#include + +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/spirv/type/image.h" + +namespace tint::spirv::type { + +/// SampledImage represents an OpTypeSampledImage in SPIR-V. +class SampledImage final : public Castable { + public: + /// Constructor + /// @param image the image type + explicit SampledImage(const core::type::Type* image); + + /// @param other the other node to compare against + /// @returns true if the this type is equal to @p other + bool Equals(const UniqueNode& other) const override; + + /// @returns the friendly name for this type + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + SampledImage* Clone(core::type::CloneContext& ctx) const override; + + /// @returns the image type + const spirv::type::Image* Image() const { return image_; } + + private: + const spirv::type::Image* image_; +}; + +} // namespace tint::spirv::type + +#endif // SRC_TINT_LANG_SPIRV_TYPE_SAMPLED_IMAGE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/validate/validate.cc b/3rdparty/dawn/src/tint/lang/spirv/validate/validate.cc new file mode 100644 index 000000000..237e1259d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/validate/validate.cc @@ -0,0 +1,98 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/validate/validate.h" + +#include +#include +#include + +#include "spirv-tools/libspirv.hpp" +#include "src/tint/utils/diagnostic/diagnostic.h" + +namespace tint::spirv::validate { + +Result Validate(Slice spirv, spv_target_env target_env) { + Vector diags; + diags.Push(diag::Diagnostic{}); // Filled in on error + + spvtools::SpirvTools tools(target_env); + tools.SetMessageConsumer( + [&](spv_message_level_t level, const char*, const spv_position_t& pos, const char* msg) { + diag::Diagnostic diag; + diag.message = msg; + diag.source.range.begin.line = static_cast(pos.line) + 1; + diag.source.range.begin.column = static_cast(pos.column) + 1; + diag.source.range.end = diag.source.range.begin; + switch (level) { + case SPV_MSG_FATAL: + case SPV_MSG_INTERNAL_ERROR: + case SPV_MSG_ERROR: + diag.severity = diag::Severity::Error; + break; + case SPV_MSG_WARNING: + diag.severity = diag::Severity::Warning; + break; + case SPV_MSG_INFO: + case SPV_MSG_DEBUG: + diag.severity = diag::Severity::Note; + break; + } + diags.Push(std::move(diag)); + }); + + // Don't prepare to emit friendly names. The preparation costs + // time by scanning the whole module and building a string table. + spvtools::ValidatorOptions val_opts; + val_opts.SetFriendlyNames(false); + + if (tools.Validate(spirv.data, spirv.len, val_opts)) { + return Success; + } + + std::string disassembly; + if (tools.Disassemble( + spirv.data, spirv.len, &disassembly, + SPV_BINARY_TO_TEXT_OPTION_INDENT | SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES)) { + diag::Diagnostic& err = diags.Front(); + err.message = "SPIR-V failed validation.\n\nDisassembly:\n" + std::move(disassembly); + err.severity = diag::Severity::Error; + } else { + diag::Diagnostic& err = diags.Front(); + err.message = "SPIR-V failed validation and disassembly\n"; + err.severity = diag::Severity::Error; + } + auto file = std::make_shared("spirv", disassembly); + for (auto& diag : diags) { + diag.source.file = file.get(); + diag.owned_file = file; + } + auto list = diag::List(diags); + return Failure{list.Str()}; +} + +} // namespace tint::spirv::validate diff --git a/3rdparty/dawn/src/tint/lang/spirv/validate/validate.h b/3rdparty/dawn/src/tint/lang/spirv/validate/validate.h new file mode 100644 index 000000000..6e88423a3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/validate/validate.h @@ -0,0 +1,45 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_VALIDATE_VALIDATE_H_ +#define SRC_TINT_LANG_SPIRV_VALIDATE_VALIDATE_H_ + +#include "spirv-tools/libspirv.hpp" +#include "src/tint/utils/containers/slice.h" +#include "src/tint/utils/result.h" + +namespace tint::spirv::validate { + +/// Validate checks that the provided SPIR-V passes validation. +/// @param spirv the SPIR-V binary data +/// @param target_env the target environment to validate against +/// @return success or failure(s) +Result Validate(Slice spirv, spv_target_env target_env); + +} // namespace tint::spirv::validate + +#endif // SRC_TINT_LANG_SPIRV_VALIDATE_VALIDATE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.cc new file mode 100644 index 000000000..6e9d535c7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.cc @@ -0,0 +1,93 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "src/tint/lang/spirv/writer/common/binary_writer.h" + +#include +#include + +#include "src/tint/utils/memory/bitcast.h" + +namespace tint::spirv::writer { +namespace { + +const uint32_t kGeneratorId = 23u << 16; + +} // namespace + +BinaryWriter::BinaryWriter() = default; + +BinaryWriter::~BinaryWriter() = default; + +void BinaryWriter::WriteModule(const Module& module) { + out_.reserve(module.TotalSize()); + module.Iterate([this](const Instruction& inst) { this->ProcessInstruction(inst); }); +} + +void BinaryWriter::WriteInstruction(const Instruction& inst) { + ProcessInstruction(inst); +} + +void BinaryWriter::WriteHeader(uint32_t bound, uint32_t version, uint32_t spirv_version) { + out_.push_back(spv::MagicNumber); + out_.push_back(spirv_version); + out_.push_back(kGeneratorId | version); + out_.push_back(bound); + out_.push_back(0); +} + +void BinaryWriter::ProcessInstruction(const Instruction& inst) { + TINT_ASSERT(inst.WordLength() < 65536); + out_.push_back(inst.WordLength() << 16 | static_cast(inst.Opcode())); + for (const auto& op : inst.Operands()) { + ProcessOp(op); + } +} + +void BinaryWriter::ProcessOp(const Operand& op) { + if (auto* i = std::get_if(&op)) { + out_.push_back(*i); + return; + } + if (auto* f = std::get_if(&op)) { + out_.push_back(tint::Bitcast(*f)); + return; + } + if (auto* str = std::get_if(&op)) { + auto idx = out_.size(); + out_.resize(out_.size() + OperandLength(op), 0); + memcpy(&out_[idx], str->c_str(), str->size() + 1); + return; + } +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.h new file mode 100644 index 000000000..49092352b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/binary_writer.h @@ -0,0 +1,74 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_BINARY_WRITER_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_BINARY_WRITER_H_ + +#include + +#include "src/tint/lang/spirv/writer/common/module.h" + +namespace tint::spirv::writer { + +/// Writer to convert from module to SPIR-V binary. +class BinaryWriter { + public: + /// Constructor + BinaryWriter(); + ~BinaryWriter(); + + /// Writes the SPIR-V header. + /// @param bound the bound to output + /// @param version the generator version number + /// @param spirv_version the SPIR-V binary version (default SPIR-V 1.3). + void WriteHeader(uint32_t bound, uint32_t version = 0, uint32_t spirv_version = 0x10300u); + + /// Writes the given module data into a binary. Note, this does not emit the SPIR-V header. You + /// **must** call WriteHeader() before WriteModule() if you want the SPIR-V to be emitted. + /// @param module the module to assemble from + void WriteModule(const Module& module); + + /// Writes the given instruction into the binary. + /// @param inst the instruction to assemble + void WriteInstruction(const Instruction& inst); + + /// @returns the assembled SPIR-V + const std::vector& Result() const { return out_; } + + /// @returns the assembled SPIR-V + std::vector& Result() { return out_; } + + private: + void ProcessInstruction(const Instruction& inst); + void ProcessOp(const Operand& op); + + std::vector out_; +}; + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_BINARY_WRITER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/function.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/function.cc new file mode 100644 index 000000000..ba133c360 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/function.cc @@ -0,0 +1,174 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/common/function.h" + +#include +#include + +#include "src/tint/utils/ice/ice.h" + +namespace tint::spirv::writer { +namespace { + +bool IsFunctionTerminator(spv::Op op) { + return op == spv::Op::OpReturn || op == spv::Op::OpReturnValue || op == spv::Op::OpKill || + op == spv::Op::OpUnreachable || op == spv::Op::OpTerminateInvocation; +} + +bool IsBranchTerminator(spv::Op op) { + return op == spv::Op::OpBranch || op == spv::Op::OpBranchConditional || op == spv::Op::OpSwitch; +} + +} // namespace +Function::Function() : declaration_(Instruction{spv::Op::OpNop, {}}), label_op_(Operand(0u)) {} + +Function::Function(const Instruction& declaration, + const Operand& label_op, + const InstructionList& params) + : declaration_(declaration), label_op_(label_op), params_(params) {} + +Function::Function(const Function& other) = default; + +Function& Function::operator=(const Function& other) = default; + +Function::~Function() = default; + +void Function::Iterate(std::function cb) const { + cb(declaration_); + + for (const auto& param : params_) { + cb(param); + } + + cb(Instruction{spv::Op::OpLabel, {label_op_}}); + + for (const auto& var : vars_) { + cb(var); + } + + std::vector block_order; + block_order.reserve(blocks_.size()); + + std::unordered_set seen_blocks; + + std::vector block_idx_stack; + block_idx_stack.push_back(0); + seen_blocks.insert(0); + + auto idx_for_id = [&](uint32_t id) -> uint32_t { + auto iter = block_id_to_block_.find(id); + TINT_ASSERT(iter != block_id_to_block_.end()); + return iter->second; + }; + + auto push_id = [&](const Instruction& inst, size_t idx) { + auto id = idx_for_id(std::get(inst.Operands()[idx])); + + if (seen_blocks.find(id) != seen_blocks.end()) { + return; + } + seen_blocks.insert(id); + + block_idx_stack.push_back(id); + }; + + while (!block_idx_stack.empty()) { + auto idx = block_idx_stack.back(); + block_idx_stack.pop_back(); + + block_order.push_back(idx); + + auto& blk = blocks_[idx]; + auto& term = blk.back(); + if (IsFunctionTerminator(term.Opcode())) { + continue; + } + + TINT_ASSERT(IsBranchTerminator(term.Opcode())); + + // The initial block doesn't have a label, so can end up with 1 + // instruction. + if (blk.size() >= 2) { + auto& pre_term = blk[blk.size() - 2]; + + // Push the merges first so the emit after the branch conditional. + switch (pre_term.Opcode()) { + case spv::Op::OpSelectionMerge: { + push_id(pre_term, 0); + break; + } + case spv::Op::OpLoopMerge: { + // Push merge first, then continuing + push_id(pre_term, 0); + push_id(pre_term, 1); + break; + } + default: + break; + } + } + + switch (term.Opcode()) { + case spv::Op::OpBranch: { + push_id(term, 0); + break; + } + case spv::Op::OpBranchConditional: { + // Push false then true as we'll emit in reversed order + push_id(term, 2); + push_id(term, 1); + + break; + } + case spv::Op::OpSwitch: { + auto& ops = term.Operands(); + for (size_t k = ops.size() - 1; k > 2; k -= 2) { + push_id(term, k); + } + push_id(term, 1); + break; + } + default: + TINT_UNREACHABLE(); + } + } + + TINT_ASSERT(seen_blocks.size() == blocks_.size()); + + // Emit the blocks in block order + for (const auto& idx : block_order) { + auto& blk = blocks_[idx]; + for (const auto& inst : blk) { + cb(inst); + } + } + + cb(Instruction{spv::Op::OpFunctionEnd, {}}); +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/function.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/function.h new file mode 100644 index 000000000..633f08a47 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/function.h @@ -0,0 +1,137 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_FUNCTION_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_FUNCTION_H_ + +#include +#include +#include + +#include "src/tint/lang/spirv/writer/common/instruction.h" + +namespace tint::spirv::writer { + +/// A SPIR-V function +class Function { + public: + using Block = InstructionList; + + /// Constructor for testing purposes + /// This creates a bad declaration, so won't generate correct SPIR-V + Function(); + + /// Constructor + /// @param declaration the function declaration + /// @param label_op the operand for function's entry block label + /// @param params the function parameters + Function(const Instruction& declaration, + const Operand& label_op, + const InstructionList& params); + /// Copy constructor + /// @param other the function to copy + Function(const Function& other); + /// Copy assignment operator + /// @param other the function to copy + /// @returns the new Function + Function& operator=(const Function& other); + /// Destructor + ~Function(); + + /// Iterates over the function call the cb on each instruction + /// @param cb the callback to call + void Iterate(std::function cb) const; + + /// @returns the declaration + const Instruction& Declaration() const { return declaration_; } + + /// @returns the label ID for the function entry block + uint32_t LabelId() const { return std::get(label_op_); } + + /// Adds an instruction to the instruction list + /// @param op the op to set + /// @param operands the operands for the instruction + void PushInst(spv::Op op, const OperandList& operands) { + blocks_[current_block_idx_].push_back(Instruction{op, operands}); + } + /// Adds a new block to the block list + /// @returns the index of the new block + size_t AppendBlock(uint32_t spv_id) { + blocks_.push_back({}); + + auto blk_id = blocks_.size() - 1; + block_id_to_block_[spv_id] = static_cast(blk_id); + return blk_id; + } + /// Sets the block to insert into + /// @param idx the index to set + void SetCurrentBlockIndex(size_t idx) { current_block_idx_ = idx; } + + /// Adds a variable to the variable list + /// @param operands the operands for the variable + void PushVar(const OperandList& operands) { + vars_.push_back(Instruction{spv::Op::OpVariable, operands}); + } + /// @returns the variable list + const InstructionList& Variables() const { return vars_; } + + /// @returns the word length of the function + uint32_t WordLength() const { + // 1 for the Label and 1 for the FunctionEnd + uint32_t size = 2 + declaration_.WordLength(); + + for (const auto& param : params_) { + size += param.WordLength(); + } + for (const auto& var : vars_) { + size += var.WordLength(); + } + for (const auto& blk : blocks_) { + for (const auto& inst : blk) { + size += inst.WordLength(); + } + } + return size; + } + + /// @returns true if the function has a valid declaration + explicit operator bool() const { return declaration_.Opcode() == spv::Op::OpFunction; } + + private: + Instruction declaration_; + Operand label_op_; + InstructionList params_; + InstructionList vars_; + std::vector blocks_; + size_t current_block_idx_ = 0; + + std::unordered_map block_id_to_block_; +}; + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_FUNCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.cc new file mode 100644 index 000000000..8ca51ff53 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.cc @@ -0,0 +1,51 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/common/instruction.h" + +#include + +namespace tint::spirv::writer { + +Instruction::Instruction(spv::Op op, OperandList operands) + : op_(op), operands_(std::move(operands)) {} + +Instruction::Instruction(const Instruction&) = default; + +Instruction& Instruction::operator=(const Instruction&) = default; + +Instruction::~Instruction() = default; + +uint32_t Instruction::WordLength() const { + uint32_t size = 1; // Initial 1 for the op and size + for (const auto& op : operands_) { + size += OperandLength(op); + } + return size; +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.h new file mode 100644 index 000000000..564ee1e47 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/instruction.h @@ -0,0 +1,73 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_INSTRUCTION_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_INSTRUCTION_H_ + +#include + +#include "spirv/unified1/spirv.hpp11" +#include "src/tint/lang/spirv/writer/common/operand.h" + +namespace tint::spirv::writer { + +/// A single SPIR-V instruction +class Instruction { + public: + /// Constructor + /// @param op the op to generate + /// @param operands the operand values for the instruction + Instruction(spv::Op op, OperandList operands); + /// Copy Constructor + Instruction(const Instruction&); + /// Copy assignment operator + /// @param other the instruction to copy + /// @returns the new Instruction + Instruction& operator=(const Instruction& other); + /// Destructor + ~Instruction(); + + /// @returns the instructions op + spv::Op Opcode() const { return op_; } + + /// @returns the instructions operands + const OperandList& Operands() const { return operands_; } + + /// @returns the number of uint32_t's needed to hold the instruction + uint32_t WordLength() const; + + private: + spv::Op op_ = spv::Op::OpNop; + OperandList operands_; +}; + +/// A list of instructions +using InstructionList = std::vector; + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_INSTRUCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/module.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/module.cc new file mode 100644 index 000000000..e8b66361d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/module.cc @@ -0,0 +1,123 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/common/module.h" + +namespace tint::spirv::writer { +namespace { + +/// Helper to return the size in words of an instruction list when serialized. +/// @param instructions the instruction list +/// @returns the number of words needed to serialize the list +uint32_t SizeOf(const InstructionList& instructions) { + uint32_t size = 0; + for (const auto& inst : instructions) { + size += inst.WordLength(); + } + return size; +} + +} // namespace + +Module::Module() = default; + +Module::Module(const Module&) = default; + +Module::Module(Module&&) = default; + +Module::~Module() = default; + +Module& Module::operator=(const Module& other) = default; + +Module& Module::operator=(Module&& other) = default; + +uint32_t Module::TotalSize() const { + // The 5 covers the magic, version, generator, id bound and reserved. + uint32_t size = 5; + + size += SizeOf(capabilities_); + size += SizeOf(extensions_); + size += SizeOf(ext_imports_); + size += SizeOf(memory_model_); + size += SizeOf(entry_points_); + size += SizeOf(execution_modes_); + size += SizeOf(debug_); + size += SizeOf(annotations_); + size += SizeOf(types_); + for (const auto& func : functions_) { + size += func.WordLength(); + } + + return size; +} + +void Module::Iterate(std::function cb) const { + for (const auto& inst : capabilities_) { + cb(inst); + } + for (const auto& inst : extensions_) { + cb(inst); + } + for (const auto& inst : ext_imports_) { + cb(inst); + } + for (const auto& inst : memory_model_) { + cb(inst); + } + for (const auto& inst : entry_points_) { + cb(inst); + } + for (const auto& inst : execution_modes_) { + cb(inst); + } + for (const auto& inst : debug_) { + cb(inst); + } + for (const auto& inst : annotations_) { + cb(inst); + } + for (const auto& inst : types_) { + cb(inst); + } + for (const auto& func : functions_) { + func.Iterate(cb); + } +} + +void Module::PushCapability(uint32_t cap) { + if (capability_set_.Add(cap)) { + capabilities_.push_back(Instruction{spv::Op::OpCapability, {Operand(cap)}}); + } +} + +void Module::PushExtension(const char* extension) { + if (extension_set_.Add(extension)) { + extensions_.push_back(Instruction{spv::Op::OpExtension, {Operand(extension)}}); + } +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/module.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/module.h new file mode 100644 index 000000000..88f0b87c9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/module.h @@ -0,0 +1,198 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_MODULE_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_MODULE_H_ + +#include +#include +#include +#include + +#include "src/tint/lang/spirv/writer/common/function.h" +#include "src/tint/lang/spirv/writer/common/instruction.h" +#include "src/tint/utils/containers/hashset.h" + +namespace tint::spirv::writer { + +/// A SPIR-V module. +class Module { + public: + /// Constructor + Module(); + + /// Copy constructor + /// @param other the other Module to copy + Module(const Module& other); + + /// Move constructor + /// @param other the other Module to move + Module(Module&& other); + + /// Destructor + ~Module(); + + /// Copy-assignment operator + /// @param other the other Module to copy + /// @returns this Module + Module& operator=(const Module& other); + + /// Move-assignment operator + /// @param other the other Module to move + /// @returns this Module + Module& operator=(Module&& other); + + /// @returns the number of uint32_t's needed to make up the results + uint32_t TotalSize() const; + + /// @returns the id bound for this program + uint32_t IdBound() const { return next_id_; } + + /// @returns the next id to be used + uint32_t NextId() { + auto id = next_id_; + next_id_ += 1; + return id; + } + + /// Iterates over all the instructions in the correct order and calls the given callback. + /// @param cb the callback to execute + void Iterate(std::function cb) const; + + /// Add an instruction to the list of capabilities, if the capability hasn't already been added. + /// @param cap the capability to set + void PushCapability(uint32_t cap); + + /// @returns the capabilities + const InstructionList& Capabilities() const { return capabilities_; } + + /// Add an instruction to the list of extensions. + /// @param extension the name of the extension + void PushExtension(const char* extension); + + /// @returns the extensions + const InstructionList& Extensions() const { return extensions_; } + + /// Add an instruction to the list of imported extension instructions. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushExtImport(spv::Op op, const OperandList& operands) { + ext_imports_.push_back(Instruction{op, operands}); + } + + /// @returns the ext imports + const InstructionList& ExtImports() const { return ext_imports_; } + + /// Add an instruction to the memory model. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushMemoryModel(spv::Op op, const OperandList& operands) { + memory_model_.push_back(Instruction{op, operands}); + } + + /// @returns the memory model + const InstructionList& MemoryModel() const { return memory_model_; } + + /// Add an instruction to the list pf entry points. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushEntryPoint(spv::Op op, const OperandList& operands) { + entry_points_.push_back(Instruction{op, operands}); + } + /// @returns the entry points + const InstructionList& EntryPoints() const { return entry_points_; } + + /// Add an instruction to the execution mode declarations. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushExecutionMode(spv::Op op, const OperandList& operands) { + execution_modes_.push_back(Instruction{op, operands}); + } + + /// @returns the execution modes + const InstructionList& ExecutionModes() const { return execution_modes_; } + + /// Add an instruction to the debug declarations. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushDebug(spv::Op op, const OperandList& operands) { + debug_.push_back(Instruction{op, operands}); + } + + /// @returns the debug instructions + const InstructionList& Debug() const { return debug_; } + + /// Add an instruction to the type declarations. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushType(spv::Op op, const OperandList& operands) { + types_.push_back(Instruction{op, operands}); + } + + /// @returns the type instructions + const InstructionList& Types() const { return types_; } + + /// Add an instruction to the annotations. + /// @param op the op to set + /// @param operands the operands for the instruction + void PushAnnot(spv::Op op, const OperandList& operands) { + annotations_.push_back(Instruction{op, operands}); + } + + /// @returns the annotations + const InstructionList& Annots() const { return annotations_; } + + /// Add a function to the module. + /// @param func the function to add + void PushFunction(const Function& func) { functions_.push_back(func); } + + /// @returns the functions + const std::vector& Functions() const { return functions_; } + + /// @returns the SPIR-V code as a vector of uint32_t + std::vector& Code() { return code_; } + + private: + uint32_t next_id_ = 1; + InstructionList capabilities_; + InstructionList extensions_; + InstructionList ext_imports_; + InstructionList memory_model_; + InstructionList entry_points_; + InstructionList execution_modes_; + InstructionList debug_; + InstructionList types_; + InstructionList annotations_; + std::vector functions_; + Hashset capability_set_; + Hashset extension_set_; + std::vector code_; +}; + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_MODULE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.cc new file mode 100644 index 000000000..8fa581cf5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.cc @@ -0,0 +1,42 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/common/operand.h" + +namespace tint::spirv::writer { + +uint32_t OperandLength(const Operand& o) { + if (auto* str = std::get_if(&o)) { + // SPIR-V always nul-terminates strings. The length is rounded up to a + // multiple of 4 bytes with 0 bytes padding the end. Accounting for the + // nul terminator is why '+ 4u' is used here instead of '+ 3u'. + return static_cast((str->length() + 4u) >> 2); + } + return 1; +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.h new file mode 100644 index 000000000..3a4bcfc9a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/operand.h @@ -0,0 +1,59 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPERAND_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPERAND_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/math/hash.h" + +namespace tint::spirv::writer { + +/// A single SPIR-V instruction operand +using Operand = std::variant; + +// Helper for returning an uint32_t Operand with the provided integer value. +template +inline Operand U32Operand(T val) { + return Operand{static_cast(val)}; +} + +/// @returns the number of uint32_t's needed for this operand +uint32_t OperandLength(const Operand& o); + +/// A list of operands +using OperandList = std::vector; + +using OperandListKey = tint::UnorderedKeyWrapper; + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPERAND_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helper.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helper.cc new file mode 100644 index 000000000..025813efa --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helper.cc @@ -0,0 +1,234 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/common/option_helpers.h" + +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/diagnostic/diagnostic.h" + +namespace tint::spirv::writer { + +Result ValidateBindingOptions(const Options& options) { + diag::List diagnostics; + + tint::Hashmap seen_wgsl_bindings{}; + tint::Hashmap seen_spirv_bindings{}; + + // Both wgsl_seen and spirv_seen check to see if the pair of [src, dst] are unique. If we have + // multiple entries that map the same [src, dst] pair, that's fine. We treat it as valid as it's + // possible for multiple entry points to use the remapper at the same time. If the pair doesn't + // match, then we report an error about a duplicate binding point. + + auto wgsl_seen = [&diagnostics, &seen_wgsl_bindings](const tint::BindingPoint& src, + const tint::BindingPoint& dst) -> bool { + if (auto binding = seen_wgsl_bindings.Get(src)) { + if (*binding != dst) { + diagnostics.AddError(Source{}) << "found duplicate WGSL binding point: " << src; + return true; + } + } + seen_wgsl_bindings.Add(src, dst); + return false; + }; + + const auto& statically_paired_texture_binding_points = + options.statically_paired_texture_binding_points; + auto spirv_seen = [&diagnostics, &seen_spirv_bindings, + &statically_paired_texture_binding_points]( + const tint::BindingPoint& src, const tint::BindingPoint& dst) -> bool { + if (auto binding = seen_spirv_bindings.Get(src)) { + if (*binding != dst && !statically_paired_texture_binding_points.count(*binding) && + !statically_paired_texture_binding_points.count(dst)) { + diagnostics.AddError(Source{}) + << "found duplicate SPIR-V binding point: [group: " << src.group + << ", binding: " << src.binding << "]"; + return true; + } + } + seen_spirv_bindings.Add(src, dst); + return false; + }; + + auto valid = [&wgsl_seen, &spirv_seen](const auto& hsh) -> bool { + for (const auto& it : hsh) { + const auto& src_binding = it.first; + const auto& dst_binding = it.second; + + if (wgsl_seen(src_binding, dst_binding)) { + return false; + } + + if (spirv_seen(dst_binding, src_binding)) { + return false; + } + } + return true; + }; + + if (!valid(options.bindings.uniform)) { + diagnostics.AddNote(Source{}) << "when processing uniform"; + return Failure{diagnostics.Str()}; + } + if (!valid(options.bindings.storage)) { + diagnostics.AddNote(Source{}) << "when processing storage"; + return Failure{diagnostics.Str()}; + } + if (!valid(options.bindings.texture)) { + diagnostics.AddNote(Source{}) << "when processing texture"; + return Failure{diagnostics.Str()}; + } + if (!valid(options.bindings.storage_texture)) { + diagnostics.AddNote(Source{}) << "when processing storage_texture"; + return Failure{diagnostics.Str()}; + } + if (!valid(options.bindings.sampler)) { + diagnostics.AddNote(Source{}) << "when processing sampler"; + return Failure{diagnostics.Str()}; + } + if (!valid(options.bindings.input_attachment)) { + diagnostics.AddNote(Source{}) << "when processing input_attachment"; + return Failure{diagnostics.Str()}; + } + + for (const auto& it : options.bindings.external_texture) { + const auto& src_binding = it.first; + const auto& plane0 = it.second.plane0; + const auto& plane1 = it.second.plane1; + const auto& metadata = it.second.metadata; + + // Validate with the actual source regardless of what the remapper will do + if (wgsl_seen(src_binding, plane0)) { + diagnostics.AddNote(Source{}) << "when processing external_texture"; + return Failure{diagnostics.Str()}; + } + + if (spirv_seen(plane0, src_binding)) { + diagnostics.AddNote(Source{}) << "when processing external_texture"; + return Failure{diagnostics.Str()}; + } + if (spirv_seen(plane1, src_binding)) { + diagnostics.AddNote(Source{}) << "when processing external_texture"; + return Failure{diagnostics.Str()}; + } + if (spirv_seen(metadata, src_binding)) { + diagnostics.AddNote(Source{}) << "when processing external_texture"; + return Failure{diagnostics.Str()}; + } + } + + return Success; +} + +// The remapped binding data and external texture data need to coordinate in order to put things in +// the correct place when we're done. +// +// When the data comes in we have a list of all WGSL origin (group,binding) pairs to SPIR-V +// (group,binding) pairs in the `uniform`, `storage`, `texture`, and `sampler` arrays. +// +// The `external_texture` array stores a WGSL origin (group,binding) pair for the external textures +// which provide `plane0`, `plane1`, and `metadata` SPIR-V (group,binding) pairs. +// +// If the remapper is run first, then the `external_texture` will end up being moved from the WGSL +// point, or the SPIR-V point (or the `plane0` value). There will also, possibly, have been bindings +// moved aside in order to place the `external_texture` bindings. +// +// If multiplanar runs first, care needs to be taken that when the texture is split and we create +// `plane1` and `metadata` that they do not collide with existing bindings. If they would collide +// then we need to place them elsewhere and have the remapper place them in the correct locations. +// +// # Example +// WGSL: +// @group(0) @binding(0) var u: Uniforms; +// @group(0) @binding(1) var s: sampler; +// @group(0) @binding(2) var t: texture_external; +// +// Given that program, Dawn may decide to do the remappings such that: +// * WGSL u (0, 0) -> SPIR-V (0, 1) +// * WGSL s (0, 1) -> SPIR-V (0, 2) +// * WGSL t (0, 2): +// * plane0 -> SPIR-V (0, 3) +// * plane1 -> SPIR-V (0, 4) +// * metadata -> SPIR-V (0, 0) +// +// In this case, if we run binding remapper first, then tell multiplanar to look for the texture at +// (0, 3) instead of the original (0, 2). +// +// If multiplanar runs first, then metadata (0, 0) needs to be placed elsewhere and then remapped +// back to (0, 0) by the remapper. (Otherwise, we'll have two `@group(0) @binding(0)` items in the +// program.) +// +// # Status +// The below method assumes we run binding remapper first. So it will setup the binding data and +// switch the value used by the multiplanar. +void PopulateRemapperAndMultiplanarOptions( + const Options& options, + RemapperData& remapper_data, + tint::transform::multiplanar::BindingsMap& multiplanar_map) { + auto create_remappings = [&remapper_data](const auto& hsh) { + for (const auto& it : hsh) { + const BindingPoint& src_binding_point = it.first; + const auto& dst_binding_point = it.second; + + // Bindings which go to the same slot in SPIR-V do not need to be re-bound. + if (src_binding_point == dst_binding_point) { + continue; + } + + remapper_data.emplace(src_binding_point, dst_binding_point); + } + }; + + create_remappings(options.bindings.uniform); + create_remappings(options.bindings.storage); + create_remappings(options.bindings.texture); + create_remappings(options.bindings.storage_texture); + create_remappings(options.bindings.sampler); + create_remappings(options.bindings.input_attachment); + + // External textures are re-bound to their plane0 location + for (const auto& it : options.bindings.external_texture) { + const BindingPoint& src_binding_point = it.first; + const auto& plane0 = it.second.plane0; + const auto& plane1 = it.second.plane1; + const auto& metadata = it.second.metadata; + + // Use the re-bound spir-v plane0 value for the lookup key. + multiplanar_map.emplace(plane0, + tint::transform::multiplanar::BindingPoints{plane1, metadata}); + + // Bindings which go to the same slot in SPIR-V do not need to be re-bound. + if (src_binding_point == plane0) { + continue; + } + + remapper_data.emplace(src_binding_point, plane0); + } +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helpers.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helpers.h new file mode 100644 index 000000000..355861f98 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/option_helpers.h @@ -0,0 +1,58 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_HELPERS_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_HELPERS_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/ir/transform/multiplanar_options.h" +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/utils/result.h" + +namespace tint::spirv::writer { + +using RemapperData = std::unordered_map; + +/// @param options the options +/// @return success or failure +Result ValidateBindingOptions(const Options& options); + +/// Populates data from the writer options for the remapper and external texture. +/// @param options the writer options +/// @param remapper_data where to put the remapper data +/// @param multiplanar_map where to store the multiplanar texture options +/// Note, these are populated together because there are dependencies between the two types of data. +void PopulateRemapperAndMultiplanarOptions( + const Options& options, + RemapperData& remapper_data, + tint::transform::multiplanar::BindingsMap& multiplanar_map); + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_HELPERS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/options.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/options.h new file mode 100644 index 000000000..f955100fc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/options.h @@ -0,0 +1,258 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_ + +#include +#include +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/api/common/bindings.h" +#include "src/tint/api/common/resource_table_config.h" +#include "src/tint/api/common/substitute_overrides_config.h" +#include "src/tint/utils/reflection.h" + +namespace tint::spirv::writer { + +/// Supported SPIR-V binary versions. +/// If a new version is added here, also add it to: +/// * Writer::CanGenerate +/// * Printer::Code +/// Fully usable version will also need additions to: +/// * --spir-version on the command line +/// * Dawn in the Vulkan backend +enum class SpvVersion : uint32_t { + kSpv13, // SPIR-V 1.3 + kSpv14, // SPIR-V 1.4 + kSpv15, // SPIR-V 1.5, for testing purposes only +}; + +/// Configuration options used for generating SPIR-V. +struct Options { + struct RangeOffsets { + /// The offset of the min_depth immediate data + uint32_t min = 0; + /// The offset of the max_depth immediate data + uint32_t max = 0; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(RangeOffsets, min, max); + TINT_REFLECT_HASH_CODE(RangeOffsets); + }; + + /// The set of options which control workarounds for driver issues in the SPIR-V generator. + struct Workarounds { + /////////////////////////////////////////////////////////////////////////////////////////// + // NOTE: When adding a new option here, it should also be added to the FuzzedOptions // + // structure in writer_fuzz.cc. // + /////////////////////////////////////////////////////////////////////////////////////////// + + /// Set to `true` to generate a polyfill for switch statements using if/else statements. + bool polyfill_case_switch = false; + + /// Set to `true` to scalarize max min and clamp builtins. + bool scalarize_max_min_clamp = false; + + /// Set to `true` if handles should be transformed by direct variable access. + bool dva_transform_handle = false; + + /// Set to `true` to generate polyfill for `pack4x8snorm`, `pack4x8unorm`, `unpack4x8snorm` + /// and `unpack4x8unorm` builtins + bool polyfill_pack_unpack_4x8_norm = false; + + /// Set to `true` to generate a polyfill clamp of `id` param of subgroupShuffle to within + /// the spec max subgroup size. + bool subgroup_shuffle_clamped = false; + + /// Set to 'true' to force workaround for 'textureSampleCompare(Level)' for texture arrays + /// of cube depth. + bool texture_sample_compare_depth_cube_array = false; + + /// Set to `true` to generate polyfill for `subgroupBroadcast(f16)` + bool polyfill_subgroup_broadcast_f16 = false; + + /// Set to `true` to always pass matrices to user functions by pointer instead of by value. + bool pass_matrix_by_pointer = false; + + /// Set to `true` to generate polyfill for f32 negation. + bool polyfill_unary_f32_negation = false; + + /// Set to `true` to generate polyfill for f32 abs. + bool polyfill_f32_abs = false; + + TINT_REFLECT(Workarounds, + polyfill_case_switch, + scalarize_max_min_clamp, + dva_transform_handle, + polyfill_pack_unpack_4x8_norm, + subgroup_shuffle_clamped, + texture_sample_compare_depth_cube_array, + polyfill_subgroup_broadcast_f16, + pass_matrix_by_pointer, + polyfill_unary_f32_negation, + polyfill_f32_abs); + }; + + /// Any options which are controlled by the presence/absence of a vulkan extension. + struct Extensions { + /////////////////////////////////////////////////////////////////////////////////////////// + // NOTE: When adding a new option here, it should also be added to the FuzzedOptions // + // structure in writer_fuzz.cc. // + /////////////////////////////////////////////////////////////////////////////////////////// + + /// Set to `true` to allow for the usage of the demote to helper extension. + bool use_demote_to_helper_invocation = false; + + /// Set to `true` to use the StorageInputOutput16 capability for shader IO that uses f16 + /// types. + bool use_storage_input_output_16 = true; + + /// Set to `true` to initialize workgroup memory with OpConstantNull when + /// VK_KHR_zero_initialize_workgroup_memory is enabled. + bool use_zero_initialize_workgroup_memory = false; + + /// Set to `true` if the Vulkan Memory Model should be used + bool use_vulkan_memory_model = false; + + /// Set to `true` to skip robustness transform on textures. + bool disable_image_robustness = false; + + /// Set to `true` to disable index clamping on the runtime-sized arrays in robustness + /// transform. + bool disable_runtime_sized_array_index_clamping = false; + + /// Set to `true` to generate polyfill for `dot4I8Packed` and `dot4U8Packed` builtins + bool dot_4x8_packed = false; + + /// Set to `true` to use the uniform buffer directly, `false` to decompose into array. + bool use_uniform_buffers = false; + + TINT_REFLECT(Extensions, + use_demote_to_helper_invocation, + use_storage_input_output_16, + use_zero_initialize_workgroup_memory, + use_vulkan_memory_model, + disable_image_robustness, + disable_runtime_sized_array_index_clamping, + dot_4x8_packed, + use_uniform_buffers); + }; + + /////////////////////////////////////////////////////////////////////////////////////////// + // NOTE: When adding a new option here, it should also be added to the FuzzedOptions // + // structure in writer_fuzz.cc (if fuzzing is desired). // + /////////////////////////////////////////////////////////////////////////////////////////// + + /// The entry point name to generate + std::string entry_point_name; + + /// An optional remapped name to use when emitting the entry point. + std::string remapped_entry_point_name = {}; + + /// The bindings + Bindings bindings = {}; + + // BindingPoints for textures that are paired with static samplers in the + // BGL. These BindingPoints are the only ones that are allowed to map to + // duplicate spir-v bindings, since they must map to the spir-v bindings of + // the samplers with which they are paired. + std::unordered_set statically_paired_texture_binding_points = {}; + + /// Set to `true` to strip all user-declared identifiers from the module. + bool strip_all_names = false; + + /// Set to `true` to disable software robustness that prevents out-of-bounds accesses. + bool disable_robustness = false; + + /// Set to `true` to disable workgroup memory zero initialization + bool disable_workgroup_init = false; + + /// Set to `true` to disable the polyfills on integer division and modulo. + bool disable_polyfill_integer_div_mod = false; + + /// Set to `true` to enable integer range analysis in robustness transform. + bool disable_integer_range_analysis = false; + + /// Set to `true` to generate a PointSize builtin and have it set to 1.0 + /// from all vertex shaders in the module. + bool emit_vertex_point_size = true; + + /// Set to `true` to apply builtin 'position' pixel center emulation. + bool polyfill_pixel_center = false; + + /// Any workarounds to enable/disable. + Workarounds workarounds{}; + + /// Any used extensions + Extensions extensions{}; + + /// Offsets of the minDepth and maxDepth push constants. + std::optional depth_range_offsets = std::nullopt; + + /// SPIR-V binary version. + SpvVersion spirv_version = SpvVersion::kSpv13; + + /// Resource table information + std::optional resource_table = std::nullopt; + + // Configuration for substitute overrides + SubstituteOverridesConfig substitute_overrides_config = {}; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(Options, + entry_point_name, + remapped_entry_point_name, + bindings, + statically_paired_texture_binding_points, + strip_all_names, + disable_robustness, + disable_workgroup_init, + disable_polyfill_integer_div_mod, + disable_integer_range_analysis, + emit_vertex_point_size, + polyfill_pixel_center, + workarounds, + extensions, + depth_range_offsets, + spirv_version, + resource_table, + substitute_overrides_config); +}; + +} // namespace tint::spirv::writer + +namespace tint { + +/// Reflect enum information for SPIR-V version. +TINT_REFLECT_ENUM_RANGE(spirv::writer::SpvVersion, kSpv13, kSpv14); + +} // namespace tint + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/output.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/common/output.cc new file mode 100644 index 000000000..41ccd1cce --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/output.cc @@ -0,0 +1,40 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/common/output.h" + +namespace tint::spirv::writer { + +Output::Output() = default; + +Output::~Output() = default; + +Output::Output(const Output&) = default; + +Output& Output::operator=(const Output&) = default; + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/common/output.h b/3rdparty/dawn/src/tint/lang/spirv/writer/common/output.h new file mode 100644 index 000000000..44d5a6141 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/common/output.h @@ -0,0 +1,84 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OUTPUT_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OUTPUT_H_ + +#include + +#include +#include +#include + +#include "src/tint/api/common/subgroup_matrix.h" + +namespace tint::spirv::writer { + +/// The output produced when generating SPIR-V. +struct Output { + /// Constructor + Output(); + + /// Destructor + ~Output(); + + /// Copy constructor + Output(const Output&); + + /// Copy assignment + /// @returns this + Output& operator=(const Output&); + + /// Workgroup size information + struct WorkgroupInfo { + /// The x-component + uint32_t x = 0; + /// The y-component + uint32_t y = 0; + /// The z-component + uint32_t z = 0; + + /// The needed workgroup storage size + size_t storage_size = 0; + + /// The `@subgroup_size` attribute + std::optional subgroup_size = {}; + }; + + /// The generated SPIR-V. + std::vector spirv; + + /// The workgroup size information, if the entry point was a compute shader + WorkgroupInfo workgroup_info{}; + + /// The subgroup matrix information + SubgroupMatrixInfo subgroup_matrix_info{}; +}; + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_OUTPUT_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.cc new file mode 100644 index 000000000..2d71e7b2f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.cc @@ -0,0 +1,3042 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/printer/printer.h" + +#include +#include +#include + +#include "spirv/unified1/GLSL.std.450.h" +#include "spirv/unified1/spirv.h" + +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/block_param.h" +#include "src/tint/lang/core/ir/break_if.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/continue.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/discard.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/load_vector_element.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/store_vector_element.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/terminate_invocation.h" +#include "src/tint/lang/core/ir/terminator.h" +#include "src/tint/lang/core/ir/unreachable.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/atomic.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/subgroup_matrix.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/lang/spirv/ir/binary.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/lang/spirv/ir/copy_logical.h" +#include "src/tint/lang/spirv/ir/literal_operand.h" +#include "src/tint/lang/spirv/type/explicit_layout_array.h" +#include "src/tint/lang/spirv/type/resource_table.h" +#include "src/tint/lang/spirv/type/sampled_image.h" +#include "src/tint/lang/spirv/writer/common/binary_writer.h" +#include "src/tint/lang/spirv/writer/common/function.h" +#include "src/tint/lang/spirv/writer/common/module.h" +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/lang/spirv/writer/raise/builtin_polyfill.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/symbol/symbol.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::spirv::writer { +namespace { + +constexpr uint32_t kWriterVersion = 1; +constexpr const char* kGLSLstd450 = "GLSL.std.450"; + +SpvStorageClass StorageClass(core::AddressSpace addrspace) { + switch (addrspace) { + case core::AddressSpace::kHandle: + return SpvStorageClassUniformConstant; + case core::AddressSpace::kFunction: + return SpvStorageClassFunction; + case core::AddressSpace::kIn: + return SpvStorageClassInput; + case core::AddressSpace::kPrivate: + return SpvStorageClassPrivate; + case core::AddressSpace::kImmediate: + return SpvStorageClassPushConstant; + case core::AddressSpace::kOut: + return SpvStorageClassOutput; + case core::AddressSpace::kStorage: + return SpvStorageClassStorageBuffer; + case core::AddressSpace::kUniform: + return SpvStorageClassUniform; + case core::AddressSpace::kWorkgroup: + return SpvStorageClassWorkgroup; + default: + return SpvStorageClassMax; + } +} + +const core::type::Type* DedupType(const core::type::Type* ty, core::type::Manager& types) { + return Switch( + ty, + + // Atomics are not a distinct type in SPIR-V. + [&](const core::type::Atomic* atomic) { return atomic->Type(); }, + + // Both sampler types are the same in SPIR-V. + [&](const core::type::Sampler* s) -> const core::type::Type* { + if (s->IsComparison()) { + return types.Get(core::type::SamplerKind::kSampler); + } + return s; + }, + + // The Vulkan spec says: The "Depth" operand of OpTypeImage is ignored. + // In SPIRV, 0 means not depth, 1 means depth, and 2 means unknown. + // Using anything other than 0 is problematic on various Vulkan drivers. + [&](const type::Image* img) -> const core::type::Type* { + // Set storage textures to access `read` + auto access = img->GetAccess(); + if (img->GetTexelFormat() != core::TexelFormat::kUndefined) { + access = core::Access::kRead; + } + + // Depth textures are always declared as sampled textures. + return types.Get( + img->GetSampledType(), img->GetDim(), type::Depth::kNotDepth, img->GetArrayed(), + img->GetMultisampled(), img->GetSampled(), img->GetTexelFormat(), access); + }, + + // Dedup a SampledImage if its underlying image will be deduped. + [&](const type::SampledImage* si) -> const core::type::Type* { + auto* img = DedupType(si->Image(), types); + if (img != si->Image()) { + return types.Get(img); + } + return si; + }, + + [&](Default) { return ty; }); +} + +/// PIMPL class for SPIR-V writer +class Printer { + public: + /// Constructor + /// @param module the Tint IR module to generate + /// @param options the printer options + Printer(core::ir::Module& module, const Options& options) + : ir_(module), b_(module), options_(options) { + zero_init_workgroup_memory_ = !options.disable_workgroup_init && + options.extensions.use_zero_initialize_workgroup_memory; + } + + /// @returns the generated SPIR-V code on success, or failure + Result Code() { + TINT_CHECK_RESULT(Generate()); + + uint32_t version = 0u; + switch (options_.spirv_version) { + case SpvVersion::kSpv13: + version = 0x10300u; + break; + case SpvVersion::kSpv14: + version = 0x10400u; + break; + case SpvVersion::kSpv15: + version = 0x10500u; + break; + default: + TINT_IR_ICE(ir_) << "unsupported SPIR-V version"; + } + + // Serialize the module into binary SPIR-V. + BinaryWriter writer; + writer.WriteHeader(module_.IdBound(), kWriterVersion, version); + writer.WriteModule(module_); + + output_.spirv = std::move(writer.Result()); + return output_; + } + + private: + core::ir::Module& ir_; + core::ir::Builder b_; + Options options_; + writer::Module module_; + BinaryWriter writer_; + + Output output_; + + struct BlockInfo { + size_t idx; + core::ir::Block* block; + }; + std::deque blocks_to_emit_; + + /// A function type used for an OpTypeFunction declaration. + struct FunctionType { + uint32_t return_type_id; + Vector param_type_ids; + + /// @returns the hash code of the FunctionType + tint::HashCode HashCode() const { + auto hash = Hash(return_type_id); + for (auto& p : param_type_ids) { + hash = HashCombine(hash, p); + } + return hash; + } + + /// Equality operator for FunctionType. + bool operator==(const FunctionType& other) const { + return (param_type_ids == other.param_type_ids) && + (return_type_id == other.return_type_id); + } + }; + + /// The map of types to their result IDs. + Hashmap types_; + + /// The map of function types to their result IDs. + Hashmap function_types_; + + /// The map of constants to their result IDs. + Hashmap constants_; + + /// The map of types to the result IDs of their OpConstantNull instructions. + Hashmap constant_nulls_; + + /// The map of types to the result IDs of their OpUndef instructions. + Hashmap undef_values_; + + /// The map of non-constant values to their result IDs. + Hashmap values_; + + /// The map of blocks to the IDs of their label instructions. + Hashmap block_labels_; + + /// The map of control instructions to the IDs of the label of their SPIR-V merge blocks. + Hashmap merge_block_labels_; + + /// The map of loop instructions to the IDs of the label of their SPIR-V header blocks. + Hashmap loop_header_block_labels_; + + /// The map of extended instruction set names to their result IDs. + Hashmap imports_; + + /// The current function that is being emitted. + Function current_function_; + + bool zero_init_workgroup_memory_ = false; + + /// Builds the SPIR-V from the IR + Result Generate() { + TINT_CHECK_RESULT( + core::ir::ValidateAndDumpIfNeeded(ir_, "spirv.Printer", kPrinterCapabilities)); + + module_.PushCapability(SpvCapabilityShader); + + if (options_.extensions.use_vulkan_memory_model) { + module_.PushExtension("SPV_KHR_vulkan_memory_model"); + module_.PushCapability(SpvCapabilityVulkanMemoryModelKHR); + // Required for the `Device` scope on atomic operations + module_.PushCapability(SpvCapabilityVulkanMemoryModelDeviceScopeKHR); + module_.PushMemoryModel(spv::Op::OpMemoryModel, {U32Operand(SpvAddressingModelLogical), + U32Operand(SpvMemoryModelVulkanKHR)}); + } else { + module_.PushMemoryModel(spv::Op::OpMemoryModel, {U32Operand(SpvAddressingModelLogical), + U32Operand(SpvMemoryModelGLSL450)}); + } + + // Emit module-scope declarations. + EmitRootBlock(ir_.root_block); + + // Emit functions. + for (core::ir::Function* func : ir_.functions) { + TINT_CHECK_RESULT(EmitFunction(func)); + } + + return Success; + } + + /// Convert a builtin to the corresponding SPIR-V enum value, taking into account the target + /// address space. Adds any capabilities needed for the builtin. + /// @param builtin the builtin to convert + /// @param addrspace the address space the builtin is being used in + /// @returns the enum value of the corresponding SPIR-V builtin + uint32_t Builtin(core::BuiltinValue builtin, core::AddressSpace addrspace) { + switch (builtin) { + case core::BuiltinValue::kPointSize: + return SpvBuiltInPointSize; + case core::BuiltinValue::kCullDistance: + return SpvBuiltInCullDistance; + case core::BuiltinValue::kFragDepth: + return SpvBuiltInFragDepth; + case core::BuiltinValue::kFrontFacing: + return SpvBuiltInFrontFacing; + case core::BuiltinValue::kGlobalInvocationId: + return SpvBuiltInGlobalInvocationId; + case core::BuiltinValue::kInstanceIndex: + return SpvBuiltInInstanceIndex; + case core::BuiltinValue::kLocalInvocationId: + return SpvBuiltInLocalInvocationId; + case core::BuiltinValue::kLocalInvocationIndex: + return SpvBuiltInLocalInvocationIndex; + case core::BuiltinValue::kNumWorkgroups: + return SpvBuiltInNumWorkgroups; + case core::BuiltinValue::kPosition: + if (addrspace == core::AddressSpace::kOut) { + // Vertex output. + return SpvBuiltInPosition; + } else { + // Fragment input. + return SpvBuiltInFragCoord; + } + case core::BuiltinValue::kSampleIndex: + module_.PushCapability(SpvCapabilitySampleRateShading); + return SpvBuiltInSampleId; + case core::BuiltinValue::kSampleMask: + return SpvBuiltInSampleMask; + case core::BuiltinValue::kSubgroupId: + module_.PushCapability(SpvCapabilityGroupNonUniform); + return SpvBuiltInSubgroupId; + case core::BuiltinValue::kSubgroupInvocationId: + module_.PushCapability(SpvCapabilityGroupNonUniform); + return SpvBuiltInSubgroupLocalInvocationId; + case core::BuiltinValue::kSubgroupSize: + module_.PushCapability(SpvCapabilityGroupNonUniform); + return SpvBuiltInSubgroupSize; + case core::BuiltinValue::kNumSubgroups: + module_.PushCapability(SpvCapabilityGroupNonUniform); + return SpvBuiltInNumSubgroups; + case core::BuiltinValue::kVertexIndex: + return SpvBuiltInVertexIndex; + case core::BuiltinValue::kWorkgroupId: + return SpvBuiltInWorkgroupId; + case core::BuiltinValue::kClipDistances: + module_.PushCapability(SpvCapabilityClipDistance); + return SpvBuiltInClipDistance; + case core::BuiltinValue::kPrimitiveIndex: + // TODO(dsinclair): This can be others, but use geometry for now. + module_.PushCapability(SpvCapabilityGeometry); + return SpvBuiltInPrimitiveId; + case core::BuiltinValue::kBarycentricCoord: + module_.PushExtension("SPV_KHR_fragment_shader_barycentric"); + module_.PushCapability(SpvCapabilityFragmentBarycentricKHR); + return SpvBuiltInBaryCoordKHR; + case core::BuiltinValue::kUndefined: + return SpvBuiltInMax; + } + return SpvBuiltInMax; + } + + /// Get the result ID of the constant `constant`, emitting its instruction if necessary. + /// @param constant the constant to get the ID for + /// @returns the result ID of the constant + uint32_t Constant(core::ir::Constant* constant) { + // If it is a literal operand, just return the value. + if (auto* literal = constant->As()) { + return literal->Value()->ValueAs(); + } + + auto id = Constant(constant->Value()); + + // Set the name for the SPIR-V result ID if provided in the module. + PushName(id, constant); + + return id; + } + + /// Get the result ID of the constant `constant`, emitting its instruction if necessary. + /// @param constant the constant to get the ID for + /// @returns the result ID of the constant + uint32_t Constant(const core::constant::Value* constant) { + return constants_.GetOrAdd(constant, [&] { + auto* ty = constant->Type(); + + // Use OpConstantNull for zero-valued composite constants. + if (!ty->Is() && constant->AllZero()) { + return ConstantNull(ty); + } + + auto id = module_.NextId(); + Switch( + ty, // + [&](const core::type::Bool*) { + module_.PushType(constant->ValueAs() ? spv::Op::OpConstantTrue + : spv::Op::OpConstantFalse, + {Type(ty), id}); + }, + [&](const core::type::I32*) { + module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs()}); + }, + [&](const core::type::U32*) { + module_.PushType(spv::Op::OpConstant, + {Type(ty), id, U32Operand(constant->ValueAs())}); + }, + [&](const core::type::I8*) { + module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs()}); + }, + [&](const core::type::U8*) { + module_.PushType(spv::Op::OpConstant, + {Type(ty), id, U32Operand(constant->ValueAs())}); + }, + [&](const core::type::F32*) { + module_.PushType(spv::Op::OpConstant, {Type(ty), id, constant->ValueAs()}); + }, + [&](const core::type::F16*) { + module_.PushType( + spv::Op::OpConstant, + {Type(ty), id, U32Operand(constant->ValueAs().BitsRepresentation())}); + }, + [&](const core::type::Vector* vec) { + OperandList operands = {Type(ty), id}; + for (uint32_t i = 0; i < vec->Width(); i++) { + operands.push_back(Constant(constant->Index(i))); + } + module_.PushType(spv::Op::OpConstantComposite, operands); + }, + [&](const core::type::Matrix* mat) { + OperandList operands = {Type(ty), id}; + for (uint32_t i = 0; i < mat->Columns(); i++) { + operands.push_back(Constant(constant->Index(i))); + } + module_.PushType(spv::Op::OpConstantComposite, operands); + }, + [&](const core::type::Array* arr) { + TINT_IR_ASSERT(ir_, arr->ConstantCount()); + OperandList operands = {Type(ty), id}; + for (uint32_t i = 0; i < arr->ConstantCount(); i++) { + operands.push_back(Constant(constant->Index(i))); + } + module_.PushType(spv::Op::OpConstantComposite, operands); + }, + [&](const core::type::Struct* str) { + OperandList operands = {Type(ty), id}; + for (uint32_t i = 0; i < str->Members().Length(); i++) { + operands.push_back(Constant(constant->Index(i))); + } + module_.PushType(spv::Op::OpConstantComposite, operands); + }, // + TINT_ICE_ON_NO_MATCH); + return id; + }); + } + + /// Get the result ID of the OpConstantNull instruction for `type`, emitting it if necessary. + /// @param type the type to get the ID for + /// @returns the result ID of the OpConstantNull instruction + uint32_t ConstantNull(const core::type::Type* type) { + return constant_nulls_.GetOrAdd(type, [&] { + auto id = module_.NextId(); + module_.PushType(spv::Op::OpConstantNull, {Type(type), id}); + return id; + }); + } + + /// Get the result ID of the OpUndef instruction with type `ty`, emitting it if necessary. + /// @param type the type of the undef value + /// @returns the result ID of the instruction + uint32_t Undef(const core::type::Type* type) { + return undef_values_.GetOrAdd(type, [&] { + auto id = module_.NextId(); + module_.PushType(spv::Op::OpUndef, {Type(type), id}); + return id; + }); + } + + /// Get the result ID of the type `ty`, emitting a type declaration instruction if necessary. + /// @param ty the type to get the ID for + /// @returns the result ID of the type + uint32_t Type(const core::type::Type* ty) { + ty = DedupType(ty, ir_.Types()); + return types_.GetOrAdd(ty, [&] { + auto id = module_.NextId(); + Switch( + ty, // + [&](const core::type::Void*) { module_.PushType(spv::Op::OpTypeVoid, {id}); }, + [&](const core::type::Bool*) { module_.PushType(spv::Op::OpTypeBool, {id}); }, + [&](const core::type::I32*) { + module_.PushType(spv::Op::OpTypeInt, {id, 32u, 1u}); + }, + [&](const core::type::U32*) { + module_.PushType(spv::Op::OpTypeInt, {id, 32u, 0u}); + }, + [&](const core::type::I8*) { + module_.PushCapability(SpvCapabilityInt8); + module_.PushType(spv::Op::OpTypeInt, {id, 8u, 1u}); + }, + [&](const core::type::U8*) { + module_.PushCapability(SpvCapabilityInt8); + module_.PushType(spv::Op::OpTypeInt, {id, 8u, 0u}); + }, + [&](const core::type::F32*) { module_.PushType(spv::Op::OpTypeFloat, {id, 32u}); }, + [&](const core::type::F16*) { + module_.PushCapability(SpvCapabilityFloat16); + module_.PushCapability(SpvCapabilityStorageBuffer16BitAccess); + if (options_.extensions.use_uniform_buffers) { + module_.PushCapability(SpvCapabilityUniformAndStorageBuffer16BitAccess); + } + module_.PushType(spv::Op::OpTypeFloat, {id, 16u}); + }, + [&](const core::type::Vector* vec) { + module_.PushType(spv::Op::OpTypeVector, {id, Type(vec->Type()), vec->Width()}); + }, + [&](const core::type::Matrix* mat) { + module_.PushType(spv::Op::OpTypeMatrix, + {id, Type(mat->ColumnType()), mat->Columns()}); + }, + [&](const core::type::Array* arr) { + if (arr->ConstantCount()) { + auto* count = b_.ConstantValue(u32(arr->ConstantCount().value())); + module_.PushType(spv::Op::OpTypeArray, + {id, Type(arr->ElemType()), Constant(count)}); + } else { + TINT_IR_ASSERT(ir_, arr->Count()->Is()); + module_.PushType(spv::Op::OpTypeRuntimeArray, {id, Type(arr->ElemType())}); + } + if (auto* ex = arr->As()) { + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationArrayStride), ex->Stride()}); + } + }, + [&](const core::type::BindingArray* arr) { + auto* count = b_.ConstantValue( + u32(arr->Count()->As()->value)); + module_.PushType(spv::Op::OpTypeArray, + {id, Type(arr->ElemType()), Constant(count)}); + }, + [&](const spirv::type::ResourceTable* rb) { + module_.PushCapability(SpvCapabilityRuntimeDescriptorArray); + module_.PushExtension("SPV_EXT_descriptor_indexing"); + module_.PushType(spv::Op::OpTypeRuntimeArray, {id, Type(rb->GetBindingType())}); + }, + [&](const core::type::Pointer* ptr) { + module_.PushType(spv::Op::OpTypePointer, + {id, U32Operand(StorageClass(ptr->AddressSpace())), + Type(ptr->StoreType())}); + }, + [&](const core::type::Struct* str) { EmitStructType(id, str); }, + [&](const core::type::Sampler*) { module_.PushType(spv::Op::OpTypeSampler, {id}); }, + [&](const type::SampledImage* s) { + module_.PushType(spv::Op::OpTypeSampledImage, {id, Type(s->Image())}); + }, + [&](const core::type::SubgroupMatrix* sm) { + TINT_IR_ASSERT(ir_, options_.extensions.use_vulkan_memory_model); + auto scope = Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup))); + auto cols = Constant(ir_.constant_values.Get(u32(sm->Columns()))); + auto rows = Constant(ir_.constant_values.Get(u32(sm->Rows()))); + spv::CooperativeMatrixUse use = spv::CooperativeMatrixUse::Max; + switch (sm->Kind()) { + case core::SubgroupMatrixKind::kLeft: + use = spv::CooperativeMatrixUse::MatrixAKHR; + break; + case core::SubgroupMatrixKind::kRight: + use = spv::CooperativeMatrixUse::MatrixBKHR; + break; + case core::SubgroupMatrixKind::kResult: + use = spv::CooperativeMatrixUse::MatrixAccumulatorKHR; + break; + case core::SubgroupMatrixKind::kUndefined: + TINT_IR_UNREACHABLE(ir_); + } + module_.PushExtension("SPV_KHR_cooperative_matrix"); + module_.PushCapability(SpvCapabilityCooperativeMatrixKHR); + module_.PushType(spv::Op::OpTypeCooperativeMatrixKHR, + { + id, + Type(sm->Type()), + scope, + rows, + cols, + Constant(ir_.constant_values.Get(u32(use))), + }); + }, + [&](const spirv::type::Image* img) { + if (img->GetDim() == type::Dim::kD1) { + if (img->GetSampled() == type::Sampled::kReadWriteOpCompatible) { + module_.PushCapability(SpvCapabilityImage1D); + } else { + module_.PushCapability(SpvCapabilitySampled1D); + } + } else if (img->GetDim() == type::Dim::kBuffer) { + module_.PushCapability(SpvCapabilityImageBuffer); + } else if (img->GetDim() == type::Dim::kSubpassData) { + module_.PushCapability(SpvCapabilityInputAttachment); + } else if (img->GetDim() == type::Dim::kCube && + img->GetArrayed() == type::Arrayed::kArrayed && + img->GetSampled() != type::Sampled::kReadWriteOpCompatible) { + module_.PushCapability(SpvCapabilitySampledCubeArray); + } + + uint32_t sampled_type = Type(img->GetSampledType()); + uint32_t dim = static_cast(img->GetDim()); + uint32_t depth = static_cast(img->GetDepth()); + uint32_t ms = static_cast(img->GetMultisampled()); + uint32_t sampled = static_cast(img->GetSampled()); + uint32_t array = static_cast(img->GetArrayed()); + uint32_t format = TexelFormat(img->GetTexelFormat()); + + module_.PushType(spv::Op::OpTypeImage, + {id, sampled_type, dim, depth, array, ms, sampled, format}); + }, // + TINT_ICE_ON_NO_MATCH); + return id; + }); + } + + /// 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(core::ir::Instruction* inst) { return Value(inst->Result()); } + + /// Get the result ID of the value `value`, emitting its instruction if necessary. + /// @param value the value to get the ID for + /// @returns the result ID of the value + uint32_t Value(core::ir::Value* value) { + return Switch( + value, // + [&](core::ir::Constant* constant) { return Constant(constant); }, + [&](core::ir::Value*) { + return values_.GetOrAdd(value, [&] { return module_.NextId(); }); + }); + } + + /// 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 + uint32_t Label(const core::ir::Block* block) { + return block_labels_.GetOrAdd(block, [&] { return module_.NextId(); }); + } + + /// Emit a struct type. + /// @param id the result ID to use + /// @param str the struct type to emit + void EmitStructType(uint32_t id, const core::type::Struct* str) { + // Helper to return `type` or a potentially nested array element type within `type` as a + // matrix type, or nullptr if no such matrix type is present. + auto get_nested_matrix_type = [&](const core::type::Type* type) { + while (auto* arr = type->As()) { + type = arr->ElemType(); + } + return type->As(); + }; + + OperandList operands = {id}; + for (auto* member : str->Members()) { + operands.push_back(Type(member->Type())); + + if (str->StructFlags().Contains(core::type::kExplicitLayout)) { + // Generate struct member offset decoration. + module_.PushAnnot(spv::Op::OpMemberDecorate, + {operands[0], member->Index(), U32Operand(SpvDecorationOffset), + member->Offset()}); + + // Emit matrix layout decorations if necessary. + if (auto* matrix_type = get_nested_matrix_type(member->Type())) { + const uint32_t effective_row_count = (matrix_type->Rows() == 2) ? 2 : 4; + module_.PushAnnot(spv::Op::OpMemberDecorate, + {id, member->Index(), U32Operand(SpvDecorationColMajor)}); + module_.PushAnnot(spv::Op::OpMemberDecorate, + {id, member->Index(), U32Operand(SpvDecorationMatrixStride), + Operand(effective_row_count * matrix_type->Type()->Size())}); + } + } + + PushMemberName(id, member->Index(), member->Name()); + } + module_.PushType(spv::Op::OpTypeStruct, std::move(operands)); + + // Add a Block decoration if necessary. + if (str->StructFlags().Contains(core::type::StructFlag::kBlock)) { + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationBlock)}); + } + + PushName(id, str->Name()); + } + + /// Emit a function. + /// @param func the function to emit + Result EmitFunction(core::ir::Function* func) { + if (func->Params().Length() > 255) { + // Tint transforms may add additional function parameters which can cause a valid input + // shader to exceed SPIR-V's function parameter limit. There isn't much we can do about + // this, so just fail gracefully instead of a generating invalid SPIR-V. + StringStream ss; + ss << "Function '" << ir_.NameOf(func).Name() + << "' has more than 255 parameters after running Tint transforms"; + return Failure{ss.str()}; + } + + auto id = Value(func); + + // Emit the function name. + PushName(id, func); + + // Emit OpEntryPoint and OpExecutionMode declarations if needed. + if (func->IsEntryPoint()) { + EmitEntryPoint(func, id); + } + + // Get the ID for the return type. + auto return_type_id = Type(func->ReturnType()); + + FunctionType function_type{return_type_id, {}}; + InstructionList params; + + // Generate function parameter declarations and add their type IDs to the function + // signature. + for (auto* param : func->Params()) { + auto param_type_id = Type(param->Type()); + auto param_id = Value(param); + params.push_back(Instruction(spv::Op::OpFunctionParameter, {param_type_id, param_id})); + function_type.param_type_ids.Push(param_type_id); + PushName(param_id, param); + } + + // Get the ID for the function type (creating it if needed). + auto function_type_id = function_types_.GetOrAdd(function_type, [&] { + auto func_ty_id = module_.NextId(); + OperandList operands = {func_ty_id, return_type_id}; + operands.insert(operands.end(), function_type.param_type_ids.begin(), + function_type.param_type_ids.end()); + module_.PushType(spv::Op::OpTypeFunction, operands); + return func_ty_id; + }); + + // Declare the function. + auto decl = Instruction{ + spv::Op::OpFunction, + {return_type_id, id, U32Operand(SpvFunctionControlMaskNone), function_type_id}}; + + // Create a function that we will add instructions to. + auto entry_block = module_.NextId(); + current_function_ = Function(decl, entry_block, std::move(params)); + TINT_DEFER(current_function_ = Function()); + + // Emit the body of the function. + auto idx = current_function_.AppendBlock(entry_block); + blocks_to_emit_.push_back({idx, func->Block()}); + + while (!blocks_to_emit_.empty()) { + auto blk = blocks_to_emit_.front(); + blocks_to_emit_.pop_front(); + + EmitBlock(blk); + } + + // Add the function to the module. + module_.PushFunction(current_function_); + + return Success; + } + + /// Emit entry point declarations for a function. + /// @param func the function to emit entry point declarations for + /// @param id the result ID of the function declaration + void EmitEntryPoint(core::ir::Function* func, uint32_t id) { + SpvExecutionModel stage = SpvExecutionModelMax; + switch (func->Stage()) { + case core::ir::Function::PipelineStage::kCompute: { + stage = SpvExecutionModelGLCompute; + + auto const_wg_size = func->WorkgroupSizeAsConst(); + TINT_IR_ASSERT(ir_, const_wg_size); + auto wg_size = *const_wg_size; + + // Store the workgroup information away to return from the generator. + output_.workgroup_info.x = wg_size[0]; + output_.workgroup_info.y = wg_size[1]; + output_.workgroup_info.z = wg_size[2]; + + // Store the subgroup size information away to return from the generator when the + // `@subgroup_size` attribute is used. + const auto const_sg_size = func->SubgroupSizeAsConst(); + if (const_sg_size.has_value()) { + output_.workgroup_info.subgroup_size = const_sg_size; + } + + module_.PushExecutionMode( + spv::Op::OpExecutionMode, + {id, U32Operand(SpvExecutionModeLocalSize), const_wg_size->at(0), + const_wg_size->at(1), const_wg_size->at(2)}); + break; + } + case core::ir::Function::PipelineStage::kFragment: { + stage = SpvExecutionModelFragment; + module_.PushExecutionMode(spv::Op::OpExecutionMode, + {id, U32Operand(SpvExecutionModeOriginUpperLeft)}); + break; + } + case core::ir::Function::PipelineStage::kVertex: { + stage = SpvExecutionModelVertex; + break; + } + case core::ir::Function::PipelineStage::kUndefined: + TINT_IR_ICE(ir_) << "undefined pipeline stage for entry point"; + } + + // Use the remapped entry point name if requested, otherwise use the original name. + std::string name; + if (!options_.remapped_entry_point_name.empty()) { + name = options_.remapped_entry_point_name; + } else { + name = ir_.NameOf(func).Name(); + } + TINT_IR_ASSERT(ir_, !name.empty()); + + OperandList operands = {U32Operand(stage), id, name}; + + // Add the list of all referenced shader IO variables. + for (auto* global : *ir_.root_block) { + auto* var = global->As(); + if (!var) { + continue; + } + + auto* ptr = var->Result()->Type()->As(); + if (options_.spirv_version < SpvVersion::kSpv14) { + // In SPIR-V 1.3 or earlier, OpEntryPoint should list only statically used + // input/output variables. + if (!(ptr->AddressSpace() == core::AddressSpace::kIn || + ptr->AddressSpace() == core::AddressSpace::kOut)) { + continue; + } + + // Determine if this IO variable is used by the entry point. + bool used = false; + for (const auto& use : var->Result()->UsagesUnsorted()) { + auto* block = use->instruction->Block(); + while (block->Parent()) { + block = block->Parent()->Block(); + } + if (block == func->Block()) { + used = true; + break; + } + } + if (!used) { + continue; + } + operands.push_back(Value(var)); + } else { + // In SPIR-V 1.4 or later, OpEntryPoint must list all global variables statically + // used by the entry point. It may be a superset of the used variables though. + operands.push_back(Value(var)); + } + + // Add the necessary SPIR-V execution modes for `frag_depth` usage. + if (var->Attributes().builtin == core::BuiltinValue::kFragDepth) { + // Always add `DepthReplacing` when `frag_depth` is written to. + module_.PushExecutionMode(spv::Op::OpExecutionMode, + {id, U32Operand(SpvExecutionModeDepthReplacing)}); + // Add `DepthGreater` or `DepthLess` if the depth movement direction is constrained. + if (var->Attributes().depth_mode == core::BuiltinDepthMode::kGreater) { + module_.PushExecutionMode(spv::Op::OpExecutionMode, + {id, U32Operand(SpvExecutionModeDepthGreater)}); + } else if (var->Attributes().depth_mode == core::BuiltinDepthMode::kLess) { + module_.PushExecutionMode(spv::Op::OpExecutionMode, + {id, U32Operand(SpvExecutionModeDepthLess)}); + } + } + } + + module_.PushEntryPoint(spv::Op::OpEntryPoint, operands); + } + + /// Emit the root block. + /// @param root_block the root block to emit + void EmitRootBlock(core::ir::Block* root_block) { + for (auto* inst : *root_block) { + Switch( + inst, // + [&](core::ir::Var* v) { EmitGlobalVar(v); }, // + TINT_ICE_ON_NO_MATCH); + } + } + + size_t NewBlock(uint32_t id) { + auto idx = current_function_.AppendBlock(id); + current_function_.SetCurrentBlockIndex(idx); + current_function_.PushInst(spv::Op::OpLabel, {id}); + return idx; + } + + /// Queue a block for emission. If the block contains comments a SPIR-V block will be created + /// and it will be added to the queue to be emitted later. If the block is empty, the + /// necessarily branch/unreachable instructions are added and no further processing is required. + /// @param block the block to emit + void QueueBlock(core::ir::Block* block) { + auto idx = NewBlock(Label(block)); + + if (!block->IsEmpty()) { + blocks_to_emit_.push_back({idx, block}); + return; + } + + // If there are no instructions in the block, it's a dead end, so we shouldn't be able to + // get here to begin with. + if (!block->Parent()->Results().IsEmpty()) { + current_function_.PushInst(spv::Op::OpBranch, {GetMergeLabel(block->Parent())}); + } else { + current_function_.PushInst(spv::Op::OpUnreachable, {}); + } + } + + void EmitBlock(BlockInfo& blk) { + current_function_.SetCurrentBlockIndex(blk.idx); + + // Emit the block's statements. + EmitBlockInstructions(blk.block); + } + + /// Emit all OpPhi nodes for incoming branches to @p block. + /// @param block the block to emit the OpPhis for + void EmitIncomingPhis(core::ir::MultiInBlock* block) { + // Emit Phi nodes for all the incoming block parameters + for (size_t param_idx = 0; param_idx < block->Params().Length(); param_idx++) { + auto* param = block->Params()[param_idx]; + OperandList ops{Type(param->Type()), Value(param)}; + + for (auto* incoming : block->InboundSiblingBranches()) { + auto* arg = incoming->Args()[param_idx]; + ops.push_back(Value(arg)); + ops.push_back(GetTerminatorBlockLabel(incoming)); + } + + current_function_.PushInst(spv::Op::OpPhi, std::move(ops)); + } + } + + /// Emit all instructions of @p block. + /// @param block the block's instructions to emit + void EmitBlockInstructions(core::ir::Block* block) { + TINT_IR_ASSERT(ir_, !block->IsEmpty()); + for (auto* inst : *block) { + Switch( + inst, // + [&](core::ir::Access* a) { EmitAccess(a); }, // + [&](core::ir::Bitcast* b) { EmitBitcast(b); }, // + [&](core::ir::CoreBinary* b) { EmitBinary(b); }, // + [&](spirv::ir::Binary* b) { EmitSpirvBinary(b); }, // + [&](core::ir::CoreBuiltinCall* b) { EmitCoreBuiltinCall(b); }, // + [&](spirv::ir::BuiltinCall* b) { EmitSpirvBuiltinCall(b); }, // + [&](core::ir::Construct* c) { EmitConstruct(c); }, // + [&](core::ir::Convert* c) { EmitConvert(c); }, // + [&](core::ir::Load* l) { EmitLoad(l); }, // + [&](core::ir::LoadVectorElement* l) { EmitLoadVectorElement(l); }, // + [&](core::ir::Loop* l) { EmitLoop(l); }, // + [&](core::ir::Switch* sw) { EmitSwitch(sw); }, // + [&](core::ir::Swizzle* s) { EmitSwizzle(s); }, // + [&](core::ir::Store* s) { EmitStore(s); }, // + [&](core::ir::StoreVectorElement* s) { EmitStoreVectorElement(s); }, // + [&](core::ir::UserCall* c) { EmitUserCall(c); }, // + [&](core::ir::CoreUnary* u) { EmitUnary(u); }, // + [&](core::ir::Var* v) { EmitVar(v); }, // + [&](core::ir::Let* l) { EmitLet(l); }, // + [&](core::ir::If* i) { EmitIf(i); }, // + [&](core::ir::Terminator* t) { EmitTerminator(t); }, // + [&](core::ir::Discard* t) { EmitDiscard(t); }, // + [&](spirv::ir::CopyLogical* c) { EmitCopyLogical(c); }, // + TINT_ICE_ON_NO_MATCH); + + // Set the name for the SPIR-V result ID if provided in the module. + if (inst->Results().Length() == 1u && !inst->Is()) { + PushName(Value(inst), inst); + } + } + } + + void EmitDiscard(core::ir::Discard*) { + if (options_.extensions.use_demote_to_helper_invocation) { + module_.PushExtension("SPV_EXT_demote_to_helper_invocation"); + module_.PushCapability(SpvCapabilityDemoteToHelperInvocationEXT); + current_function_.PushInst(spv::Op::OpDemoteToHelperInvocationEXT, {}); + } else { + // OpKill does not have the same behavioral semantics as demote to helper and will not + // be conformant. OpKill has also been deprecated and the alternative + // OpTerminateInvocation also does not have demote to helper semantics. + TINT_IR_ICE(ir_) << "No substitute function for discard"; + } + } + + /// Emit a terminator instruction. + /// @param t the terminator instruction to emit + void EmitTerminator(core::ir::Terminator* t) { + tint::Switch( // + t, // + [&](core::ir::Return*) { + if (!t->Args().IsEmpty()) { + TINT_IR_ASSERT(ir_, t->Args().Length() == 1u); + OperandList operands; + operands.push_back(Value(t->Args()[0])); + current_function_.PushInst(spv::Op::OpReturnValue, operands); + } else { + current_function_.PushInst(spv::Op::OpReturn, {}); + } + return; + }, + [&](core::ir::BreakIf* breakif) { + auto true_idx = GetMergeLabel(breakif->Loop()); + auto false_idx = GetLoopHeaderLabel(breakif->Loop()); + current_function_.PushInst(spv::Op::OpBranchConditional, + { + Value(breakif->Condition()), + true_idx, + false_idx, + }); + }, + [&](core::ir::Continue* cont) { + current_function_.PushInst(spv::Op::OpBranch, {Label(cont->Loop()->Continuing())}); + }, + [&](core::ir::ExitIf* exit) { + current_function_.PushInst(spv::Op::OpBranch, {GetMergeLabel(exit->If())}); + }, + [&](core::ir::ExitLoop* exit) { + current_function_.PushInst(spv::Op::OpBranch, {GetMergeLabel(exit->Loop())}); + }, + [&](core::ir::ExitSwitch* exit) { + current_function_.PushInst(spv::Op::OpBranch, {GetMergeLabel(exit->Switch())}); + }, + [&](core::ir::NextIteration* ni) { + current_function_.PushInst(spv::Op::OpBranch, {GetLoopHeaderLabel(ni->Loop())}); + }, + [&](core::ir::TerminateInvocation*) { + current_function_.PushInst(spv::Op::OpKill, {}); + }, + [&](core::ir::Unreachable*) { + current_function_.PushInst(spv::Op::OpUnreachable, {}); + }, // + TINT_ICE_ON_NO_MATCH); + } + + /// Emit an `if` flow node. + /// @param i the if node to emit + void EmitIf(core::ir::If* i) { + 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 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 = GetMergeLabel(i); + uint32_t true_label = merge_label; + uint32_t false_label = merge_label; + + if (true_block->Length() > 1 || !i->Results().IsEmpty() || + ((true_block->Terminator() != nullptr) && + !true_block->Terminator()->Is())) { + true_label = Label(true_block); + } + if (false_block->Length() > 1 || !i->Results().IsEmpty() || + ((false_block->Terminator() != nullptr) && + !false_block->Terminator()->Is())) { + false_label = Label(false_block); + } + + // Spirv 1.6 requires that 'OpBranchConditional' have different labels for the true/false + // target blocks. This change has also been seen to resolve bugs in control flow for some + // backend compilers. + if (true_label == false_label) { + true_label = Label(true_block); + } + + // Emit the OpSelectionMerge and OpBranchConditional instructions. + current_function_.PushInst(spv::Op::OpSelectionMerge, + {merge_label, U32Operand(SpvSelectionControlMaskNone)}); + current_function_.PushInst(spv::Op::OpBranchConditional, + {Value(i->Condition()), true_label, false_label}); + + // Emit the `true` and `false` blocks, if they're not being skipped. + if (true_label != merge_label) { + QueueBlock(true_block); + } + if (false_label != merge_label) { + QueueBlock(false_block); + } + + NewBlock(merge_label); + + // Emit the OpPhis for the ExitIfs + EmitExitPhis(i); + } + + uint32_t GetAccessChainIndexId(core::ir::Value* idx) { + if (idx->Type()->Is()) { + return Value(idx); + } + + // If the index isn't a unsigned value, then convert it to unsigned. A negative + // value is never allowed as a constant access index in SPIR-V. This conversion fixes that + // potential issue. + + // If the index was a constant, keep it as a constant as is required for struct members. + if (auto* c = idx->As()) { + return Constant(ir_.constant_values.Get(c->Value()->ValueAs())); + } + + // Use a bitcast for runtime values. + uint32_t spv_id = module_.NextId(); + current_function_.PushInst(spv::Op::OpBitcast, + {Type(ir_.Types().u32()), spv_id, Value(idx)}); + return spv_id; + } + + /// Emit an access instruction + /// @param access the access instruction to emit + void EmitAccess(core::ir::Access* access) { + auto* ty = access->Result()->Type(); + + auto id = Value(access); + OperandList operands = {Type(ty), id, Value(access->Object())}; + + if (ty->Is()) { + // Use OpAccessChain for accesses into pointer types. + for (auto* idx : access->Indices()) { + operands.push_back(GetAccessChainIndexId(idx)); + } + current_function_.PushInst(spv::Op::OpAccessChain, std::move(operands)); + return; + } + + // For non-pointer types, we assume that the indices are constants and use + // OpCompositeExtract. If we hit a non-constant index into a vector type, use + // OpVectorExtractDynamic for it. + auto* source_ty = access->Object()->Type(); + for (auto* idx : access->Indices()) { + if (auto* constant = idx->As()) { + // Push the index to the chain and update the current type. + auto i = constant->Value()->ValueAs(); + operands.push_back(i); + source_ty = source_ty->Element(i); + } else { + // The VarForDynamicIndex transform ensures that only value types that are vectors + // will be dynamically indexed, as we can use OpVectorExtractDynamic for this case. + TINT_IR_ASSERT(ir_, source_ty->Is()); + + // If this wasn't the first access in the chain then emit the chain so far as an + // OpCompositeExtract, creating a new result ID for the resulting vector. + auto vec_id = Value(access->Object()); + if (operands.size() > 3) { + vec_id = module_.NextId(); + operands[0] = Type(source_ty); + operands[1] = vec_id; + current_function_.PushInst(spv::Op::OpCompositeExtract, std::move(operands)); + } + + // Now emit the OpVectorExtractDynamic instruction. + operands = {Type(ty), id, vec_id, Value(idx)}; + current_function_.PushInst(spv::Op::OpVectorExtractDynamic, std::move(operands)); + return; + } + } + current_function_.PushInst(spv::Op::OpCompositeExtract, std::move(operands)); + } + + /// Emit a binary instruction. + /// @param binary the binary instruction to emit + void EmitBinary(core::ir::CoreBinary* binary) { + auto id = Value(binary); + auto lhs = Value(binary->LHS()); + auto rhs = Value(binary->RHS()); + auto* ty = binary->Result()->Type(); + auto* lhs_ty = binary->LHS()->Type(); + + // Determine the opcode. + spv::Op op = spv::Op::Max; + switch (binary->Op()) { + case core::BinaryOp::kAdd: { + op = ty->IsIntegerScalarOrVector() ? spv::Op::OpIAdd : spv::Op::OpFAdd; + break; + } + case core::BinaryOp::kDivide: { + if (ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSDiv; + } else if (ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpUDiv; + } else if (ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFDiv; + } + break; + } + case core::BinaryOp::kMultiply: { + if (ty->IsIntegerScalarOrVector()) { + op = spv::Op::OpIMul; + } else if (ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFMul; + } + break; + } + case core::BinaryOp::kSubtract: { + op = ty->IsIntegerScalarOrVector() ? spv::Op::OpISub : spv::Op::OpFSub; + break; + } + case core::BinaryOp::kModulo: { + if (ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSRem; + } else if (ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpUMod; + } else if (ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFRem; + } + break; + } + + case core::BinaryOp::kAnd: { + if (ty->IsIntegerScalarOrVector()) { + op = spv::Op::OpBitwiseAnd; + } else if (ty->IsBoolScalarOrVector()) { + op = spv::Op::OpLogicalAnd; + } + break; + } + case core::BinaryOp::kOr: { + if (ty->IsIntegerScalarOrVector()) { + op = spv::Op::OpBitwiseOr; + } else if (ty->IsBoolScalarOrVector()) { + op = spv::Op::OpLogicalOr; + } + break; + } + case core::BinaryOp::kXor: { + op = spv::Op::OpBitwiseXor; + break; + } + + case core::BinaryOp::kShiftLeft: { + op = spv::Op::OpShiftLeftLogical; + break; + } + case core::BinaryOp::kShiftRight: { + if (ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpShiftRightArithmetic; + } else if (ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpShiftRightLogical; + } + break; + } + + case core::BinaryOp::kEqual: { + if (lhs_ty->IsBoolScalarOrVector()) { + op = spv::Op::OpLogicalEqual; + } else if (lhs_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFOrdEqual; + } else if (lhs_ty->IsIntegerScalarOrVector()) { + op = spv::Op::OpIEqual; + } + break; + } + case core::BinaryOp::kNotEqual: { + if (lhs_ty->IsBoolScalarOrVector()) { + op = spv::Op::OpLogicalNotEqual; + } else if (lhs_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFOrdNotEqual; + } else if (lhs_ty->IsIntegerScalarOrVector()) { + op = spv::Op::OpINotEqual; + } + break; + } + case core::BinaryOp::kGreaterThan: { + if (lhs_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFOrdGreaterThan; + } else if (lhs_ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSGreaterThan; + } else if (lhs_ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpUGreaterThan; + } + break; + } + case core::BinaryOp::kGreaterThanEqual: { + if (lhs_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFOrdGreaterThanEqual; + } else if (lhs_ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSGreaterThanEqual; + } else if (lhs_ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpUGreaterThanEqual; + } + break; + } + case core::BinaryOp::kLessThan: { + if (lhs_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFOrdLessThan; + } else if (lhs_ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSLessThan; + } else if (lhs_ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpULessThan; + } + break; + } + case core::BinaryOp::kLessThanEqual: { + if (lhs_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFOrdLessThanEqual; + } else if (lhs_ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSLessThanEqual; + } else if (lhs_ty->IsUnsignedIntegerScalarOrVector()) { + op = spv::Op::OpULessThanEqual; + } + break; + } + default: { + TINT_IR_UNIMPLEMENTED(ir_) + << "\"" << binary->Op() << "\" (enum value=" << static_cast(binary->Op()) + << ")"; + } + } + + // Emit the instruction. + current_function_.PushInst(op, {Type(ty), id, lhs, rhs}); + } + + /// Emit a binary instruction. + /// @param binary the binary instruction to emit + void EmitSpirvBinary(spirv::ir::Binary* binary) { + auto id = Value(binary); + auto lhs = Value(binary->LHS()); + auto rhs = Value(binary->RHS()); + auto* ty = binary->Result()->Type(); + + // Determine the opcode. + spv::Op op = spv::Op::Max; + switch (binary->Op()) { + case core::BinaryOp::kAdd: { + op = ty->DeepestElement()->IsIntegerScalarOrVector() ? spv::Op::OpIAdd + : spv::Op::OpFAdd; + break; + } + case core::BinaryOp::kSubtract: { + op = ty->DeepestElement()->IsIntegerScalarOrVector() ? spv::Op::OpISub + : spv::Op::OpFSub; + break; + } + case core::BinaryOp::kMultiply: { + op = ty->DeepestElement()->IsIntegerScalarOrVector() ? spv::Op::OpIMul + : spv::Op::OpFMul; + break; + } + default: { + TINT_IR_UNIMPLEMENTED(ir_) + << "\"" << binary->Op() << "\" (enum value=" << static_cast(binary->Op()) + << ")"; + } + } + + // Emit the instruction. + current_function_.PushInst(op, {Type(ty), id, lhs, rhs}); + } + + /// Emit a bitcast instruction. + /// @param bitcast the bitcast instruction to emit + void EmitBitcast(core::ir::Bitcast* bitcast) { + auto* ty = bitcast->Result()->Type(); + if (ty == bitcast->Val()->Type()) { + values_.Add(bitcast->Result(), Value(bitcast->Val())); + return; + } + current_function_.PushInst(spv::Op::OpBitcast, + {Type(ty), Value(bitcast), Value(bitcast->Val())}); + } + + /// Emit a builtin function call instruction. + /// @param builtin the builtin call instruction to emit + void EmitSpirvBuiltinCall(spirv::ir::BuiltinCall* builtin) { + auto id = Value(builtin); + + OperandList operands; + if (!builtin->Result()->Type()->Is()) { + operands = {Type(builtin->Result()->Type()), id}; + } + + spv::Op op = spv::Op::Max; + + auto ext_inst = [&](enum GLSLstd450 inst) { + op = spv::Op::OpExtInst; + operands.push_back(ImportGlslStd450()); + operands.push_back(U32Operand(inst)); + }; + + switch (builtin->Func()) { + case spirv::BuiltinFn::kAbs: + ext_inst(GLSLstd450SAbs); + break; + case spirv::BuiltinFn::kArrayLength: + op = spv::Op::OpArrayLength; + break; + case spirv::BuiltinFn::kAtomicIAdd: + op = spv::Op::OpAtomicIAdd; + break; + case spirv::BuiltinFn::kAtomicISub: + op = spv::Op::OpAtomicISub; + break; + case spirv::BuiltinFn::kAtomicAnd: + op = spv::Op::OpAtomicAnd; + break; + case spirv::BuiltinFn::kAtomicCompareExchange: + op = spv::Op::OpAtomicCompareExchange; + break; + case spirv::BuiltinFn::kAtomicExchange: + op = spv::Op::OpAtomicExchange; + break; + case spirv::BuiltinFn::kAtomicLoad: + op = spv::Op::OpAtomicLoad; + break; + case spirv::BuiltinFn::kAtomicOr: + op = spv::Op::OpAtomicOr; + break; + case spirv::BuiltinFn::kAtomicSMax: + op = spv::Op::OpAtomicSMax; + break; + case spirv::BuiltinFn::kAtomicSMin: + op = spv::Op::OpAtomicSMin; + break; + case spirv::BuiltinFn::kAtomicStore: + op = spv::Op::OpAtomicStore; + break; + case spirv::BuiltinFn::kAtomicUMax: + op = spv::Op::OpAtomicUMax; + break; + case spirv::BuiltinFn::kAtomicUMin: + op = spv::Op::OpAtomicUMin; + break; + case spirv::BuiltinFn::kAtomicXor: + op = spv::Op::OpAtomicXor; + break; + case BuiltinFn::kAtomicIIncrement: + op = spv::Op::OpAtomicIIncrement; + break; + case BuiltinFn::kAtomicIDecrement: + op = spv::Op::OpAtomicIDecrement; + break; + case spirv::BuiltinFn::kDot: + op = spv::Op::OpDot; + break; + case spirv::BuiltinFn::kImageDrefGather: + op = spv::Op::OpImageDrefGather; + break; + case spirv::BuiltinFn::kImageFetch: + op = spv::Op::OpImageFetch; + break; + case spirv::BuiltinFn::kImageGather: + op = spv::Op::OpImageGather; + break; + case spirv::BuiltinFn::kImageQuerySize: + module_.PushCapability(SpvCapabilityImageQuery); + op = spv::Op::OpImageQuerySize; + break; + case spirv::BuiltinFn::kImageQuerySizeLod: + module_.PushCapability(SpvCapabilityImageQuery); + op = spv::Op::OpImageQuerySizeLod; + break; + case spirv::BuiltinFn::kImageQueryLevels: + module_.PushCapability(SpvCapabilityImageQuery); + op = spv::Op::OpImageQueryLevels; + break; + case spirv::BuiltinFn::kImageQuerySamples: + module_.PushCapability(SpvCapabilityImageQuery); + op = spv::Op::OpImageQuerySamples; + break; + case spirv::BuiltinFn::kImageRead: + op = spv::Op::OpImageRead; + break; + case spirv::BuiltinFn::kImageSampleImplicitLod: + op = spv::Op::OpImageSampleImplicitLod; + break; + case spirv::BuiltinFn::kImageSampleExplicitLod: + op = spv::Op::OpImageSampleExplicitLod; + break; + case spirv::BuiltinFn::kImageSampleProjImplicitLod: + op = spv::Op::OpImageSampleProjImplicitLod; + break; + case spirv::BuiltinFn::kImageSampleProjExplicitLod: + op = spv::Op::OpImageSampleProjExplicitLod; + break; + case spirv::BuiltinFn::kImageSampleDrefImplicitLod: + op = spv::Op::OpImageSampleDrefImplicitLod; + break; + case spirv::BuiltinFn::kImageSampleDrefExplicitLod: + op = spv::Op::OpImageSampleDrefExplicitLod; + break; + case spirv::BuiltinFn::kImageSampleProjDrefImplicitLod: + op = spv::Op::OpImageSampleProjDrefImplicitLod; + break; + case spirv::BuiltinFn::kImageSampleProjDrefExplicitLod: + op = spv::Op::OpImageSampleProjDrefExplicitLod; + break; + case spirv::BuiltinFn::kImageWrite: + op = spv::Op::OpImageWrite; + break; + case spirv::BuiltinFn::kMatrixTimesMatrix: + op = spv::Op::OpMatrixTimesMatrix; + break; + case spirv::BuiltinFn::kMatrixTimesScalar: + op = spv::Op::OpMatrixTimesScalar; + break; + case spirv::BuiltinFn::kMatrixTimesVector: + op = spv::Op::OpMatrixTimesVector; + break; + case spirv::BuiltinFn::kModf: + ext_inst(GLSLstd450Modf); + break; + case spirv::BuiltinFn::kFrexp: + ext_inst(GLSLstd450Frexp); + break; + case spirv::BuiltinFn::kSMax: + ext_inst(GLSLstd450SMax); + break; + case spirv::BuiltinFn::kSMin: + ext_inst(GLSLstd450SMin); + break; + case spirv::BuiltinFn::kSClamp: + ext_inst(GLSLstd450SClamp); + break; + case spirv::BuiltinFn::kUMax: + ext_inst(GLSLstd450UMax); + break; + case spirv::BuiltinFn::kUMin: + ext_inst(GLSLstd450UMin); + break; + case spirv::BuiltinFn::kUClamp: + ext_inst(GLSLstd450UClamp); + break; + case spirv::BuiltinFn::kNormalize: + ext_inst(GLSLstd450Normalize); + break; + case spirv::BuiltinFn::kOpImage: + op = spv::Op::OpImage; + break; + case spirv::BuiltinFn::kOpSampledImage: + op = spv::Op::OpSampledImage; + break; + case spirv::BuiltinFn::kSDot: + module_.PushExtension("SPV_KHR_integer_dot_product"); + module_.PushCapability(SpvCapabilityDotProductKHR); + module_.PushCapability(SpvCapabilityDotProductInput4x8BitPackedKHR); + op = spv::Op::OpSDot; + break; + case spirv::BuiltinFn::kSelect: + op = spv::Op::OpSelect; + break; + case spirv::BuiltinFn::kSign: + ext_inst(GLSLstd450SSign); + break; + case spirv::BuiltinFn::kInverse: + ext_inst(GLSLstd450MatrixInverse); + break; + case spirv::BuiltinFn::kFindILsb: + ext_inst(GLSLstd450FindILsb); + break; + case spirv::BuiltinFn::kFindSMsb: + ext_inst(GLSLstd450FindSMsb); + break; + case spirv::BuiltinFn::kFindUMsb: + ext_inst(GLSLstd450FindUMsb); + break; + case spirv::BuiltinFn::kRefract: + ext_inst(GLSLstd450Refract); + break; + case spirv::BuiltinFn::kReflect: + ext_inst(GLSLstd450Reflect); + break; + case spirv::BuiltinFn::kFaceForward: + ext_inst(GLSLstd450FaceForward); + break; + case spirv::BuiltinFn::kLdexp: + ext_inst(GLSLstd450Ldexp); + break; + case spirv::BuiltinFn::kUDot: + module_.PushExtension("SPV_KHR_integer_dot_product"); + module_.PushCapability(SpvCapabilityDotProductKHR); + module_.PushCapability(SpvCapabilityDotProductInput4x8BitPackedKHR); + op = spv::Op::OpUDot; + break; + case spirv::BuiltinFn::kVectorTimesMatrix: + op = spv::Op::OpVectorTimesMatrix; + break; + case spirv::BuiltinFn::kVectorTimesScalar: + op = spv::Op::OpVectorTimesScalar; + break; + case spirv::BuiltinFn::kCooperativeMatrixLoad: + op = spv::Op::OpCooperativeMatrixLoadKHR; + break; + case spirv::BuiltinFn::kCooperativeMatrixMulAdd: + op = spv::Op::OpCooperativeMatrixMulAddKHR; + break; + case spirv::BuiltinFn::kCooperativeMatrixStore: + op = spv::Op::OpCooperativeMatrixStoreKHR; + break; + case spirv::BuiltinFn::kBitCount: + op = spv::Op::OpBitCount; + break; + case spirv::BuiltinFn::kBitFieldInsert: + op = spv::Op::OpBitFieldInsert; + break; + case spirv::BuiltinFn::kBitFieldSExtract: + op = spv::Op::OpBitFieldSExtract; + break; + case spirv::BuiltinFn::kBitFieldUExtract: + op = spv::Op::OpBitFieldUExtract; + break; + case BuiltinFn::kAdd: + op = spv::Op::OpIAdd; + break; + case BuiltinFn::kSub: + op = spv::Op::OpISub; + break; + case BuiltinFn::kMul: + op = spv::Op::OpIMul; + break; + case BuiltinFn::kSDiv: + op = spv::Op::OpSDiv; + break; + case BuiltinFn::kSMod: + op = spv::Op::OpSMod; + break; + case BuiltinFn::kConvertFToS: + op = spv::Op::OpConvertFToS; + break; + case BuiltinFn::kConvertSToF: + op = spv::Op::OpConvertSToF; + break; + case BuiltinFn::kConvertUToF: + op = spv::Op::OpConvertUToF; + break; + case BuiltinFn::kBitwiseAnd: + op = spv::Op::OpBitwiseAnd; + break; + case BuiltinFn::kBitwiseOr: + op = spv::Op::OpBitwiseOr; + break; + case BuiltinFn::kBitwiseXor: + op = spv::Op::OpBitwiseXor; + break; + case BuiltinFn::kEqual: + op = spv::Op::OpIEqual; + break; + case BuiltinFn::kNotEqual: + op = spv::Op::OpINotEqual; + break; + case BuiltinFn::kSGreaterThan: + op = spv::Op::OpSGreaterThan; + break; + case BuiltinFn::kSGreaterThanEqual: + op = spv::Op::OpSGreaterThanEqual; + break; + case BuiltinFn::kSLessThan: + op = spv::Op::OpSLessThan; + break; + case BuiltinFn::kSLessThanEqual: + op = spv::Op::OpSLessThanEqual; + break; + case BuiltinFn::kUGreaterThan: + op = spv::Op::OpUGreaterThan; + break; + case BuiltinFn::kUGreaterThanEqual: + op = spv::Op::OpUGreaterThanEqual; + break; + case BuiltinFn::kULessThan: + op = spv::Op::OpULessThan; + break; + case BuiltinFn::kULessThanEqual: + op = spv::Op::OpULessThanEqual; + break; + case BuiltinFn::kShiftLeftLogical: + op = spv::Op::OpShiftLeftLogical; + break; + case BuiltinFn::kShiftRightLogical: + op = spv::Op::OpShiftRightLogical; + break; + case BuiltinFn::kShiftRightArithmetic: + op = spv::Op::OpShiftRightArithmetic; + break; + case BuiltinFn::kNot: + op = spv::Op::OpNot; + break; + case BuiltinFn::kSNegate: + op = spv::Op::OpSNegate; + break; + case BuiltinFn::kFMod: + op = spv::Op::OpFMod; + break; + case BuiltinFn::kOuterProduct: + op = spv::Op::OpOuterProduct; + break; + case BuiltinFn::kGroupNonUniformBroadcast: + op = spv::Op::OpGroupNonUniformBroadcast; + break; + case BuiltinFn::kGroupNonUniformBroadcastFirst: + op = spv::Op::OpGroupNonUniformBroadcastFirst; + break; + case BuiltinFn::kGroupNonUniformQuadBroadcast: + op = spv::Op::OpGroupNonUniformQuadBroadcast; + break; + case BuiltinFn::kGroupNonUniformQuadSwap: + op = spv::Op::OpGroupNonUniformQuadSwap; + break; + case BuiltinFn::kGroupNonUniformShuffle: + op = spv::Op::OpGroupNonUniformShuffle; + break; + case BuiltinFn::kGroupNonUniformShuffleXor: + op = spv::Op::OpGroupNonUniformShuffleXor; + break; + case BuiltinFn::kGroupNonUniformShuffleDown: + op = spv::Op::OpGroupNonUniformShuffleDown; + break; + case BuiltinFn::kGroupNonUniformShuffleUp: + op = spv::Op::OpGroupNonUniformShuffleUp; + break; + case BuiltinFn::kGroupNonUniformSMin: + op = spv::Op::OpGroupNonUniformSMin; + break; + case BuiltinFn::kGroupNonUniformSMax: + op = spv::Op::OpGroupNonUniformSMax; + break; + case BuiltinFn::kUConvert: + op = spv::Op::OpUConvert; + break; + case BuiltinFn::kSConvert: + op = spv::Op::OpSConvert; + break; + case spirv::BuiltinFn::kNone: + TINT_IR_ICE(ir_) << "undefined spirv ir function"; + } + + for (auto* arg : builtin->Args()) { + operands.push_back(Value(arg)); + } + current_function_.PushInst(op, operands); + } + + /// Emit an OpCopyLogical instruction. + /// @param copy The logical copy instruction to emit + void EmitCopyLogical(spirv::ir::CopyLogical* copy) { + auto id = Value(copy); + + OperandList operands = {Type(copy->Result()->Type()), id}; + operands.push_back(Value(copy->Arg())); + current_function_.PushInst(spv::Op::OpCopyLogical, operands); + } + + uint32_t ImportGlslStd450() { + return imports_.GetOrAdd(kGLSLstd450, [&] { + // Import the instruction set the first time it is requested. + auto import = module_.NextId(); + module_.PushExtImport(spv::Op::OpExtInstImport, {import, Operand(kGLSLstd450)}); + return import; + }); + } + + /// Emit a builtin function call instruction. + /// @param builtin the builtin call instruction to emit + void EmitCoreBuiltinCall(core::ir::CoreBuiltinCall* builtin) { + auto* result_ty = builtin->Result()->Type(); + + if (builtin->Func() == core::BuiltinFn::kAbs && + result_ty->IsUnsignedIntegerScalarOrVector()) { + // abs() is a no-op for unsigned integers. + values_.Add(builtin->Result(), Value(builtin->Args()[0])); + return; + } + if ((builtin->Func() == core::BuiltinFn::kAll || + builtin->Func() == core::BuiltinFn::kAny) && + builtin->Args()[0]->Type()->Is()) { + // all() and any() are passthroughs for scalar arguments. + values_.Add(builtin->Result(), Value(builtin->Args()[0])); + return; + } + + auto id = Value(builtin); + + spv::Op op = spv::Op::Max; + OperandList operands = {Type(result_ty), id}; + + // Helper to set up the opcode and operand list for a GLSL extended instruction. + auto glsl_ext_inst = [&](enum GLSLstd450 inst) { + op = spv::Op::OpExtInst; + operands.push_back(ImportGlslStd450()); + operands.push_back(U32Operand(inst)); + }; + + // TODO(crbug.com/359883869): Clean up this emission logic so this flag isn't necessary. + bool args_emitted = false; + + // Determine the opcode. + switch (builtin->Func()) { + case core::BuiltinFn::kAbs: + if (result_ty->IsFloatScalarOrVector()) { + glsl_ext_inst(GLSLstd450FAbs); + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450SAbs); + } + break; + case core::BuiltinFn::kAll: + op = spv::Op::OpAll; + break; + case core::BuiltinFn::kAny: + op = spv::Op::OpAny; + break; + case core::BuiltinFn::kAcos: + glsl_ext_inst(GLSLstd450Acos); + break; + case core::BuiltinFn::kAcosh: + glsl_ext_inst(GLSLstd450Acosh); + break; + case core::BuiltinFn::kAsin: + glsl_ext_inst(GLSLstd450Asin); + break; + case core::BuiltinFn::kAsinh: + glsl_ext_inst(GLSLstd450Asinh); + break; + case core::BuiltinFn::kAtan: + glsl_ext_inst(GLSLstd450Atan); + break; + case core::BuiltinFn::kAtan2: + glsl_ext_inst(GLSLstd450Atan2); + break; + case core::BuiltinFn::kAtanh: + glsl_ext_inst(GLSLstd450Atanh); + break; + case core::BuiltinFn::kClamp: + if (result_ty->IsFloatScalarOrVector()) { + glsl_ext_inst(GLSLstd450NClamp); + } else if (result_ty->IsUnsignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450UClamp); + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450SClamp); + } + break; + case core::BuiltinFn::kCeil: + glsl_ext_inst(GLSLstd450Ceil); + break; + case core::BuiltinFn::kCos: + glsl_ext_inst(GLSLstd450Cos); + break; + case core::BuiltinFn::kCosh: + glsl_ext_inst(GLSLstd450Cosh); + break; + case core::BuiltinFn::kCountOneBits: + op = spv::Op::OpBitCount; + break; + case core::BuiltinFn::kCross: + glsl_ext_inst(GLSLstd450Cross); + break; + case core::BuiltinFn::kDegrees: + glsl_ext_inst(GLSLstd450Degrees); + break; + case core::BuiltinFn::kDeterminant: + glsl_ext_inst(GLSLstd450Determinant); + break; + case core::BuiltinFn::kDistance: + glsl_ext_inst(GLSLstd450Distance); + break; + case core::BuiltinFn::kDpdx: + op = spv::Op::OpDPdx; + break; + case core::BuiltinFn::kDpdxCoarse: + module_.PushCapability(SpvCapabilityDerivativeControl); + op = spv::Op::OpDPdxCoarse; + break; + case core::BuiltinFn::kDpdxFine: + module_.PushCapability(SpvCapabilityDerivativeControl); + op = spv::Op::OpDPdxFine; + break; + case core::BuiltinFn::kDpdy: + op = spv::Op::OpDPdy; + break; + case core::BuiltinFn::kDpdyCoarse: + module_.PushCapability(SpvCapabilityDerivativeControl); + op = spv::Op::OpDPdyCoarse; + break; + case core::BuiltinFn::kDpdyFine: + module_.PushCapability(SpvCapabilityDerivativeControl); + op = spv::Op::OpDPdyFine; + break; + case core::BuiltinFn::kExp: + glsl_ext_inst(GLSLstd450Exp); + break; + case core::BuiltinFn::kExp2: + glsl_ext_inst(GLSLstd450Exp2); + break; + case core::BuiltinFn::kExtractBits: + op = result_ty->IsSignedIntegerScalarOrVector() ? spv::Op::OpBitFieldSExtract + : spv::Op::OpBitFieldUExtract; + break; + case core::BuiltinFn::kFaceForward: + glsl_ext_inst(GLSLstd450FaceForward); + break; + case core::BuiltinFn::kFloor: + glsl_ext_inst(GLSLstd450Floor); + break; + case core::BuiltinFn::kFma: + glsl_ext_inst(GLSLstd450Fma); + break; + case core::BuiltinFn::kFract: + glsl_ext_inst(GLSLstd450Fract); + break; + case core::BuiltinFn::kFrexp: + glsl_ext_inst(GLSLstd450FrexpStruct); + break; + case core::BuiltinFn::kFwidth: + op = spv::Op::OpFwidth; + break; + case core::BuiltinFn::kFwidthCoarse: + module_.PushCapability(SpvCapabilityDerivativeControl); + op = spv::Op::OpFwidthCoarse; + break; + case core::BuiltinFn::kFwidthFine: + module_.PushCapability(SpvCapabilityDerivativeControl); + op = spv::Op::OpFwidthFine; + break; + case core::BuiltinFn::kInsertBits: + op = spv::Op::OpBitFieldInsert; + break; + case core::BuiltinFn::kInverseSqrt: + glsl_ext_inst(GLSLstd450InverseSqrt); + break; + case core::BuiltinFn::kLdexp: + glsl_ext_inst(GLSLstd450Ldexp); + break; + case core::BuiltinFn::kLength: + glsl_ext_inst(GLSLstd450Length); + break; + case core::BuiltinFn::kLog: + glsl_ext_inst(GLSLstd450Log); + break; + case core::BuiltinFn::kLog2: + glsl_ext_inst(GLSLstd450Log2); + break; + case core::BuiltinFn::kMax: + if (result_ty->IsFloatScalarOrVector()) { + glsl_ext_inst(GLSLstd450NMax); + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450SMax); + } else if (result_ty->IsUnsignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450UMax); + } + break; + case core::BuiltinFn::kMin: + if (result_ty->IsFloatScalarOrVector()) { + glsl_ext_inst(GLSLstd450NMin); + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450SMin); + } else if (result_ty->IsUnsignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450UMin); + } + break; + case core::BuiltinFn::kMix: + glsl_ext_inst(GLSLstd450FMix); + break; + case core::BuiltinFn::kModf: + glsl_ext_inst(GLSLstd450ModfStruct); + break; + case core::BuiltinFn::kNormalize: + glsl_ext_inst(GLSLstd450Normalize); + break; + case core::BuiltinFn::kPack2X16Float: + glsl_ext_inst(GLSLstd450PackHalf2x16); + break; + case core::BuiltinFn::kPack2X16Snorm: + glsl_ext_inst(GLSLstd450PackSnorm2x16); + break; + case core::BuiltinFn::kPack2X16Unorm: + glsl_ext_inst(GLSLstd450PackUnorm2x16); + break; + case core::BuiltinFn::kPack4X8Snorm: + glsl_ext_inst(GLSLstd450PackSnorm4x8); + break; + case core::BuiltinFn::kPack4X8Unorm: + glsl_ext_inst(GLSLstd450PackUnorm4x8); + break; + case core::BuiltinFn::kPow: + glsl_ext_inst(GLSLstd450Pow); + break; + case core::BuiltinFn::kQuadBroadcast: + module_.PushCapability(SpvCapabilityGroupNonUniformQuad); + op = spv::Op::OpGroupNonUniformQuadBroadcast; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kQuadSwapX: + module_.PushCapability(SpvCapabilityGroupNonUniformQuad); + op = spv::Op::OpGroupNonUniformQuadSwap; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(Value(builtin->Args()[0])); + operands.push_back(Constant(ir_.constant_values.Get(0_u))); // Direction + args_emitted = true; + break; + case core::BuiltinFn::kQuadSwapY: + module_.PushCapability(SpvCapabilityGroupNonUniformQuad); + op = spv::Op::OpGroupNonUniformQuadSwap; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(Value(builtin->Args()[0])); + operands.push_back(Constant(ir_.constant_values.Get(1_u))); // Direction + args_emitted = true; + break; + case core::BuiltinFn::kQuadSwapDiagonal: + module_.PushCapability(SpvCapabilityGroupNonUniformQuad); + op = spv::Op::OpGroupNonUniformQuadSwap; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(Value(builtin->Args()[0])); + operands.push_back(Constant(ir_.constant_values.Get(2_u))); // Direction + args_emitted = true; + break; + case core::BuiltinFn::kQuantizeToF16: + op = spv::Op::OpQuantizeToF16; + break; + case core::BuiltinFn::kRadians: + glsl_ext_inst(GLSLstd450Radians); + break; + case core::BuiltinFn::kReflect: + glsl_ext_inst(GLSLstd450Reflect); + break; + case core::BuiltinFn::kRefract: + glsl_ext_inst(GLSLstd450Refract); + break; + case core::BuiltinFn::kReverseBits: + op = spv::Op::OpBitReverse; + break; + case core::BuiltinFn::kRound: + glsl_ext_inst(GLSLstd450RoundEven); + break; + case core::BuiltinFn::kSign: + if (result_ty->IsFloatScalarOrVector()) { + glsl_ext_inst(GLSLstd450FSign); + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + glsl_ext_inst(GLSLstd450SSign); + } + break; + case core::BuiltinFn::kSin: + glsl_ext_inst(GLSLstd450Sin); + break; + case core::BuiltinFn::kSinh: + glsl_ext_inst(GLSLstd450Sinh); + break; + case core::BuiltinFn::kSmoothstep: + glsl_ext_inst(GLSLstd450SmoothStep); + break; + case core::BuiltinFn::kSqrt: + glsl_ext_inst(GLSLstd450Sqrt); + break; + case core::BuiltinFn::kStep: + glsl_ext_inst(GLSLstd450Step); + break; + case core::BuiltinFn::kStorageBarrier: { + spv::MemorySemanticsMask memory_mask = spv::MemorySemanticsMask::UniformMemory | + spv::MemorySemanticsMask::AcquireRelease; + if (options_.extensions.use_vulkan_memory_model) { + memory_mask = memory_mask | spv::MemorySemanticsMask::MakeAvailable | + spv::MemorySemanticsMask::MakeVisible; + } + + op = spv::Op::OpControlBarrier; + operands.clear(); + operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup)))); + operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup)))); + operands.push_back(Constant(b_.ConstantValue(u32(memory_mask)))); + break; + } + case core::BuiltinFn::kSubgroupAdd: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = result_ty->IsIntegerScalarOrVector() ? spv::Op::OpGroupNonUniformIAdd + : spv::Op::OpGroupNonUniformFAdd; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupInclusiveAdd: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = result_ty->IsIntegerScalarOrVector() ? spv::Op::OpGroupNonUniformIAdd + : spv::Op::OpGroupNonUniformFAdd; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::InclusiveScan))); + break; + case core::BuiltinFn::kSubgroupExclusiveAdd: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = result_ty->IsIntegerScalarOrVector() ? spv::Op::OpGroupNonUniformIAdd + : spv::Op::OpGroupNonUniformFAdd; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::ExclusiveScan))); + break; + case core::BuiltinFn::kSubgroupMul: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = result_ty->IsIntegerScalarOrVector() ? spv::Op::OpGroupNonUniformIMul + : spv::Op::OpGroupNonUniformFMul; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupInclusiveMul: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = result_ty->IsIntegerScalarOrVector() ? spv::Op::OpGroupNonUniformIMul + : spv::Op::OpGroupNonUniformFMul; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::InclusiveScan))); + break; + case core::BuiltinFn::kSubgroupExclusiveMul: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = result_ty->IsIntegerScalarOrVector() ? spv::Op::OpGroupNonUniformIMul + : spv::Op::OpGroupNonUniformFMul; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::ExclusiveScan))); + break; + case core::BuiltinFn::kSubgroupBallot: + module_.PushCapability(SpvCapabilityGroupNonUniformBallot); + op = spv::Op::OpGroupNonUniformBallot; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupElect: + module_.PushCapability(SpvCapabilityGroupNonUniform); + op = spv::Op::OpGroupNonUniformElect; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupBroadcast: + module_.PushCapability(SpvCapabilityGroupNonUniformBallot); + op = spv::Op::OpGroupNonUniformBroadcast; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupBroadcastFirst: + module_.PushCapability(SpvCapabilityGroupNonUniformBallot); + op = spv::Op::OpGroupNonUniformBroadcastFirst; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupShuffle: + module_.PushCapability(SpvCapabilityGroupNonUniformShuffle); + op = spv::Op::OpGroupNonUniformShuffle; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupShuffleXor: + module_.PushCapability(SpvCapabilityGroupNonUniformShuffle); + op = spv::Op::OpGroupNonUniformShuffleXor; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupShuffleUp: + module_.PushCapability(SpvCapabilityGroupNonUniformShuffleRelative); + op = spv::Op::OpGroupNonUniformShuffleUp; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupShuffleDown: + module_.PushCapability(SpvCapabilityGroupNonUniformShuffleRelative); + op = spv::Op::OpGroupNonUniformShuffleDown; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupAnd: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = spv::Op::OpGroupNonUniformBitwiseAnd; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupOr: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = spv::Op::OpGroupNonUniformBitwiseOr; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupXor: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + op = spv::Op::OpGroupNonUniformBitwiseXor; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupMin: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + if (result_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpGroupNonUniformFMin; + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpGroupNonUniformSMin; + } else { + TINT_IR_ASSERT(ir_, result_ty->IsUnsignedIntegerScalarOrVector()); + op = spv::Op::OpGroupNonUniformUMin; + } + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupMax: + module_.PushCapability(SpvCapabilityGroupNonUniformArithmetic); + if (result_ty->IsFloatScalarOrVector()) { + op = spv::Op::OpGroupNonUniformFMax; + } else if (result_ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpGroupNonUniformSMax; + } else { + TINT_IR_ASSERT(ir_, result_ty->IsUnsignedIntegerScalarOrVector()); + op = spv::Op::OpGroupNonUniformUMax; + } + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + operands.push_back(U32Operand(u32(spv::GroupOperation::Reduce))); + break; + case core::BuiltinFn::kSubgroupAll: + module_.PushCapability(SpvCapabilityGroupNonUniformVote); + op = spv::Op::OpGroupNonUniformAll; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kSubgroupAny: + module_.PushCapability(SpvCapabilityGroupNonUniformVote); + op = spv::Op::OpGroupNonUniformAny; + operands.push_back(Constant(ir_.constant_values.Get(u32(spv::Scope::Subgroup)))); + break; + case core::BuiltinFn::kTan: + glsl_ext_inst(GLSLstd450Tan); + break; + case core::BuiltinFn::kTanh: + glsl_ext_inst(GLSLstd450Tanh); + break; + case core::BuiltinFn::kTextureBarrier: { + spv::MemorySemanticsMask memory_mask = spv::MemorySemanticsMask::ImageMemory | + spv::MemorySemanticsMask::AcquireRelease; + if (options_.extensions.use_vulkan_memory_model) { + memory_mask = memory_mask | spv::MemorySemanticsMask::MakeAvailable | + spv::MemorySemanticsMask::MakeVisible; + } + + op = spv::Op::OpControlBarrier; + operands.clear(); + operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup)))); + operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup)))); + operands.push_back(Constant(b_.ConstantValue(u32(memory_mask)))); + break; + } + case core::BuiltinFn::kTranspose: + op = spv::Op::OpTranspose; + break; + case core::BuiltinFn::kTrunc: + glsl_ext_inst(GLSLstd450Trunc); + break; + case core::BuiltinFn::kUnpack2X16Float: + glsl_ext_inst(GLSLstd450UnpackHalf2x16); + break; + case core::BuiltinFn::kUnpack2X16Snorm: + glsl_ext_inst(GLSLstd450UnpackSnorm2x16); + break; + case core::BuiltinFn::kUnpack2X16Unorm: + glsl_ext_inst(GLSLstd450UnpackUnorm2x16); + break; + case core::BuiltinFn::kUnpack4X8Snorm: + glsl_ext_inst(GLSLstd450UnpackSnorm4x8); + break; + case core::BuiltinFn::kUnpack4X8Unorm: + glsl_ext_inst(GLSLstd450UnpackUnorm4x8); + break; + case core::BuiltinFn::kWorkgroupBarrier: { + spv::MemorySemanticsMask memory_mask = spv::MemorySemanticsMask::WorkgroupMemory | + spv::MemorySemanticsMask::AcquireRelease; + if (options_.extensions.use_vulkan_memory_model) { + memory_mask = memory_mask | spv::MemorySemanticsMask::MakeAvailable | + spv::MemorySemanticsMask::MakeVisible; + } + + op = spv::Op::OpControlBarrier; + operands.clear(); + operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup)))); + operands.push_back(Constant(b_.ConstantValue(u32(spv::Scope::Workgroup)))); + operands.push_back(Constant(b_.ConstantValue(u32(memory_mask)))); + break; + } + default: + TINT_IR_ICE(ir_) << "unimplemented builtin function: " << builtin->Func(); + } + TINT_IR_ASSERT(ir_, op != spv::Op::Max); + + // Add the arguments to the builtin call. + if (!args_emitted) { + for (auto* arg : builtin->Args()) { + operands.push_back(Value(arg)); + } + } + + // Emit the instruction. + current_function_.PushInst(op, operands); + } + + /// Emit a construct instruction. + /// @param construct the construct instruction to emit + void EmitConstruct(core::ir::Construct* construct) { + auto* result_ty = construct->Result()->Type(); + + // If there is just a single argument with the same type as the result, this is an identity + // constructor and we can just pass through the ID of the argument. + if (construct->Args().Length() == 1 && result_ty == construct->Args()[0]->Type()) { + values_.Add(construct->Result(), Value(construct->Args()[0])); + return; + } + + // A zero-value constructor may be used for subgroup matrices or when IR is created from a + // flow that is not the WGSL frontend, so special-case them into OpConstantNull here. + if (construct->Operands().IsEmpty()) { + values_.Add(construct->Result(), ConstantNull(result_ty)); + return; + } + + OperandList operands = {Type(result_ty), Value(construct)}; + for (auto* arg : construct->Args()) { + operands.push_back(Value(arg)); + } + current_function_.PushInst(spv::Op::OpCompositeConstruct, std::move(operands)); + } + + /// Emit a convert instruction. + /// @param convert the convert instruction to emit + void EmitConvert(core::ir::Convert* convert) { + auto* res_ty = convert->Result()->Type(); + auto* arg_ty = convert->Args()[0]->Type(); + + OperandList operands = {Type(convert->Result()->Type()), Value(convert)}; + for (auto* arg : convert->Args()) { + operands.push_back(Value(arg)); + } + + spv::Op op = spv::Op::Max; + if (res_ty->IsSignedIntegerScalarOrVector() && arg_ty->IsFloatScalarOrVector()) { + // float to signed int. + op = spv::Op::OpConvertFToS; + } else if (res_ty->IsUnsignedIntegerScalarOrVector() && arg_ty->IsFloatScalarOrVector()) { + // float to unsigned int. + op = spv::Op::OpConvertFToU; + } else if (res_ty->IsFloatScalarOrVector() && arg_ty->IsSignedIntegerScalarOrVector()) { + // signed int to float. + op = spv::Op::OpConvertSToF; + } else if (res_ty->IsFloatScalarOrVector() && arg_ty->IsUnsignedIntegerScalarOrVector()) { + // unsigned int to float. + op = spv::Op::OpConvertUToF; + } else if (res_ty->IsFloatScalarOrVector() && arg_ty->IsFloatScalarOrVector() && + res_ty->Size() != arg_ty->Size()) { + // float to float (different bitwidth). + op = spv::Op::OpFConvert; + } else if (res_ty->IsIntegerScalarOrVector() && arg_ty->IsIntegerScalarOrVector() && + res_ty->Size() == arg_ty->Size()) { + // int to int (same bitwidth, different signedness). + op = spv::Op::OpBitcast; + } else if (res_ty->IsBoolScalarOrVector()) { + if (arg_ty->IsIntegerScalarOrVector()) { + // int to bool. + op = spv::Op::OpINotEqual; + } else { + // float to bool. + op = spv::Op::OpFUnordNotEqual; + } + operands.push_back(ConstantNull(arg_ty)); + } else if (arg_ty->IsBoolScalarOrVector()) { + // Select between constant one and zero, splatting them to vectors if necessary. + core::ir::Constant* one = nullptr; + core::ir::Constant* zero = nullptr; + Switch( + res_ty->DeepestElement(), // + [&](const core::type::F32*) { + one = b_.Constant(1_f); + zero = b_.Constant(0_f); + }, + [&](const core::type::F16*) { + one = b_.Constant(1_h); + zero = b_.Constant(0_h); + }, + [&](const core::type::I32*) { + one = b_.Constant(1_i); + zero = b_.Constant(0_i); + }, + [&](const core::type::U32*) { + one = b_.Constant(1_u); + zero = b_.Constant(0_u); + }); + TINT_IR_ASSERT(ir_, one && zero); + + if (auto* vec = res_ty->As()) { + // Splat the scalars into vectors. + one = b_.Splat(vec, one); + zero = b_.Splat(vec, zero); + } + + op = spv::Op::OpSelect; + operands.push_back(Constant(b_.ConstantValue(one))); + operands.push_back(Constant(b_.ConstantValue(zero))); + } else { + TINT_IR_ICE(ir_) << "unhandled convert instruction"; + } + + current_function_.PushInst(op, std::move(operands)); + } + + SpvMemoryAccessMask MemoryAccessMaskForPointer(const core::type::Pointer* ptr) { + TINT_IR_ASSERT(ir_, ptr); + + if (options_.extensions.use_vulkan_memory_model && + (ptr->AddressSpace() == core::AddressSpace::kStorage || + ptr->AddressSpace() == core::AddressSpace::kWorkgroup) && + ptr->Access() == core::Access::kReadWrite) { + return SpvMemoryAccessNonPrivatePointerMask; + } + + return SpvMemoryAccessMaskNone; + } + + /// Emit a load instruction. + /// @param load the load instruction to emit + void EmitLoad(core::ir::Load* load) { + current_function_.PushInst(spv::Op::OpLoad, + {Type(load->Result()->Type()), Value(load), Value(load->From()), + U32Operand(MemoryAccessMaskForPointer( + load->From()->Type()->As()))}); + } + + /// Emit a load vector element instruction. + /// @param load the load vector element instruction to emit + void EmitLoadVectorElement(core::ir::LoadVectorElement* load) { + auto* vec_ptr_ty = load->From()->Type()->As(); + auto* el_ty = load->Result()->Type(); + auto* el_ptr_ty = ir_.Types().ptr(vec_ptr_ty->AddressSpace(), el_ty, vec_ptr_ty->Access()); + auto el_ptr_id = module_.NextId(); + current_function_.PushInst(spv::Op::OpAccessChain, + {Type(el_ptr_ty), el_ptr_id, Value(load->From()), + GetAccessChainIndexId(load->Index())}); + current_function_.PushInst(spv::Op::OpLoad, + {Type(load->Result()->Type()), Value(load), el_ptr_id, + U32Operand(MemoryAccessMaskForPointer(vec_ptr_ty))}); + } + + /// Emit a loop instruction. + /// @param loop the loop instruction to emit + void EmitLoop(core::ir::Loop* loop) { + auto init_label = loop->HasInitializer() ? Label(loop->Initializer()) : 0; + auto body_label = Label(loop->Body()); + auto continuing_label = Label(loop->Continuing()); + + auto header_label = GetLoopHeaderLabel(loop); + auto merge_label = GetMergeLabel(loop); + + if (init_label != 0) { + // Emit the loop initializer. + current_function_.PushInst(spv::Op::OpBranch, {init_label}); + QueueBlock(loop->Initializer()); + } else { + // No initializer. Branch to body. + current_function_.PushInst(spv::Op::OpBranch, {header_label}); + } + + // Emit the loop body header, which contains the OpLoopMerge and OpPhis. + // This then unconditionally branches to body_label + NewBlock(header_label); + EmitIncomingPhis(loop->Body()); + current_function_.PushInst(spv::Op::OpLoopMerge, {merge_label, continuing_label, + U32Operand(SpvLoopControlMaskNone)}); + current_function_.PushInst(spv::Op::OpBranch, {body_label}); + + // Emit the loop body + auto body_blk = NewBlock(body_label); + blocks_to_emit_.push_back({body_blk, loop->Body()}); + + auto cont_blk = NewBlock(continuing_label); + EmitIncomingPhis(loop->Continuing()); + + // Emit the loop continuing block. + if (loop->Continuing()->Terminator()) { + blocks_to_emit_.push_back({cont_blk, loop->Continuing()}); + } else { + // We still need to emit a continuing block with a back-edge, even if it is unreachable. + current_function_.PushInst(spv::Op::OpBranch, {header_label}); + } + + // Emit the loop merge block. + NewBlock(merge_label); + + // Emit the OpPhis for the ExitLoops + EmitExitPhis(loop); + } + + /// Emit a switch instruction. + /// @param swtch the switch instruction to emit + void EmitSwitch(core::ir::Switch* swtch) { + // Find the default selector. There must be exactly one. + uint32_t default_label = 0u; + for (auto& c : swtch->Cases()) { + for (auto& sel : c.selectors) { + if (sel.IsDefault()) { + default_label = Label(c.block); + } + } + } + TINT_IR_ASSERT(ir_, default_label != 0u); + + // Build the operands to the OpSwitch instruction. + OperandList switch_operands = {Value(swtch->Condition()), default_label}; + for (auto& c : swtch->Cases()) { + auto label = Label(c.block); + for (auto& sel : c.selectors) { + if (sel.IsDefault()) { + continue; + } + switch_operands.push_back(sel.val->Value()->ValueAs()); + switch_operands.push_back(label); + } + } + + uint32_t merge_label = GetMergeLabel(swtch); + + // Emit the OpSelectionMerge and OpSwitch instructions. + current_function_.PushInst(spv::Op::OpSelectionMerge, + {merge_label, U32Operand(SpvSelectionControlMaskNone)}); + current_function_.PushInst(spv::Op::OpSwitch, switch_operands); + + // Emit the cases. + for (auto& c : swtch->Cases()) { + QueueBlock(c.block); + } + + // Emit the switch merge block. + NewBlock(merge_label); + + // Emit the OpPhis for the ExitSwitches + EmitExitPhis(swtch); + } + + /// Emit a swizzle instruction. + /// @param swizzle the swizzle instruction to emit + void EmitSwizzle(core::ir::Swizzle* swizzle) { + auto id = Value(swizzle); + auto obj = Value(swizzle->Object()); + + // If there is only one swizzle index use OpCompositeExtract as we are producing a scalar. + if (swizzle->Indices().Length() == 1) { + OperandList operands = {Type(swizzle->Result()->Type()), id, obj, + swizzle->Indices()[0]}; + current_function_.PushInst(spv::Op::OpCompositeExtract, operands); + return; + } + + OperandList operands = {Type(swizzle->Result()->Type()), id, obj, obj}; + for (auto idx : swizzle->Indices()) { + operands.push_back(idx); + } + current_function_.PushInst(spv::Op::OpVectorShuffle, operands); + } + + /// Emit a store instruction. + /// @param store the store instruction to emit + void EmitStore(core::ir::Store* store) { + current_function_.PushInst(spv::Op::OpStore, + {Value(store->To()), Value(store->From()), + U32Operand(MemoryAccessMaskForPointer( + store->To()->Type()->As()))}); + } + + /// Emit a store vector element instruction. + /// @param store the store vector element instruction to emit + void EmitStoreVectorElement(core::ir::StoreVectorElement* store) { + auto* vec_ptr_ty = store->To()->Type()->As(); + auto* el_ty = store->Value()->Type(); + auto* el_ptr_ty = ir_.Types().ptr(vec_ptr_ty->AddressSpace(), el_ty, vec_ptr_ty->Access()); + auto el_ptr_id = module_.NextId(); + current_function_.PushInst(spv::Op::OpAccessChain, + {Type(el_ptr_ty), el_ptr_id, Value(store->To()), + GetAccessChainIndexId(store->Index())}); + current_function_.PushInst( + spv::Op::OpStore, + {el_ptr_id, Value(store->Value()), U32Operand(MemoryAccessMaskForPointer(vec_ptr_ty))}); + } + + /// Emit a unary instruction. + /// @param unary the unary instruction to emit + void EmitUnary(core::ir::CoreUnary* unary) { + auto id = Value(unary); + auto* ty = unary->Result()->Type(); + spv::Op op = spv::Op::Max; + switch (unary->Op()) { + case core::UnaryOp::kComplement: + op = spv::Op::OpNot; + break; + case core::UnaryOp::kNegation: + if (ty->IsFloatScalarOrVector()) { + op = spv::Op::OpFNegate; + } else if (ty->IsSignedIntegerScalarOrVector()) { + op = spv::Op::OpSNegate; + } + break; + case core::UnaryOp::kNot: + op = spv::Op::OpLogicalNot; + break; + default: + TINT_IR_UNIMPLEMENTED(ir_) << unary->Op(); + } + current_function_.PushInst(op, {Type(ty), id, Value(unary->Val())}); + } + + /// Emit a user call instruction. + /// @param call the user call instruction to emit + void EmitUserCall(core::ir::UserCall* call) { + auto id = Value(call); + OperandList operands = {Type(call->Result()->Type()), id, Value(call->Target())}; + for (auto* arg : call->Args()) { + operands.push_back(Value(arg)); + } + current_function_.PushInst(spv::Op::OpFunctionCall, operands); + } + + /// Emit IO attributes. + /// @param id the ID of the variable to decorate + /// @param attrs the shader IO attrs + /// @param addrspace the address of the variable + void EmitIOAttributes(uint32_t id, + const core::IOAttributes& attrs, + core::AddressSpace addrspace) { + if (attrs.location) { + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationLocation), *attrs.location}); + } + if (attrs.blend_src) { + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationIndex), *attrs.blend_src}); + } + if (attrs.interpolation) { + switch (attrs.interpolation->type) { + case core::InterpolationType::kLinear: + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationNoPerspective)}); + break; + case core::InterpolationType::kFlat: + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationFlat)}); + break; + case core::InterpolationType::kPerspective: + case core::InterpolationType::kUndefined: + break; + } + switch (attrs.interpolation->sampling) { + case core::InterpolationSampling::kCentroid: + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationCentroid)}); + break; + case core::InterpolationSampling::kSample: + module_.PushCapability(SpvCapabilitySampleRateShading); + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationSample)}); + break; + case core::InterpolationSampling::kCenter: + case core::InterpolationSampling::kFirst: + case core::InterpolationSampling::kEither: + case core::InterpolationSampling::kUndefined: + break; + } + } + if (attrs.builtin) { + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationBuiltIn), + Builtin(*attrs.builtin, addrspace)}); + } + if (attrs.invariant) { + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationInvariant)}); + } + } + + void EmitGlobalVar(core::ir::Var* var) { + auto* ptr = var->Result()->Type()->As(); + if (ptr->AddressSpace() == core::AddressSpace::kWorkgroup) { + auto* ty = ptr->StoreType(); + uint32_t align = ty->Align(); + uint32_t size = ty->Size(); + + // This essentially matches std430 layout rules from GLSL, which are in + // turn specified as an upper bound for Vulkan layout sizing. + output_.workgroup_info.storage_size += tint::RoundUp(16u, tint::RoundUp(align, size)); + } + EmitVar(var); + } + + /// Emit a var instruction. + /// @param var the var instruction to emit + void EmitVar(core::ir::Var* var) { + auto id = Value(var); + auto* ptr = var->Result()->Type()->As(); + auto* store_ty = ptr->StoreType(); + auto ty = Type(ptr); + + switch (ptr->AddressSpace()) { + case core::AddressSpace::kFunction: { + TINT_IR_ASSERT(ir_, current_function_); + if (var->Initializer()) { + current_function_.PushVar({ty, id, U32Operand(SpvStorageClassFunction)}); + current_function_.PushInst(spv::Op::OpStore, {id, Value(var->Initializer())}); + } else { + current_function_.PushVar( + {ty, id, U32Operand(SpvStorageClassFunction), ConstantNull(store_ty)}); + } + break; + } + case core::AddressSpace::kIn: { + TINT_IR_ASSERT(ir_, !current_function_); + if (store_ty->DeepestElement()->Is()) { + module_.PushCapability(SpvCapabilityStorageInputOutput16); + } + module_.PushType(spv::Op::OpVariable, {ty, id, U32Operand(SpvStorageClassInput)}); + EmitIOAttributes(id, var->Attributes(), core::AddressSpace::kIn); + break; + } + case core::AddressSpace::kPrivate: { + TINT_IR_ASSERT(ir_, !current_function_); + OperandList operands = {ty, id, U32Operand(SpvStorageClassPrivate)}; + if (var->Initializer()) { + TINT_IR_ASSERT(ir_, var->Initializer()->Is()); + operands.push_back(Value(var->Initializer())); + } else { + operands.push_back(ConstantNull(store_ty)); + } + module_.PushType(spv::Op::OpVariable, operands); + break; + } + case core::AddressSpace::kImmediate: { + TINT_IR_ASSERT(ir_, !current_function_); + module_.PushType(spv::Op::OpVariable, + {ty, id, U32Operand(SpvStorageClassPushConstant)}); + break; + } + case core::AddressSpace::kOut: { + TINT_IR_ASSERT(ir_, !current_function_); + if (store_ty->DeepestElement()->Is()) { + module_.PushCapability(SpvCapabilityStorageInputOutput16); + } + module_.PushType(spv::Op::OpVariable, {ty, id, U32Operand(SpvStorageClassOutput)}); + EmitIOAttributes(id, var->Attributes(), core::AddressSpace::kOut); + break; + } + case core::AddressSpace::kHandle: + case core::AddressSpace::kStorage: + case core::AddressSpace::kUniform: { + TINT_IR_ASSERT(ir_, !current_function_); + module_.PushType(spv::Op::OpVariable, + {ty, id, U32Operand(StorageClass(ptr->AddressSpace()))}); + auto bp = var->BindingPoint().value(); + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationDescriptorSet), bp.group}); + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationBinding), bp.binding}); + + // Add NonReadable and NonWritable decorations to storage textures and buffers. + auto* st = store_ty->As(); + bool is_storage_texture = + st && st->GetTexelFormat() != core::TexelFormat::kUndefined; + auto access = is_storage_texture ? st->GetAccess() : ptr->Access(); + + if (is_storage_texture || ptr->AddressSpace() != core::AddressSpace::kHandle) { + if (access == core::Access::kRead) { + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationNonWritable)}); + } else if (access == core::Access::kWrite) { + module_.PushAnnot(spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationNonReadable)}); + } + } + if (!options_.extensions.use_vulkan_memory_model && + access == core::Access::kReadWrite) { + module_.PushAnnot(spv::Op::OpDecorate, {id, U32Operand(SpvDecorationCoherent)}); + } + + auto iidx = var->InputAttachmentIndex(); + if (iidx) { + TINT_IR_ASSERT(ir_, st->GetDim() == type::Dim::kSubpassData); + module_.PushAnnot( + spv::Op::OpDecorate, + {id, U32Operand(SpvDecorationInputAttachmentIndex), iidx.value()}); + } + break; + } + case core::AddressSpace::kWorkgroup: { + TINT_IR_ASSERT(ir_, !current_function_); + OperandList operands = {ty, id, U32Operand(SpvStorageClassWorkgroup)}; + if (zero_init_workgroup_memory_) { + // If requested, use the VK_KHR_zero_initialize_workgroup_memory to + // zero-initialize the workgroup variable using an null constant initializer. + operands.push_back(ConstantNull(store_ty)); + } + module_.PushType(spv::Op::OpVariable, operands); + break; + } + default: { + TINT_IR_ICE(ir_) << "unimplemented variable address space " << ptr->AddressSpace(); + } + } + + // Set the name if present. + PushName(id, var); + } + + /// Emit a let instruction. + /// @param let the let instruction to emit + void EmitLet(core::ir::Let* let) { + auto id = Value(let->Value()); + values_.Add(let->Result(), id); + } + + /// Emit the OpPhis for the given flow control instruction. + /// @param inst the flow control instruction + void EmitExitPhis(core::ir::ControlInstruction* inst) { + struct Branch { + uint32_t label = 0; + core::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(); + + Vector branches; + branches.Reserve(inst->Exits().Count()); + + auto exits = inst->Exits().Vector(); + exits.Sort([](auto a, auto b) -> bool { return a < b; }); + + for (auto& exit : exits) { + branches.Push(Branch{GetTerminatorBlockLabel(exit), exit->Args()[index]}); + } + branches.Sort(); // Sort the branches by label to ensure deterministic output + + // Also add phi nodes from implicit exit blocks. + if (inst->Is()) { + inst->ForeachBlock([&](core::ir::Block* block) { + if (block->IsEmpty()) { + branches.Push(Branch{Label(block), nullptr}); + } + }); + } + OperandList ops{Type(ty), Value(result)}; + for (auto& branch : branches) { + if (branch.value == nullptr) { + ops.push_back(Undef(ty)); + } else { + ops.push_back(Value(branch.value)); + } + ops.push_back(branch.label); + } + current_function_.PushInst(spv::Op::OpPhi, std::move(ops)); + } + } + + /// Get the ID of the label of the merge block for a control instruction. + /// @param ci the control instruction to get the merge label for + /// @returns the label ID + uint32_t GetMergeLabel(core::ir::ControlInstruction* ci) { + return merge_block_labels_.GetOrAdd(ci, [&] { return module_.NextId(); }); + } + + /// Get the ID of the label of the loop header block + /// @param loop the loop to get the header id + /// @returns the label ID + uint32_t GetLoopHeaderLabel(core::ir::Loop* loop) { + return loop_header_block_labels_.GetOrAdd(loop, [&] { return module_.NextId(); }); + } + + /// Get the ID of the label of the block that will contain a terminator instruction. + /// @param t the terminator instruction to get the block label for + /// @returns the label ID + uint32_t GetTerminatorBlockLabel(core::ir::Terminator* t) { + // Walk backwards from `t` until we find a control instruction. + auto* inst = t->prev; + while (inst) { + auto* prev = inst->prev; + if (auto* ci = inst->As()) { + // This is the last control instruction before `t`, so use its merge block label. + return GetMergeLabel(ci); + } + inst = prev; + } + + // There were no control instructions before `t`, so use the label of the parent block. + return Label(t->Block()); + } + + /// Convert a texel format to the corresponding SPIR-V enum value, adding required capabilities. + /// @param format the format to convert + /// @returns the enum value of the corresponding SPIR-V texel format + uint32_t TexelFormat(const core::TexelFormat format) { + switch (format) { + case core::TexelFormat::kBgra8Unorm: + TINT_IR_ICE(ir_) << "bgra8unorm should have been polyfilled to rgba8unorm"; + case core::TexelFormat::kR8Unorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR8; + case core::TexelFormat::kR8Snorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR8Snorm; + case core::TexelFormat::kR8Uint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR8ui; + case core::TexelFormat::kR8Sint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR8i; + case core::TexelFormat::kRg8Unorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg8; + case core::TexelFormat::kRg8Snorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg8Snorm; + case core::TexelFormat::kRg8Uint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg8ui; + case core::TexelFormat::kRg8Sint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg8i; + case core::TexelFormat::kR16Uint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR16ui; + case core::TexelFormat::kR16Sint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR16i; + case core::TexelFormat::kR16Float: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR16f; + case core::TexelFormat::kRg16Uint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg16ui; + case core::TexelFormat::kRg16Sint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg16i; + case core::TexelFormat::kRg16Float: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg16f; + case core::TexelFormat::kR16Unorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR16; + case core::TexelFormat::kR16Snorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR16Snorm; + case core::TexelFormat::kRg16Unorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg16; + case core::TexelFormat::kRg16Snorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg16Snorm; + case core::TexelFormat::kRgba16Unorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRgba16; + case core::TexelFormat::kRgba16Snorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRgba16Snorm; + case core::TexelFormat::kR32Uint: + return SpvImageFormatR32ui; + case core::TexelFormat::kR32Sint: + return SpvImageFormatR32i; + case core::TexelFormat::kR32Float: + return SpvImageFormatR32f; + case core::TexelFormat::kRgba8Unorm: + return SpvImageFormatRgba8; + case core::TexelFormat::kRgba8Snorm: + return SpvImageFormatRgba8Snorm; + case core::TexelFormat::kRgba8Uint: + return SpvImageFormatRgba8ui; + case core::TexelFormat::kRgba8Sint: + return SpvImageFormatRgba8i; + case core::TexelFormat::kRg32Uint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg32ui; + case core::TexelFormat::kRg32Sint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg32i; + case core::TexelFormat::kRg32Float: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRg32f; + case core::TexelFormat::kRgba16Uint: + return SpvImageFormatRgba16ui; + case core::TexelFormat::kRgba16Sint: + return SpvImageFormatRgba16i; + case core::TexelFormat::kRgba16Float: + return SpvImageFormatRgba16f; + case core::TexelFormat::kRgba32Uint: + return SpvImageFormatRgba32ui; + case core::TexelFormat::kRgba32Sint: + return SpvImageFormatRgba32i; + case core::TexelFormat::kRgba32Float: + return SpvImageFormatRgba32f; + case core::TexelFormat::kRgb10A2Uint: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRgb10a2ui; + case core::TexelFormat::kRgb10A2Unorm: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatRgb10A2; + case core::TexelFormat::kRg11B10Ufloat: + module_.PushCapability(SpvCapabilityStorageImageExtendedFormats); + return SpvImageFormatR11fG11fB10f; + case core::TexelFormat::kUndefined: + return SpvImageFormatUnknown; + } + return SpvImageFormatUnknown; + } + + /// Set the debug name of an instruction. + void PushName(uint32_t id, core::ir::Instruction* inst) { PushName(id, ir_.NameOf(inst)); } + /// Set the debug name of a value. + void PushName(uint32_t id, core::ir::Value* value) { PushName(id, ir_.NameOf(value)); } + /// Set the debug name for a SPIR-V ID. + void PushName(uint32_t id, const Symbol& name) { + // Only set the name if it is valid and if we are not stripping user identifiers. + if (name && !options_.strip_all_names) { + module_.PushDebug(spv::Op::OpName, {id, Operand(name.Name())}); + } + } + /// Set the debug member name for a SPIR-V ID. + void PushMemberName(uint32_t id, uint32_t index, const Symbol& name) { + // Only set the name if it is valid and if we are not stripping user identifiers. + if (name && !options_.strip_all_names) { + module_.PushDebug(spv::Op::OpMemberName, {id, index, Operand(name.Name())}); + } + } +}; + +} // namespace + +Result Print(core::ir::Module& module, const Options& options) { + return Printer{module, options}.Code(); +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.h b/3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.h new file mode 100644 index 000000000..0922e3e22 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/printer/printer.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_PRINTER_PRINTER_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_PRINTER_PRINTER_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/lang/spirv/writer/common/output.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::spirv::writer { + +// The capabilities that might be needed due to raising. +const core::ir::Capabilities kPrinterCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// @returns the generated SPIR-V instructions on success, or failure +/// @param module the Tint IR module to generate +/// @param options the printer options +Result Print(core::ir::Module& module, const Options& options); + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_PRINTER_PRINTER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc new file mode 100644 index 000000000..7dd07e392 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc @@ -0,0 +1,1447 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/builtin_polyfill.h" + +#include + +#include "spirv/unified1/spirv.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/spirv/ir/binary.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/lang/spirv/ir/literal_operand.h" +#include "src/tint/lang/spirv/type/resource_table.h" +#include "src/tint/lang/spirv/type/sampled_image.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/internal_limits.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +const spirv::type::Image* ImageFromTexture(core::type::Manager& ty, + const core::type::Texture* tex_ty) { + auto dim = type::Dim::kD1; + auto depth = type::Depth::kNotDepth; + auto arrayed = type::Arrayed::kNonArrayed; + auto ms = type::Multisampled::kSingleSampled; + auto sampled = type::Sampled::kSamplingCompatible; + auto fmt = core::TexelFormat::kUndefined; + auto access = core::Access::kReadWrite; + const core::type::Type* sample_ty = ty.f32(); + + switch (tex_ty->Dim()) { + case core::type::TextureDimension::k1d: + dim = type::Dim::kD1; + break; + case core::type::TextureDimension::k2d: + dim = type::Dim::kD2; + break; + case core::type::TextureDimension::k2dArray: + dim = type::Dim::kD2; + arrayed = type::Arrayed::kArrayed; + break; + case core::type::TextureDimension::k3d: + dim = type::Dim::kD3; + break; + case core::type::TextureDimension::kCube: + dim = type::Dim::kCube; + break; + case core::type::TextureDimension::kCubeArray: + dim = type::Dim::kCube; + arrayed = type::Arrayed::kArrayed; + break; + default: + TINT_ICE() << "Invalid texture dimension: " << tex_ty->Dim(); + } + + tint::Switch( + tex_ty, // + [&](const core::type::DepthTexture*) { // + depth = type::Depth::kDepth; + }, + [&](const core::type::DepthMultisampledTexture*) { + depth = type::Depth::kDepth; + ms = type::Multisampled::kMultisampled; + }, + [&](const core::type::MultisampledTexture* mt) { + ms = type::Multisampled::kMultisampled; + sample_ty = mt->Type(); + }, + [&](const core::type::SampledTexture* st) { + sampled = type::Sampled::kSamplingCompatible; + sample_ty = st->Type(); + }, + [&](const core::type::StorageTexture* st) { + sampled = type::Sampled::kReadWriteOpCompatible; + fmt = st->TexelFormat(); + sample_ty = st->Type(); + access = st->Access(); + }, + [&](const core::type::TexelBuffer* tb) { + sampled = type::Sampled::kReadWriteOpCompatible; + fmt = tb->TexelFormat(); + sample_ty = tb->Type(); + access = tb->Access(); + dim = type::Dim::kBuffer; + }, + [&](const core::type::InputAttachment* ia) { + dim = type::Dim::kSubpassData; + sampled = type::Sampled::kReadWriteOpCompatible; + sample_ty = ia->Type(); + }, + TINT_ICE_ON_NO_MATCH); + + return ty.Get(sample_ty, dim, depth, arrayed, ms, sampled, fmt, access); +} + +/// Returns a replacement type if type replacement is necessary. +/// @param ty the type manager +/// @param type the type to replace +/// @returns the replacement type if replacement needs to happen +const core::type::Type* ReplacementType(core::type::Manager& ty, const core::type::Type* type) { + return Switch( + type, + [&](const core::type::Pointer* ptr) -> const core::type::Type* { + if (auto* replacement = ReplacementType(ty, ptr->StoreType())) { + return ty.ptr(ptr->AddressSpace(), replacement, ptr->Access()); + } + return nullptr; + }, + [&](const core::type::BindingArray* arr) -> const core::type::Type* { + if (auto* replacement = ReplacementType(ty, arr->ElemType())) { + return ty.binding_array(replacement, + arr->Count()->As()->value); + } + return nullptr; + }, + [&](const spirv::type::ResourceTable* rb) -> const core::type::Type* { + if (auto* replacement = ReplacementType(ty, rb->GetBindingType())) { + return ty.Get(replacement); + } + return nullptr; + }, + [&](const core::type::Texture* tex) { return ImageFromTexture(ty, tex); }, + [&](Default) { return nullptr; }); +} + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + PolyfillConfig config; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + // Find the builtins that need replacing. + Vector worklist; + Vector subgroup_matrix_constructors; + + // Replace types for function parameters if necessary + for (auto fn : ir.functions) { + for (auto* param : fn->Params()) { + if (auto* replacement = ReplacementType(ty, param->Type())) { + param->SetType(replacement); + } + } + } + + for (auto* inst : ir.Instructions()) { + // Replace types for instruction results if necessary + for (auto* result : inst->Results()) { + if (auto* replacement = ReplacementType(ty, result->Type())) { + result->SetType(replacement); + } + } + + if (auto* builtin = inst->As()) { + switch (builtin->Func()) { + case core::BuiltinFn::kArrayLength: + case core::BuiltinFn::kAtomicAdd: + case core::BuiltinFn::kAtomicAnd: + case core::BuiltinFn::kAtomicCompareExchangeWeak: + case core::BuiltinFn::kAtomicExchange: + case core::BuiltinFn::kAtomicLoad: + case core::BuiltinFn::kAtomicMax: + case core::BuiltinFn::kAtomicMin: + case core::BuiltinFn::kAtomicOr: + case core::BuiltinFn::kAtomicStore: + case core::BuiltinFn::kAtomicSub: + case core::BuiltinFn::kAtomicXor: + case core::BuiltinFn::kDot: + case core::BuiltinFn::kDot4I8Packed: + case core::BuiltinFn::kDot4U8Packed: + case core::BuiltinFn::kQuadBroadcast: + case core::BuiltinFn::kSelect: + case core::BuiltinFn::kSubgroupBroadcast: + case core::BuiltinFn::kSubgroupShuffle: + case core::BuiltinFn::kSubgroupShuffleDown: + case core::BuiltinFn::kSubgroupShuffleUp: + case core::BuiltinFn::kSubgroupShuffleXor: + case core::BuiltinFn::kTextureDimensions: + case core::BuiltinFn::kTextureGather: + case core::BuiltinFn::kTextureGatherCompare: + case core::BuiltinFn::kTextureLoad: + case core::BuiltinFn::kTextureNumLayers: + case core::BuiltinFn::kTextureNumLevels: + case core::BuiltinFn::kTextureNumSamples: + case core::BuiltinFn::kTextureSample: + case core::BuiltinFn::kTextureSampleBias: + case core::BuiltinFn::kTextureSampleCompare: + case core::BuiltinFn::kTextureSampleCompareLevel: + case core::BuiltinFn::kTextureSampleGrad: + case core::BuiltinFn::kTextureSampleLevel: + case core::BuiltinFn::kTextureStore: + case core::BuiltinFn::kInputAttachmentLoad: + case core::BuiltinFn::kSubgroupMatrixLoad: + case core::BuiltinFn::kSubgroupMatrixStore: + case core::BuiltinFn::kSubgroupMatrixMultiply: + case core::BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + case core::BuiltinFn::kSubgroupMatrixScalarAdd: + case core::BuiltinFn::kSubgroupMatrixScalarSubtract: + case core::BuiltinFn::kSubgroupMatrixScalarMultiply: + worklist.Push(builtin); + break; + case core::BuiltinFn::kQuantizeToF16: + if (builtin->Result()->Type()->Is()) { + worklist.Push(builtin); + } + break; + default: + break; + } + } + if (auto* construct = inst->As()) { + if (auto* sm = construct->Result()->Type()->As()) { + if (sm->Type()->IsAnyOf() && + construct->Args().Length() > 0) { + subgroup_matrix_constructors.Push(construct); + } + } + } + } + + // Replace the builtins that we found. + for (auto* builtin : worklist) { + switch (builtin->Func()) { + case core::BuiltinFn::kArrayLength: + ArrayLength(builtin); + break; + case core::BuiltinFn::kAtomicAdd: + case core::BuiltinFn::kAtomicAnd: + case core::BuiltinFn::kAtomicCompareExchangeWeak: + case core::BuiltinFn::kAtomicExchange: + case core::BuiltinFn::kAtomicLoad: + case core::BuiltinFn::kAtomicMax: + case core::BuiltinFn::kAtomicMin: + case core::BuiltinFn::kAtomicOr: + case core::BuiltinFn::kAtomicStore: + case core::BuiltinFn::kAtomicSub: + case core::BuiltinFn::kAtomicXor: + Atomic(builtin); + break; + case core::BuiltinFn::kDot: + Dot(builtin); + break; + case core::BuiltinFn::kDot4I8Packed: + case core::BuiltinFn::kDot4U8Packed: + DotPacked4x8(builtin); + break; + case core::BuiltinFn::kQuadBroadcast: + QuadBroadcast(builtin); + break; + case core::BuiltinFn::kSelect: + Select(builtin); + break; + case core::BuiltinFn::kSubgroupBroadcast: + SubgroupBroadcast(builtin); + break; + case core::BuiltinFn::kSubgroupShuffle: + case core::BuiltinFn::kSubgroupShuffleDown: + case core::BuiltinFn::kSubgroupShuffleUp: + case core::BuiltinFn::kSubgroupShuffleXor: + SubgroupShuffle(builtin, config.subgroup_shuffle_clamped); + break; + case core::BuiltinFn::kTextureDimensions: + TextureDimensions(builtin); + break; + case core::BuiltinFn::kTextureGather: + case core::BuiltinFn::kTextureGatherCompare: + TextureGather(builtin); + break; + case core::BuiltinFn::kTextureLoad: + TextureLoad(builtin); + break; + case core::BuiltinFn::kTextureNumLayers: + TextureNumLayers(builtin); + break; + case core::BuiltinFn::kTextureNumLevels: + TextureNumLevels(builtin); + break; + case core::BuiltinFn::kTextureNumSamples: + TextureNumSamples(builtin); + break; + case core::BuiltinFn::kTextureSample: + case core::BuiltinFn::kTextureSampleBias: + case core::BuiltinFn::kTextureSampleCompare: + case core::BuiltinFn::kTextureSampleCompareLevel: + case core::BuiltinFn::kTextureSampleGrad: + case core::BuiltinFn::kTextureSampleLevel: + TextureSample(builtin); + break; + case core::BuiltinFn::kTextureStore: + TextureStore(builtin); + break; + case core::BuiltinFn::kQuantizeToF16: + QuantizeToF16Vec(builtin); + break; + case core::BuiltinFn::kInputAttachmentLoad: + InputAttachmentLoad(builtin); + break; + case core::BuiltinFn::kSubgroupMatrixLoad: + SubgroupMatrixLoad(builtin); + break; + case core::BuiltinFn::kSubgroupMatrixStore: + SubgroupMatrixStore(builtin); + break; + case core::BuiltinFn::kSubgroupMatrixMultiply: + SubgroupMatrixMultiply(builtin); + break; + case core::BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + SubgroupMatrixMultiplyAccumulate(builtin); + break; + case core::BuiltinFn::kSubgroupMatrixScalarAdd: + SubgroupMatrixScalar(builtin, core::BinaryOp::kAdd); + break; + case core::BuiltinFn::kSubgroupMatrixScalarSubtract: + SubgroupMatrixScalar(builtin, core::BinaryOp::kSubtract); + break; + case core::BuiltinFn::kSubgroupMatrixScalarMultiply: + SubgroupMatrixScalar(builtin, core::BinaryOp::kMultiply); + break; + default: + break; + } + } + + // Replace non-zero subgroup matrix constructors that use 8-bit component types. + // SPIR-V requires that the value passed to OpCompositeConstruct is an 8-bit value. + for (auto* construct : subgroup_matrix_constructors) { + auto* sm_ty = construct->Result()->Type()->As(); + TINT_IR_ASSERT(ir, construct->Args().Length() == 1u); + TINT_IR_ASSERT(ir, sm_ty); + auto* value = construct->Args()[0]; + b.InsertBefore(construct, [&] { + if (sm_ty->Type()->Is()) { + value = b.CallExplicit( + ty.i8(), spirv::BuiltinFn::kSConvert, Vector{ty.i8()}, + b.Clamp(value, -128_i, 127_i)) + ->Result(); + } else if (sm_ty->Type()->Is()) { + value = b.CallExplicit( + ty.u8(), spirv::BuiltinFn::kUConvert, Vector{ty.u8()}, + b.Clamp(value, 0_u, 255_u)) + ->Result(); + } + }); + construct->SetArg(0, value); + } + } + + /// Create a literal operand. + /// @param value the literal value + /// @returns the literal operand + spirv::ir::LiteralOperand* Literal(u32 value) { + return ir.CreateValue(b.ConstantValue(value)); + } + + /// Handle an `arrayLength()` builtin. + /// @param builtin the builtin call instruction + void ArrayLength(core::ir::CoreBuiltinCall* builtin) { + // Strip away any let instructions to get to the original struct member access instruction. + auto* ptr = builtin->Args()[0]->As(); + while (auto* let = tint::As(ptr->Instruction())) { + ptr = let->Value()->As(); + } + TINT_IR_ASSERT(ir, ptr); + + auto* access = ptr->Instruction()->As(); + TINT_IR_ASSERT(ir, access); + TINT_IR_ASSERT(ir, access->Indices().Length() == 1u); + TINT_IR_ASSERT(ir, access->Object()->Type()->UnwrapPtr()->Is()); + auto* const_idx = access->Indices()[0]->As(); + + // Replace the builtin call with a call to the spirv.array_length intrinsic. + auto* call = b.CallWithResult( + builtin->DetachResult(), spirv::BuiltinFn::kArrayLength, + Vector{access->Object(), Literal(u32(const_idx->Value()->ValueAs()))}); + call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle an atomic*() builtin. + /// @param builtin the builtin call instruction + void Atomic(core::ir::CoreBuiltinCall* builtin) { + auto* result_ty = builtin->Result()->Type(); + + auto* pointer = builtin->Args()[0]; + auto* memory = [&]() -> core::ir::Value* { + switch (pointer->Type()->As()->AddressSpace()) { + case core::AddressSpace::kWorkgroup: + return b.Constant(u32(SpvScopeWorkgroup)); + case core::AddressSpace::kStorage: + return b.Constant(u32(SpvScopeDevice)); + default: + TINT_IR_UNREACHABLE(ir) << "unhandled atomic address space"; + } + }(); + auto* memory_semantics = b.Constant(u32(SpvMemorySemanticsMaskNone)); + + // Helper to build the builtin call with the common operands. + auto build = [&](enum spirv::BuiltinFn builtin_fn) { + return b.CallWithResult(builtin->DetachResult(), builtin_fn, + pointer, memory, memory_semantics); + }; + + // Create the replacement call instruction. + core::ir::Call* call = nullptr; + switch (builtin->Func()) { + case core::BuiltinFn::kAtomicAdd: + call = build(spirv::BuiltinFn::kAtomicIAdd); + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicAnd: + call = build(spirv::BuiltinFn::kAtomicAnd); + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicCompareExchangeWeak: { + auto* cmp = builtin->Args()[1]; + auto* value = builtin->Args()[2]; + auto* int_ty = value->Type(); + call = + b.Call(int_ty, spirv::BuiltinFn::kAtomicCompareExchange, + pointer, memory, memory_semantics); + call->AppendArg(memory_semantics); + call->AppendArg(value); + call->AppendArg(cmp); + call->InsertBefore(builtin); + + // Compare the original value to the comparator to see if an exchange happened. + auto* original = call->Result(); + auto* compare = b.Equal(original, cmp); + compare->InsertBefore(builtin); + + // Construct the atomicCompareExchange result structure. + call = b.ConstructWithResult(builtin->DetachResult(), + Vector{original, compare->Result()}); + break; + } + case core::BuiltinFn::kAtomicExchange: + call = build(spirv::BuiltinFn::kAtomicExchange); + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicLoad: + call = build(spirv::BuiltinFn::kAtomicLoad); + break; + case core::BuiltinFn::kAtomicOr: + call = build(spirv::BuiltinFn::kAtomicOr); + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicMax: + if (result_ty->IsSignedIntegerScalar()) { + call = build(spirv::BuiltinFn::kAtomicSMax); + } else { + call = build(spirv::BuiltinFn::kAtomicUMax); + } + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicMin: + if (result_ty->IsSignedIntegerScalar()) { + call = build(spirv::BuiltinFn::kAtomicSMin); + } else { + call = build(spirv::BuiltinFn::kAtomicUMin); + } + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicStore: + call = build(spirv::BuiltinFn::kAtomicStore); + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicSub: + call = build(spirv::BuiltinFn::kAtomicISub); + call->AppendArg(builtin->Args()[1]); + break; + case core::BuiltinFn::kAtomicXor: + call = build(spirv::BuiltinFn::kAtomicXor); + call->AppendArg(builtin->Args()[1]); + break; + default: + TINT_IR_UNREACHABLE(ir) << "unhandled atomic builtin"; + } + + call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle a `dot()` builtin. + /// @param builtin the builtin call instruction + void Dot(core::ir::CoreBuiltinCall* builtin) { + // OpDot only supports floating point operands, so we need to polyfill the integer case. + // TODO(crbug.com/tint/1267): If SPV_KHR_integer_dot_product is supported, use that instead. + if (builtin->Result()->Type()->IsIntegerScalar()) { + core::ir::Instruction* sum = nullptr; + + auto* v1 = builtin->Args()[0]; + auto* v2 = builtin->Args()[1]; + auto* vec = v1->Type()->As(); + auto* elty = vec->Type(); + for (uint32_t i = 0; i < vec->Width(); i++) { + b.InsertBefore(builtin, [&] { + auto* e1 = b.Access(elty, v1, u32(i)); + auto* e2 = b.Access(elty, v2, u32(i)); + auto* mul = b.Multiply(e1, e2); + if (sum) { + sum = b.Add(sum, mul); + } else { + sum = mul; + } + }); + } + sum->SetResult(builtin->DetachResult()); + builtin->Destroy(); + return; + } + + // Replace the builtin call with a call to the spirv.dot intrinsic. + auto args = Vector(builtin->Args()); + auto* call = b.CallWithResult( + builtin->DetachResult(), spirv::BuiltinFn::kDot, std::move(args)); + call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle a `dot4{I,U}8Packed()` builtin. + /// @param builtin the builtin call instruction + void DotPacked4x8(core::ir::CoreBuiltinCall* builtin) { + // Replace the builtin call with a call to the spirv.{s,u}dot intrinsic. + auto is_signed = builtin->Func() == core::BuiltinFn::kDot4I8Packed; + auto inst = is_signed ? spirv::BuiltinFn::kSDot : spirv::BuiltinFn::kUDot; + + auto args = Vector(builtin->Args()); + args.Push(Literal(u32(SpvPackedVectorFormatPackedVectorFormat4x8Bit))); + + auto* call = b.CallWithResult(builtin->DetachResult(), inst, + std::move(args)); + call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle a `select()` builtin. + /// @param builtin the builtin call instruction + void Select(core::ir::CoreBuiltinCall* builtin) { + // Argument order is different in SPIR-V: (condition, true_operand, false_operand). + Vector args = { + builtin->Args()[2], + builtin->Args()[1], + builtin->Args()[0], + }; + + if (config.version < SpvVersion::kSpv14) { + // If the condition is scalar and the objects are vectors, we need to splat the + // condition into a vector of the same size. + auto* vec = builtin->Result()->Type()->As(); + if (vec && args[0]->Type()->Is()) { + Vector elements; + elements.Resize(vec->Width(), args[0]); + + auto* construct = + b.Construct(ty.vec(ty.bool_(), vec->Width()), std::move(elements)); + construct->InsertBefore(builtin); + args[0] = construct->Result(); + } + } + + // Replace the builtin call with a call to the spirv.select intrinsic. + auto* call = b.CallWithResult( + builtin->DetachResult(), spirv::BuiltinFn::kSelect, std::move(args)); + call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// ImageOperands represents the optional image operands for an image instruction. + struct ImageOperands { + /// Bias + core::ir::Value* bias = nullptr; + /// Lod + core::ir::Value* lod = nullptr; + /// Grad (dx) + core::ir::Value* ddx = nullptr; + /// Grad (dy) + core::ir::Value* ddy = nullptr; + /// ConstOffset + core::ir::Value* offset = nullptr; + /// Sample + core::ir::Value* sample = nullptr; + }; + + /// Append optional image operands to an image intrinsic argument list. + /// @param operands the operands + /// @param args the argument list + /// @param insertion_point the insertion point for new instructions + /// @param requires_float_lod true if the lod needs to be a floating point value + void AppendImageOperands(ImageOperands& operands, + Vector& args, + core::ir::CoreBuiltinCall* insertion_point, + bool requires_float_lod) { + // Add a placeholder argument for the image operand mask, which we will fill in when we have + // processed the image operands. + uint32_t image_operand_mask = 0u; + size_t mask_idx = args.Length(); + args.Push(nullptr); + + // Append the NonPrivateTexel flag to Read/Write storage textures when we load/store them. + if (config.use_vulkan_memory_model) { + if (insertion_point->Func() == core::BuiltinFn::kTextureLoad || + insertion_point->Func() == core::BuiltinFn::kTextureStore) { + if (auto* st = insertion_point->Args()[0]->Type()->As()) { + if (st->GetTexelFormat() != core::TexelFormat::kUndefined && + st->GetAccess() == core::Access::kReadWrite) { + image_operand_mask |= SpvImageOperandsNonPrivateTexelMask; + } + } + } + } + + // Add each of the optional image operands if used, updating the image operand mask. + if (operands.bias) { + image_operand_mask |= SpvImageOperandsBiasMask; + args.Push(operands.bias); + } + if (operands.lod) { + image_operand_mask |= SpvImageOperandsLodMask; + if (requires_float_lod && operands.lod->Type()->IsIntegerScalar()) { + auto* convert = b.Convert(ty.f32(), operands.lod); + convert->InsertBefore(insertion_point); + operands.lod = convert->Result(); + } + args.Push(operands.lod); + } + if (operands.ddx) { + image_operand_mask |= SpvImageOperandsGradMask; + args.Push(operands.ddx); + args.Push(operands.ddy); + } + if (operands.offset) { + image_operand_mask |= SpvImageOperandsConstOffsetMask; + args.Push(operands.offset); + } + if (operands.sample) { + image_operand_mask |= SpvImageOperandsSampleMask; + args.Push(operands.sample); + } + + // Replace the image operand mask with the final mask value, as a literal operand. + args[mask_idx] = Literal(u32(image_operand_mask)); + } + + /// Append an array index to a coordinate vector. + /// @param coords the coordinate vector + /// @param array_idx the array index + /// @param insertion_point the insertion point for new instructions + /// @returns the modified coordinate vector + core::ir::Value* AppendArrayIndex(core::ir::Value* coords, + core::ir::Value* array_idx, + core::ir::Instruction* insertion_point) { + auto* vec = coords->Type()->As(); + auto* element_ty = vec->Type(); + + // Convert the index to match the coordinate type if needed. + if (array_idx->Type() != element_ty) { + auto* array_idx_converted = b.Convert(element_ty, array_idx); + array_idx_converted->InsertBefore(insertion_point); + array_idx = array_idx_converted->Result(); + } + + // Construct a new coordinate vector. + auto num_coords = vec->Width(); + auto* coord_ty = ty.vec(element_ty, num_coords + 1); + auto* construct = b.Construct(coord_ty, Vector{coords, array_idx}); + construct->InsertBefore(insertion_point); + return construct->Result(); + } + + /// Handle a textureSample*() builtin. + /// @param builtin the builtin call instruction + void TextureSample(core::ir::CoreBuiltinCall* builtin) { + // Helper to get the next argument from the call, or nullptr if there are no more arguments. + uint32_t arg_idx = 0; + auto next_arg = [&]() { + return arg_idx < builtin->Args().Length() ? builtin->Args()[arg_idx++] : nullptr; + }; + + auto* texture = next_arg(); + auto* sampler = next_arg(); + auto* coords = next_arg(); + auto* texture_ty = texture->Type()->As(); + + const bool is_depth_3d_cube_array = texture_ty->GetArrayed() == type::Arrayed::kArrayed && + texture_ty->GetDepth() == type::Depth::kDepth && + texture_ty->GetDim() == type::Dim::kCube; + const bool polyfill_depth_cube_array = + config.texture_sample_compare_depth_cube_array && is_depth_3d_cube_array && + (builtin->Func() == core::BuiltinFn::kTextureSampleCompare || + builtin->Func() == core::BuiltinFn::kTextureSampleCompareLevel); + + // Use OpSampledImage to create an OpTypeSampledImage object. + auto* sampled_image = b.CallExplicit( + ty.Get(texture_ty), spirv::BuiltinFn::kOpSampledImage, + Vector{texture_ty}, Vector{texture, sampler}); + sampled_image->InsertBefore(builtin); + + // Append the array index to the coordinates if provided. + auto* array_idx = + texture_ty->GetArrayed() == type::Arrayed::kArrayed ? next_arg() : nullptr; + if (array_idx) { + coords = AppendArrayIndex(coords, array_idx, builtin); + } + + // Determine which SPIR-V function to use and which optional image operands are needed. + enum spirv::BuiltinFn function = BuiltinFn::kNone; + core::ir::Value* depth = nullptr; + ImageOperands operands; + switch (builtin->Func()) { + case core::BuiltinFn::kTextureSample: + function = spirv::BuiltinFn::kImageSampleImplicitLod; + operands.offset = next_arg(); + break; + case core::BuiltinFn::kTextureSampleBias: + function = spirv::BuiltinFn::kImageSampleImplicitLod; + operands.bias = next_arg(); + operands.offset = next_arg(); + break; + case core::BuiltinFn::kTextureSampleCompare: + function = polyfill_depth_cube_array + ? spirv::BuiltinFn::kImageDrefGather + : spirv::BuiltinFn::kImageSampleDrefImplicitLod; + depth = next_arg(); + operands.offset = next_arg(); + break; + case core::BuiltinFn::kTextureSampleCompareLevel: + function = polyfill_depth_cube_array + ? spirv::BuiltinFn::kImageDrefGather + : spirv::BuiltinFn::kImageSampleDrefExplicitLod; + depth = next_arg(); + if (!polyfill_depth_cube_array) { + operands.lod = b.Constant(0_f); + } + operands.offset = next_arg(); + break; + case core::BuiltinFn::kTextureSampleGrad: + function = spirv::BuiltinFn::kImageSampleExplicitLod; + operands.ddx = next_arg(); + operands.ddy = next_arg(); + operands.offset = next_arg(); + break; + case core::BuiltinFn::kTextureSampleLevel: + function = spirv::BuiltinFn::kImageSampleExplicitLod; + operands.lod = next_arg(); + operands.offset = next_arg(); + break; + default: + TINT_IR_UNREACHABLE(ir) << "unhandled texture sample builtin"; + } + + // Start building the argument list for the function. + // The first two operands are always the sampled image and then the coordinates, followed by + // the depth reference if used. + Vector function_args; + function_args.Push(sampled_image->Result()); + function_args.Push(coords); + if (depth) { + function_args.Push(depth); + } + + // Add the optional image operands, if any. + AppendImageOperands(operands, function_args, builtin, /* requires_float_lod */ true); + + // Call the function. + // If this is a depth comparison, the result is always f32, otherwise vec4f. + auto* result_ty = (depth && !polyfill_depth_cube_array) + ? static_cast(ty.f32()) + : ty.vec4f(); + + core::ir::Instruction* result = + b.Call(result_ty, function, std::move(function_args)); + result->InsertBefore(builtin); + + // If this is not a depth comparison but we are sampling a depth texture, extract the first + // component to get the scalar f32 that SPIR-V expects. + if (!depth && texture_ty->GetDepth() == type::Depth::kDepth) { + result = b.Access(ty.f32(), result, 0_u); + result->InsertBefore(builtin); + } + + if (polyfill_depth_cube_array) { + core::ir::Instruction* close_to_pcf_result = nullptr; + b.InsertAfter(result, [&] { + // This is an imperfect polyfill for builtin intrinsic to do PCF style shadows. + // See: crbug.com/467015399 + // To do a complete polyfill we would have to properly do bilinear interpolation of + // the TextureGatherCompare result which we do not do as there is no trivial way to + // do it for a cubemap. + + // We do a textureGatherCompare and then dot with a vec4f(0.25) to get the average + // result. This will give PCF-like shadows but they will not be as smooth as the + // result from the original TextureSampleCompare. We also only sample mip0 which is + // identical to TextureSampleCompareLevel but not TextureSampleCompare. + close_to_pcf_result = + b.Call(ty.f32(), spirv::BuiltinFn::kDot, result, + b.Splat(ty.vec4f(), b.Constant(0.25_f))); + }); + + close_to_pcf_result->SetResult(builtin->DetachResult()); + builtin->Destroy(); + return; + } + + result->SetResult(builtin->DetachResult()); + builtin->Destroy(); + } + + /// Handle a textureGather*() builtin. + /// @param builtin the builtin call instruction + void TextureGather(core::ir::CoreBuiltinCall* builtin) { + // Helper to get the next argument from the call, or nullptr if there are no more arguments. + uint32_t arg_idx = 0; + auto next_arg = [&]() { + return arg_idx < builtin->Args().Length() ? builtin->Args()[arg_idx++] : nullptr; + }; + + auto* component = next_arg(); + if (!component->Type()->IsIntegerScalar()) { + // The first argument wasn't the component, so it must be the texture instead. + // Use constant zero for the component. + component = b.Constant(0_u); + arg_idx--; + } + auto* texture = next_arg(); + auto* sampler = next_arg(); + auto* coords = next_arg(); + auto* texture_ty = texture->Type()->As(); + + // Use OpSampledImage to create an OpTypeSampledImage object. + auto* sampled_image = b.CallExplicit( + ty.Get(texture_ty), spirv::BuiltinFn::kOpSampledImage, + Vector{texture_ty}, Vector{texture, sampler}); + sampled_image->InsertBefore(builtin); + + // Append the array index to the coordinates if provided. + auto* array_idx = + texture_ty->GetArrayed() == type::Arrayed::kArrayed ? next_arg() : nullptr; + if (array_idx) { + coords = AppendArrayIndex(coords, array_idx, builtin); + } + + // Determine which SPIR-V function to use and which optional image operands are needed. + enum spirv::BuiltinFn function = BuiltinFn::kNone; + core::ir::Value* depth = nullptr; + ImageOperands operands; + switch (builtin->Func()) { + case core::BuiltinFn::kTextureGather: + function = spirv::BuiltinFn::kImageGather; + operands.offset = next_arg(); + break; + case core::BuiltinFn::kTextureGatherCompare: + function = spirv::BuiltinFn::kImageDrefGather; + depth = next_arg(); + operands.offset = next_arg(); + break; + default: + TINT_IR_UNIMPLEMENTED(ir) << "unhandled texture gather builtin"; + } + + // Start building the argument list for the function. + // The first two operands are always the sampled image and then the coordinates, followed by + // either the depth reference or the component. + Vector function_args; + function_args.Push(sampled_image->Result()); + function_args.Push(coords); + if (depth) { + function_args.Push(depth); + } else { + function_args.Push(component); + } + + // Add the optional image operands, if any. + AppendImageOperands(operands, function_args, builtin, /* requires_float_lod */ true); + + // Call the function. + auto* texture_call = b.CallWithResult( + builtin->DetachResult(), function, std::move(function_args)); + texture_call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle a textureLoad() builtin. + /// @param builtin the builtin call instruction + void TextureLoad(core::ir::CoreBuiltinCall* builtin) { + // Helper to get the next argument from the call, or nullptr if there are no more arguments. + uint32_t arg_idx = 0; + auto next_arg = [&]() { + return arg_idx < builtin->Args().Length() ? builtin->Args()[arg_idx++] : nullptr; + }; + + auto* texture = next_arg(); + auto* coords = next_arg(); + auto* texture_ty = texture->Type()->As(); + + // Append the array index to the coordinates if provided. + auto* array_idx = + texture_ty->GetArrayed() == type::Arrayed::kArrayed ? next_arg() : nullptr; + if (array_idx) { + coords = AppendArrayIndex(coords, array_idx, builtin); + } + + // Start building the argument list for the builtin. + // The first two operands are always the texture and then the coordinates. + Vector builtin_args; + builtin_args.Push(texture); + builtin_args.Push(coords); + + // Add the optional image operands, if any. + ImageOperands operands; + if (texture_ty->GetMultisampled() == type::Multisampled::kMultisampled) { + operands.sample = next_arg(); + } else { + operands.lod = next_arg(); + } + AppendImageOperands(operands, builtin_args, builtin, /* requires_float_lod */ false); + + // Call the builtin. + // The result is always a vec4 in SPIR-V. + auto* result_ty = builtin->Result()->Type(); + bool expects_scalar_result = result_ty->Is(); + if (expects_scalar_result) { + result_ty = ty.vec4(result_ty); + } + auto kind = texture_ty->GetSampled() == type::Sampled::kSamplingCompatible + ? spirv::BuiltinFn::kImageFetch + : spirv::BuiltinFn::kImageRead; + core::ir::Instruction* result = + b.Call(result_ty, kind, std::move(builtin_args)); + result->InsertBefore(builtin); + + // If we are expecting a scalar result, extract the first component. + if (expects_scalar_result) { + result = b.Access(ty.f32(), result, 0_u); + result->InsertBefore(builtin); + } + + result->SetResult(builtin->DetachResult()); + builtin->Destroy(); + } + + /// Handle a textureStore() builtin. + /// @param builtin the builtin call instruction + void TextureStore(core::ir::CoreBuiltinCall* builtin) { + // Helper to get the next argument from the call, or nullptr if there are no more arguments. + uint32_t arg_idx = 0; + auto next_arg = [&]() { + return arg_idx < builtin->Args().Length() ? builtin->Args()[arg_idx++] : nullptr; + }; + + auto* texture = next_arg(); + auto* coords = next_arg(); + auto* texture_ty = texture->Type()->As(); + + // Append the array index to the coordinates if provided. + auto* array_idx = + texture_ty->GetArrayed() == type::Arrayed::kArrayed ? next_arg() : nullptr; + if (array_idx) { + coords = AppendArrayIndex(coords, array_idx, builtin); + } + + auto* texel = next_arg(); + + // Start building the argument list for the function. + // The first two operands are always the texture and then the coordinates. + Vector function_args; + function_args.Push(texture); + function_args.Push(coords); + function_args.Push(texel); + + ImageOperands operands; + AppendImageOperands(operands, function_args, builtin, /* requires_float_lod */ false); + + // Call the function. + auto* texture_call = b.Call( + ty.void_(), spirv::BuiltinFn::kImageWrite, std::move(function_args)); + texture_call->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle a textureDimensions() builtin. + /// @param builtin the builtin call instruction + void TextureDimensions(core::ir::CoreBuiltinCall* builtin) { + // Helper to get the next argument from the call, or nullptr if there are no more arguments. + uint32_t arg_idx = 0; + auto next_arg = [&]() { + return arg_idx < builtin->Args().Length() ? builtin->Args()[arg_idx++] : nullptr; + }; + + auto* texture = next_arg(); + auto* texture_ty = texture->Type()->As(); + + Vector function_args; + function_args.Push(texture); + + // Determine which SPIR-V function to use, and add the Lod argument if needed. + enum spirv::BuiltinFn function; + if (texture_ty->GetMultisampled() == type::Multisampled::kMultisampled || + texture_ty->GetTexelFormat() != core::TexelFormat::kUndefined) { + function = spirv::BuiltinFn::kImageQuerySize; + } else { + function = spirv::BuiltinFn::kImageQuerySizeLod; + if (auto* lod = next_arg()) { + function_args.Push(lod); + } else { + // Lod wasn't explicit, so assume 0. + function_args.Push(b.Constant(0_u)); + } + } + + // Add an extra component to the result vector for arrayed textures. + auto* result_ty = builtin->Result()->Type(); + bool is_arrayed = texture_ty->GetArrayed() == type::Arrayed::kArrayed; + if (is_arrayed) { + auto* vec = result_ty->As(); + result_ty = ty.vec(vec->Type(), vec->Width() + 1); + } + + // Call the function. + core::ir::Instruction* result = b.CallExplicit( + result_ty, function, Vector{ty.u32()}, std::move(function_args)); + result->InsertBefore(builtin); + + // Swizzle the first two components from the result for arrayed textures. + if (is_arrayed) { + result = b.Swizzle(builtin->Result()->Type(), result, {0, 1}); + result->InsertBefore(builtin); + } + + result->SetResult(builtin->DetachResult()); + builtin->Destroy(); + } + + /// Handle a textureNumLevels() builtin. + /// @param builtin the builtin call instruction + void TextureNumLevels(core::ir::CoreBuiltinCall* builtin) { + auto args = builtin->Args(); + + b.InsertBefore(builtin, [&] { + // Call the function. + auto* res_ty = builtin->Result()->Type(); + b.CallExplicitWithResult(builtin->DetachResult(), + spirv::BuiltinFn::kImageQueryLevels, + Vector{res_ty}, Vector{args[0]}); + }); + builtin->Destroy(); + } + + /// Handle a textureNumSamples() builtin. + /// @param builtin the builtin call instruction + void TextureNumSamples(core::ir::CoreBuiltinCall* builtin) { + auto args = builtin->Args(); + + b.InsertBefore(builtin, [&] { + // Call the function. + auto* res_ty = builtin->Result()->Type(); + b.CallExplicitWithResult(builtin->DetachResult(), + spirv::BuiltinFn::kImageQuerySamples, + Vector{res_ty}, Vector{args[0]}); + }); + builtin->Destroy(); + } + + /// Handle a textureNumLayers() builtin. + /// @param builtin the builtin call instruction + void TextureNumLayers(core::ir::CoreBuiltinCall* builtin) { + auto* texture = builtin->Args()[0]; + auto* texture_ty = texture->Type()->As(); + + Vector function_args; + function_args.Push(texture); + + // Determine which SPIR-V function to use, and add the Lod argument if needed. + enum spirv::BuiltinFn function; + if (texture_ty->GetMultisampled() == type::Multisampled::kMultisampled || + texture_ty->GetTexelFormat() != core::TexelFormat::kUndefined) { + function = spirv::BuiltinFn::kImageQuerySize; + } else { + function = spirv::BuiltinFn::kImageQuerySizeLod; + function_args.Push(b.Constant(0_u)); + } + + // Call the function. + auto* texture_call = b.CallExplicit( + ty.vec3u(), function, Vector{ty.u32()}, std::move(function_args)); + texture_call->InsertBefore(builtin); + + // Extract the third component to get the number of array layers. + auto* extract = b.AccessWithResult(builtin->DetachResult(), texture_call->Result(), 2_u); + extract->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Scalarize the vector form of a `quantizeToF16()` builtin. + /// See crbug.com/tint/1741. + /// @param builtin the builtin call instruction + void QuantizeToF16Vec(core::ir::CoreBuiltinCall* builtin) { + auto* arg = builtin->Args()[0]; + auto* vec = arg->Type()->As(); + TINT_IR_ASSERT(ir, vec); + + // Replace the builtin call with a call to the spirv.dot intrinsic. + Vector args; + for (uint32_t i = 0; i < vec->Width(); i++) { + auto* el = b.Access(ty.f32(), arg, u32(i)); + auto* scalar_call = b.Call(ty.f32(), core::BuiltinFn::kQuantizeToF16, el); + args.Push(scalar_call->Result()); + el->InsertBefore(builtin); + scalar_call->InsertBefore(builtin); + } + auto* construct = b.ConstructWithResult(builtin->DetachResult(), std::move(args)); + construct->InsertBefore(builtin); + builtin->Destroy(); + } + + /// Handle an inputAttachmentLoad() builtin. + /// @param builtin the builtin call instruction + void InputAttachmentLoad(core::ir::CoreBuiltinCall* builtin) { + TINT_IR_ASSERT(ir, builtin->Args().Length() == 1); + + auto* texture = builtin->Args()[0]; + // coords for input_attachment are always (0, 0) + auto* coords = b.Composite(ty.vec2i(), 0_i, 0_i); + + // Start building the argument list for the builtin. + // The first two operands are always the texture and then the coordinates. + Vector builtin_args; + builtin_args.Push(texture); + builtin_args.Push(coords); + + // Call the builtin. + // The result is always a vec4 in SPIR-V. + auto* result_ty = builtin->Result()->Type(); + TINT_IR_ASSERT(ir, result_ty->Is()); + + core::ir::Instruction* result = b.Call( + result_ty, spirv::BuiltinFn::kImageRead, std::move(builtin_args)); + result->InsertBefore(builtin); + + result->SetResult(builtin->DetachResult()); + builtin->Destroy(); + } + + /// Handles SubgroupShuffle(), SubgroupShuffleDown(), SubgroupShuffleUp(), SubgroupShuffleXor() + /// builtins. + /// @param builtin the builtin call instruction + void SubgroupShuffle(core::ir::CoreBuiltinCall* builtin, bool clamp_subgroup_shuffle) { + TINT_IR_ASSERT(ir, builtin->Args().Length() == 2); + // The second argument is either 'id' , 'delta', or 'mask'. + // All must be bound by [0, 128) + auto* arg2 = builtin->Args()[1]; + // arg2 must be an unsigned integer scalar, so bitcast if necessary. + if (arg2->Type()->IsSignedIntegerScalar()) { + auto* cast = b.Bitcast(ty.u32(), arg2); + cast->InsertBefore(builtin); + builtin->SetArg(1, cast->Result()); + } + + /// Polyfill a `subgroupShuffleX` builtin call with one that has clamped the arg2 param + if (clamp_subgroup_shuffle) { + auto* shuffle_id = builtin->Args()[1]; + auto* mask_max_subgroup_size = + b.Constant(core::u32(tint::internal_limits::kMaxSubgroupSize - 1)); + b.InsertBefore(builtin, [&] { + auto* clamp_via_masking_and = b.And(shuffle_id, mask_max_subgroup_size); + builtin->SetArg(1, clamp_via_masking_and->Result()); + }); + } + } + + /// Handle a SubgroupBroadcast() builtin. + /// @param builtin the builtin call instruction + void SubgroupBroadcast(core::ir::CoreBuiltinCall* builtin) { + TINT_IR_ASSERT(ir, builtin->Args().Length() == 2); + auto* id = builtin->Args()[1]; + TINT_IR_ASSERT(ir, id->Is()); + + // For const signed int IDs, compile-time convert to u32 to maintain constness. + if (id->Type()->IsSignedIntegerScalar()) { + builtin->SetArg(1, b.Constant(id->As()->Value()->ValueAs())); + } + } + + /// Handle a QuadBroadcast() builtin. + /// @param builtin the builtin call instruction + void QuadBroadcast(core::ir::CoreBuiltinCall* builtin) { + TINT_IR_ASSERT(ir, builtin->Args().Length() == 2); + auto* id = builtin->Args()[1]; + TINT_IR_ASSERT(ir, id->Is()); + + // For const signed int IDs, compile-time convert to u32 to maintain constness. + if (id->Type()->IsSignedIntegerScalar()) { + builtin->SetArg(1, b.Constant(id->As()->Value()->ValueAs())); + } + } + + /// Replace a subgroupMatrixLoad builtin. + /// @param builtin the builtin call instruction + void SubgroupMatrixLoad(core::ir::CoreBuiltinCall* builtin) { + b.InsertBefore(builtin, [&] { + auto* result_ty = builtin->Result()->Type()->As(); + auto* p = builtin->Args()[0]; + auto* offset = builtin->Args()[1]; + auto* col_major = builtin->Args()[2]->As(); + auto* stride = builtin->Args()[3]; + + auto* ptr = p->Type()->As(); + auto* arr = ptr->StoreType()->As(); + + auto* layout = b.Constant(u32(col_major->Value()->ValueAs() + ? SpvCooperativeMatrixLayoutColumnMajorKHR + : SpvCooperativeMatrixLayoutRowMajorKHR)); + auto* memory_operand = Literal(u32(SpvMemoryAccessNonPrivatePointerMask)); + + // In SPIR-V `stride` and `offset` are related to the type of the input pointer, while + // in WGSL they both mean the number of elements. When the subgroup matrix element type + // is `i8` or `u8`, and the input array type is `i32` or `u32`, we need to convert the + // `stride` and `offset` in WGSL into the ones in SPIR-V by dividing them with 4. + core::ir::Value* applied_stride = nullptr; + core::ir::Value* applied_offset = nullptr; + if (result_ty->Type()->Size() == 1u && arr->ElemType()->Size() == 4u) { + auto* applied_stride_binary = + b.Binary(core::BinaryOp::kDivide, stride->Type(), stride, u32(4)); + applied_stride = applied_stride_binary->Result(); + + auto* applied_offset_binary = + b.Binary(core::BinaryOp::kDivide, offset->Type(), offset, u32(4)); + applied_offset = applied_offset_binary->Result(); + } else { + applied_stride = stride; + applied_offset = offset; + } + + // Make a pointer to the first element of the array that we will load from. + auto* elem_ptr = ty.ptr(ptr->AddressSpace(), arr->ElemType(), ptr->Access()); + auto* src = b.Access(elem_ptr, p, applied_offset); + + auto* call = b.CallWithResult( + builtin->DetachResult(), spirv::BuiltinFn::kCooperativeMatrixLoad, src, layout, + applied_stride, memory_operand); + call->SetExplicitTemplateParams(Vector{result_ty}); + }); + builtin->Destroy(); + } + + /// Replace a subgroupMatrixStore builtin. + /// @param builtin the builtin call instruction + void SubgroupMatrixStore(core::ir::CoreBuiltinCall* builtin) { + b.InsertBefore(builtin, [&] { + auto* p = builtin->Args()[0]; + auto* offset = builtin->Args()[1]; + auto* value = builtin->Args()[2]; + auto* value_type = value->Type()->As(); + + auto* col_major = builtin->Args()[3]->As(); + auto* stride = builtin->Args()[4]; + + auto* ptr = p->Type()->As(); + auto* arr = ptr->StoreType()->As(); + + // In SPIR-V `stride` and `offset` are related to the type of the input pointer, while + // in WGSL they both mean the number of elements. When the subgroup matrix element type + // is `i8` or `u8`, and the input array type is `i32` or `u32`, we need to convert the + // `stride` and `offset` in WGSL into the ones in SPIR-V by dividing them with 4. + core::ir::Value* applied_stride = nullptr; + core::ir::Value* applied_offset = nullptr; + if (value_type->Type()->Size() == 1u && arr->ElemType()->Size() == 4u) { + auto* applied_stride_binary = + b.Binary(core::BinaryOp::kDivide, stride->Type(), stride, u32(4)); + applied_stride = applied_stride_binary->Result(); + + auto* applied_offset_binary = + b.Binary(core::BinaryOp::kDivide, offset->Type(), offset, u32(4)); + applied_offset = applied_offset_binary->Result(); + } else { + applied_stride = stride; + applied_offset = offset; + } + + // Make a pointer to the first element of the array that we will write to. + auto* elem_ptr = ty.ptr(ptr->AddressSpace(), arr->ElemType(), ptr->Access()); + auto* dst = b.Access(elem_ptr, p, applied_offset); + + auto* layout = b.Constant(u32(col_major->Value()->ValueAs() + ? SpvCooperativeMatrixLayoutColumnMajorKHR + : SpvCooperativeMatrixLayoutRowMajorKHR)); + auto* memory_operand = Literal(u32(SpvMemoryAccessNonPrivatePointerMask)); + + b.Call(ty.void_(), spirv::BuiltinFn::kCooperativeMatrixStore, + dst, value, layout, applied_stride, memory_operand); + }); + builtin->Destroy(); + } + + /// Generate the literal operand for a subgroup matrix multiply instruction. + /// @param input_ty the type of the input matrices + /// @param result_ty the type of the result matrix + /// @returns the literal operands + ir::LiteralOperand* SubgroupMatrixMultiplyOperands( + const core::type::SubgroupMatrix* input_ty, + const core::type::SubgroupMatrix* result_ty) { + uint32_t operands = SpvCooperativeMatrixOperandsMaskNone; + if (input_ty->Type()->IsSignedIntegerScalar()) { + operands |= SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRMask; + operands |= SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRMask; + } + if (result_ty->Type()->IsSignedIntegerScalar()) { + operands |= SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRMask; + operands |= SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask; + } + return Literal(u32(operands)); + } + + /// Replace a subgroupMatrixMultiply builtin. + /// @param builtin the builtin call instruction + void SubgroupMatrixMultiply(core::ir::CoreBuiltinCall* builtin) { + b.InsertBefore(builtin, [&] { + // SPIR-V only provides a multiply-accumulate instruction, so construct a zero-valued + // matrix to accumulate into. + auto* result_ty = builtin->Result()->Type()->As(); + auto* left = builtin->Args()[0]; + auto* right = builtin->Args()[1]; + auto* acc = b.Construct(result_ty); + auto* operands = SubgroupMatrixMultiplyOperands( + left->Type()->As(), result_ty); + b.CallWithResult(builtin->DetachResult(), + spirv::BuiltinFn::kCooperativeMatrixMulAdd, + left, right, acc, operands); + }); + builtin->Destroy(); + } + + /// Replace a subgroupMatrixMultiplyAccumulate builtin. + /// @param builtin the builtin call instruction + void SubgroupMatrixMultiplyAccumulate(core::ir::CoreBuiltinCall* builtin) { + b.InsertBefore(builtin, [&] { + auto* left = builtin->Args()[0]; + auto* right = builtin->Args()[1]; + auto* acc = builtin->Args()[2]; + auto* operands = + SubgroupMatrixMultiplyOperands(left->Type()->As(), + acc->Type()->As()); + b.CallWithResult(builtin->DetachResult(), + spirv::BuiltinFn::kCooperativeMatrixMulAdd, + left, right, acc, operands); + }); + builtin->Destroy(); + } + + /// Replace a subgroupMatrixScalar builtin. + /// @param builtin the builtin call instruction + /// @param op the operation to perform + void SubgroupMatrixScalar(core::ir::CoreBuiltinCall* builtin, core::BinaryOp op) { + b.InsertBefore(builtin, [&] { + auto* mat = builtin->Args()[0]; + auto* scalar = builtin->Args()[1]; + + auto* sm_ty = mat->Type()->As(); + if (sm_ty->Type()->Is()) { + scalar = b.CallExplicit( + ty.i8(), spirv::BuiltinFn::kSConvert, Vector{ty.i8()}, + b.Clamp(scalar, -128_i, 127_i)) + ->Result(); + } else if (sm_ty->Type()->Is()) { + scalar = b.CallExplicit( + ty.u8(), spirv::BuiltinFn::kUConvert, Vector{ty.u8()}, + b.Clamp(scalar, 0_u, 255_u)) + ->Result(); + } + + auto* scalar_mat = b.Construct(sm_ty, scalar); + b.BinaryWithResult(builtin->DetachResult(), op, mat, scalar_mat); + }); + builtin->Destroy(); + } +}; + +} // namespace + +Result BuiltinPolyfill(core::ir::Module& ir, PolyfillConfig config) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.BuiltinPolyfill", + core::ir::Capabilities{ + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, + })); + + State{ir, config}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.h new file mode 100644 index 000000000..197e212e3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/builtin_polyfill.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_BUILTIN_POLYFILL_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_BUILTIN_POLYFILL_H_ + +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +class Texture; +} // namespace tint::core::ir + +namespace tint::spirv::writer::raise { + +struct PolyfillConfig { + bool use_vulkan_memory_model = false; + SpvVersion version = SpvVersion::kSpv13; + bool subgroup_shuffle_clamped = false; + bool texture_sample_compare_depth_cube_array = false; +}; + +/// BuiltinPolyfill is a transform that replaces calls to builtins with polyfills and calls to +/// SPIR-V backend intrinsic functions. It replaces core types with SPIR-V specific types at the +/// same time to produce valid IR (e.g. texture types to spirv.image). +/// @param module the module to transform +/// @param config the configuration used in the polyfill function +/// @returns success or failure +Result BuiltinPolyfill(core::ir::Module& module, PolyfillConfig config); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_BUILTIN_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.cc new file mode 100644 index 000000000..50d9f1008 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.cc @@ -0,0 +1,164 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/case_switch_to_if_else.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/control_instruction.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/traverse.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/unary_op.h" +#include "src/tint/lang/wgsl/ast/case_selector.h" +#include "src/tint/utils/containers/transform.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +const core::ir::Capabilities kCaseSwitchToIfElseCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, +}; + +/// PIMPL state for the transform, for a single function. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the IR + void Process() { + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* s = inst->As()) { + // Even though the switch param could be signed we use u32 as that is likely the + // internal representation of the compiler. + uint32_t max_sel_case = 0u; + uint32_t min_sel_case = std::numeric_limits().max(); + for (auto& c : s->Cases()) { + for (auto& sel : c.selectors) { + if (!sel.IsDefault() && sel.val && sel.val->Value()) { + auto val = sel.val->Value()->ValueAs().value; + max_sel_case = std::max(max_sel_case, val); + min_sel_case = std::min(min_sel_case, val); + } + } + } + + // Our concern is around handling of signed range calculations (vs unsigned). Any + // range that gets close we will polyfill. + const uint32_t kSignedRangeLimit = + static_cast(std::numeric_limits().max() - 1); + if ((max_sel_case - min_sel_case) >= kSignedRangeLimit) { + worklist.Push(s); + } + } + } + + for (auto* s : worklist) { + auto* switch_cond = s->Condition(); + Vector conditions; + core::ir::Switch::Case* default_case = nullptr; + // We take the cases here because we're going to attach the case block to an `if` + // statement and the switch will now be replaced with a single default case block. + auto cases = s->TakeCases(); + auto* def = b.DefaultCase(s); + b.Append(def, [&] { + for (auto& c : cases) { + // Default block is required by spec. It will need to be treated special. + // It is possible that default case will also have non default selectors. + // These additional selectors are superfluous as they will just form one + // default. + bool found_default = false; + for (auto& sel : c.selectors) { + if (sel.IsDefault()) { + default_case = &c; + found_default = true; + break; + } + } + if (found_default) { + continue; + } + + core::ir::Value* case_cond = nullptr; + for (auto& sel : c.selectors) { + auto* curr_selector = b.Equal(switch_cond, sel.val->As()); + if (case_cond) { + case_cond = b.Or(curr_selector, case_cond)->Result(); + } else { + case_cond = curr_selector->Result(); + } + } + conditions.Push(case_cond); + auto* if_cond = b.If(case_cond); + if_cond->SetTrue(c.block); + } + + TINT_ASSERT(default_case); + // Special handling required for default case. All non-default cases have exited the + // switch by this point so the only possibility that remains is the default. + auto* if_cond = b.If(b.Constant(true)); + if_cond->SetTrue(default_case->block); + }); + + b.Append(s->Cases()[0].block, [&] { b.Unreachable(); }); + } + } +}; + +} // namespace + +Result CaseSwitchToIfElse(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.CaseSwitchToIfElse", kCaseSwitchToIfElseCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.h new file mode 100644 index 000000000..ae846ffc9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/case_switch_to_if_else.h @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_CASE_SWITCH_TO_IF_ELSE_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_CASE_SWITCH_TO_IF_ELSE_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +/// CaseSwitchToIfElse is a transform that converts case switch statements to a series of if +/// statements with the default being an emulated else condition. +/// @param module the module to transform +/// @returns success or failure +Result CaseSwitchToIfElse(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_CASE_SWITCH_TO_IF_ELSE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc new file mode 100644 index 000000000..9e0d1dfb8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc @@ -0,0 +1,146 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/expand_implicit_splats.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/builtin_fn.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" + +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// Process the module. + void Process() { + // Find the instructions that use implicit splats and modify or replace them. + for (auto* inst : ir.Instructions()) { + if (auto* construct = inst->As()) { + // A vector constructor with a single scalar argument needs to be modified to + // replicate the argument N times. + auto* vec = construct->Result()->Type()->As(); + if ((vec != nullptr) && // + construct->Args().Length() == 1 && + construct->Args()[0]->Type()->Is()) { + for (uint32_t i = 1; i < vec->Width(); i++) { + construct->AppendArg(construct->Args()[0]); + } + } + } else if (auto* binary = inst->As()) { + // A binary instruction that mixes vector and scalar operands needs to have the + // scalar operand replaced with an explicit vector constructor. + if (binary->Result()->Type()->Is()) { + if (binary->LHS()->Type()->Is() || + binary->RHS()->Type()->Is()) { + ExpandBinary(binary); + } + } + } else if (auto* builtin = inst->As()) { + // A mix builtin call that mixes vector and scalar operands needs to have the scalar + // operand replaced with an explicit vector constructor. + if (builtin->Func() == core::BuiltinFn::kMix) { + if (builtin->Result()->Type()->Is()) { + if (builtin->Args()[2]->Type()->Is()) { + ExpandOperand(builtin, + core::ir::CoreBuiltinCall::kArgsOperandOffset + 2); + } + } + } + } + } + } + + /// Helper to expand a scalar operand of an instruction by replacing it with an explicitly + /// constructed vector that matches the result type. + void ExpandOperand(core::ir::Instruction* inst, size_t operand_idx) { + auto* vec = inst->Result()->Type()->As(); + + Vector args; + args.Resize(vec->Width(), inst->Operands()[operand_idx]); + + auto* construct = b.Construct(vec, std::move(args)); + construct->InsertBefore(inst); + inst->SetOperand(operand_idx, construct->Result()); + } + + /// Replace scalar operands to binary instructions that produce vectors. + /// @param binary the binary instruction to modify + void ExpandBinary(core::ir::Binary* binary) { + auto* result_ty = binary->Result()->Type(); + if (result_ty->IsFloatVector() && binary->Op() == core::BinaryOp::kMultiply) { + // Use OpVectorTimesScalar for floating point multiply. + auto* vts = b.CallWithResult( + binary->DetachResult(), spirv::BuiltinFn::kVectorTimesScalar); + if (binary->LHS()->Type()->Is()) { + vts->AppendArg(binary->RHS()); + vts->AppendArg(binary->LHS()); + } else { + vts->AppendArg(binary->LHS()); + vts->AppendArg(binary->RHS()); + } + if (auto name = ir.NameOf(binary)) { + ir.SetName(vts->Result(), name); + } + binary->ReplaceWith(vts); + binary->Destroy(); + } else { + // Expand the scalar argument into an explicitly constructed vector. + if (binary->LHS()->Type()->Is()) { + ExpandOperand(binary, core::ir::CoreBinary::kLhsOperandOffset); + } else if (binary->RHS()->Type()->Is()) { + ExpandOperand(binary, core::ir::CoreBinary::kRhsOperandOffset); + } + } + } +}; + +} // namespace + +Result ExpandImplicitSplats(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.ExpandImplicitSplats", + kExpandImplicitSplatsCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h new file mode 100644 index 000000000..6cafd5e90 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_EXPAND_IMPLICIT_SPLATS_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_EXPAND_IMPLICIT_SPLATS_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kExpandImplicitSplatsCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, +}; + +/// ExpandImplicitSplats is a transform that expands implicit vector splat operands in construct +/// instructions and binary instructions where not supported by SPIR-V. +/// @param module the module to transform +/// @returns success or failure +Result ExpandImplicitSplats(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_EXPAND_IMPLICIT_SPLATS_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.cc new file mode 100644 index 000000000..31b1370ad --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.cc @@ -0,0 +1,381 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/lang/spirv/ir/copy_logical.h" +#include "src/tint/lang/spirv/type/explicit_layout_array.h" +#include "src/tint/lang/spirv/writer/common/options.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The SPIR-V binary version. + SpvVersion version; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The symbol table. + SymbolTable& sym{ir.symbols}; + + /// The array and structure types that must be emitted without explicit layout decorations. + Hashset must_emit_without_explicit_layout{}; + + /// A map from original array/struct type to the explicitly laid out version. + Hashmap explicit_type_map{}; + + /// Helper functions for converting to and from explicitly laid out types. + Hashmap conversion_helpers{}; + + /// Process the module. + void Process() { + // Record arrays and structures that must not have explicit layout decorations, as well as + // variables in address space that must have explicit layout decorations. + Vector vars_requiring_explicit_layout; + for (auto* inst : ir.Instructions()) { + auto* var = inst->As(); + if (!var) { + continue; + } + + auto* ptr = var->Result()->Type()->As(); + switch (ptr->AddressSpace()) { + case core::AddressSpace::kImmediate: + case core::AddressSpace::kStorage: + case core::AddressSpace::kUniform: + vars_requiring_explicit_layout.Push(var); + break; + + case core::AddressSpace::kFunction: + case core::AddressSpace::kPrivate: + // In SPIR-V 1.4 and earlier, Vulkan allowed explicit layout decorations. + if (version > SpvVersion::kSpv14) { + RecordTypesThatMustNotHaveExplicitLayout(ptr); + } + break; + + case core::AddressSpace::kWorkgroup: + case core::AddressSpace::kHandle: + case core::AddressSpace::kPixelLocal: + case core::AddressSpace::kIn: + case core::AddressSpace::kOut: + RecordTypesThatMustNotHaveExplicitLayout(ptr); + break; + + case core::AddressSpace::kUndefined: + break; + } + } + + // If a variable that requires explicit layout decorations is using types that will be + // emitted without explicit layout decorations, we need to rewrite its store type and + // introduce element-wise copies when loading and storing those types. + for (auto* var : vars_requiring_explicit_layout) { + UpdatePointerType(var->Result()); + } + } + + /// Add all array and structure types nested in @p ptr to the set of types that must be emitted + /// without explicit layout decorations. + /// @param ptr the pointer type whose store type will be recorded + void RecordTypesThatMustNotHaveExplicitLayout(const core::type::Pointer* ptr) { + // Look for arrays and structures at any nesting depth of this type. + Vector type_queue; + type_queue.Push(ptr->StoreType()); + while (!type_queue.IsEmpty()) { + auto* next = type_queue.Pop(); + if (auto* str = next->As()) { + // Record this structure and then check its members if we haven't seen it before. + if (must_emit_without_explicit_layout.Add(str)) { + for (auto* member : str->Members()) { + type_queue.Push(member->Type()); + } + } + } else if (auto* arr = next->As()) { + // Record this array and then check its element type if we haven't seen it before. + if (must_emit_without_explicit_layout.Add(arr)) { + type_queue.Push(arr->ElemType()); + } + } + } + } + + /// Recursively fork a type to produce an identical version that will have explicit layout + /// decorations, if the original is going to be emitted without explicit layout decorations. + /// @param type the original type to fork + /// @returns the forked type, or `nullptr` if forking was not necessary + const core::type::Type* GetForkedType(const core::type::Type* type) { + return explicit_type_map.GetOrAdd(type, [&]() -> const core::type::Type* { + if (auto* str = type->As()) { + return ForkStructIfNeeded(str); + } + if (auto* arr = type->As()) { + return ForkArray(arr); + } + + // Any other type is safe to use unchanged, as they do not have layout decorations. + return nullptr; + }); + } + + /// Recursively fork a structure type to produce an identical version that will have explicit + /// layout decorations, if the original is going to be emitted without explicit layout + /// decorations. + /// @param original_struct the original structure type to fork + /// @returns the forked struct type, or `nullptr` if forking was not necessary + const core::type::Struct* ForkStructIfNeeded(const core::type::Struct* original_struct) { + // Fork each member type as necessary. + bool members_were_forked = false; + Vector new_members; + for (auto* member : original_struct->Members()) { + auto* new_member_type = GetForkedType(member->Type()); + if (!new_member_type) { + // The member type was not forked, so just use the original member type. + new_member_type = member->Type(); + } else { + members_were_forked = true; + } + auto index = static_cast(new_members.Length()); + new_members.Push(ty.Get( + member->Name(), new_member_type, index, member->Offset(), member->Align(), + member->Size(), core::IOAttributes{})); + } + + // If no members were forked and the struct itself is not shared with other address spaces, + // then the original struct can safely be reused. + if (!must_emit_without_explicit_layout.Contains(original_struct) && !members_were_forked) { + // TODO(crbug.com/tint/745): Remove the const_cast. + const_cast(original_struct) + ->SetStructFlag(core::type::kExplicitLayout); + return nullptr; + } + + // Create a new struct with the rewritten members. + auto name = sym.New(original_struct->Name().Name() + "_tint_explicit_layout"); + auto* new_str = + ty.Get(name, std::move(new_members), original_struct->Size()); + new_str->SetStructFlag(core::type::kExplicitLayout); + for (auto flag : original_struct->StructFlags()) { + new_str->SetStructFlag(flag); + } + return new_str; + } + + /// Recursively fork an array type to produce an identical version that will have explicit + /// layout decorations when emitted as SPIR-V. + /// @param original_array the original array type to fork + /// @returns the forked array type + const type::ExplicitLayoutArray* ForkArray(const core::type::Array* original_array) { + auto* new_element_type = GetForkedType(original_array->ElemType()); + if (!new_element_type) { + // The element type was not forked, so just use the original element type. + new_element_type = original_array->ElemType(); + } + + uint32_t stride = original_array->ImplicitStride(); + if (auto* ex = original_array->As()) { + stride = ex->Stride(); + } + + return ty.Get(new_element_type, // + original_array->Count(), // + original_array->Size(), // + stride); + } + + /// Update the store type of an instruction result to use the forked version if needed. + /// Replace any uses of the instruction to take the new type into account. + /// @param result the instruction result to update + void UpdatePointerType(core::ir::InstructionResult* result) { + // Check if the store type needs to be forked. + auto* ptr = result->Type()->As(); + auto* forked_type = GetForkedType(ptr->StoreType()); + if (!forked_type) { + return; + } + + // Update the store type to the forked type that will have an explicit layout. + auto* new_ptr = ty.ptr(ptr->AddressSpace(), forked_type, ptr->Access()); + result->SetType(new_ptr); + + // Update any uses of the instruction to take the new type into account. + // This may introduce manual copies to convert between the forked type and the original. + result->ForEachUseSorted([&](core::ir::Usage use) { // + ReplaceForkedPointerUse(use); + }); + } + + /// Replace a use of an instruction that produces a pointer to a type that has been forked. + /// @param use the use of the forked pointer + void ReplaceForkedPointerUse(core::ir::Usage use) { + tint::Switch( + use.instruction, // + [&](core::ir::Access* access) { + // If the access produces a pointer to a type that has been forked, we need to + // update the result type and then recurse into its uses. + UpdatePointerType(access->Result()); + }, + [&](ir::BuiltinCall* call) { + // The only builtin function that takes an array pointer is arrayLength(). + // No change is needed, as it will operate on the explicitly laid out array type. + TINT_IR_ASSERT(ir, call->Func() == BuiltinFn::kArrayLength); + }, + [&](core::ir::Let* let) { + // A let usage will propagate the pointer to a type that has been forked, so we need + // to update the result type and then recurse into its uses. + UpdatePointerType(let->Result()); + }, + [&](core::ir::Load* load) { + b.InsertAfter(load, [&] { + // Change the load instruction to produce the forked type, and then convert the + // result of the load to the original type. + auto* original_type = load->Result()->Type(); + auto* forked_load = b.InstructionResult(load->From()->Type()->UnwrapPtr()); + auto* converted = ConvertIfNeeded(original_type, forked_load); + load->Result()->ReplaceAllUsesWith(converted); + load->SetResult(forked_load); + }); + }, + [&](core::ir::Store* store) { + b.InsertBefore(store, [&] { + // Convert the `from` operand of the store instruction to the forked type. + auto* forked_type = store->To()->Type()->UnwrapPtr(); + auto* converted = ConvertIfNeeded(forked_type, store->From()); + store->SetOperand(core::ir::Store::kFromOperandOffset, converted); + }); + }, + TINT_ICE_ON_NO_MATCH); + } + + /// Convert a value to/from the explicitly laid out type, if necessary. + /// @param src the value to convert + /// @param dst_type the type to convert it to + /// @returns the converted value + core::ir::Value* ConvertIfNeeded(const core::type::Type* dst_type, core::ir::Value* src) { + // If the source type is already the same as the destination type, there is nothing to do. + auto* src_type = src->Type(); + if (src_type == dst_type) { + return src; + } + + // In SPIR-V 1.4 or later, use OpCopyLogical instead of member-wise copying. + if (version >= SpvVersion::kSpv14) { + auto* copy = + ir.CreateInstruction(b.InstructionResult(dst_type), src); + return b.Append(copy)->Result(); + } + // Create a helper function to do the conversion. + auto* helper = conversion_helpers.GetOrAdd(src_type, [&] { + auto* param = b.FunctionParam("tint_source", src_type); + auto* func = b.Function("tint_convert_explicit_layout", dst_type); + func->AppendParam(param); + b.Append(func->Block(), [&] { + if (auto* src_struct = src_type->As()) { + auto* dst_struct = dst_type->As(); + b.Return(func, ConvertStruct(src_struct, dst_struct, param)); + } else if (auto* src_arr = src_type->As()) { + auto* dst_arr = dst_type->As(); + b.Return(func, ConvertArray(src_arr, dst_arr, param)); + } else { + TINT_IR_UNREACHABLE(ir); + } + }); + return func; + }); + return b.Call(helper, src)->Result(); + } + + /// Recursively convert a struct type to/from the explicitly laid out version. + core::ir::Value* ConvertStruct(const core::type::Struct* src_struct, + const core::type::Struct* dst_struct, + core::ir::Value* input) { + // Convert each member separately and the reconstruct the target struct. + Vector construct_args; + for (uint32_t i = 0; i < dst_struct->Members().Length(); i++) { + auto* src_member = src_struct->Members()[i]; + auto* dst_member = dst_struct->Members()[i]; + auto* extracted = b.Access(src_member->Type(), input, u32(i))->Result(); + auto* converted = ConvertIfNeeded(dst_member->Type(), extracted); + construct_args.Push(converted); + } + return b.Construct(dst_struct, std::move(construct_args))->Result(); + } + + /// Recursively convert an array type to/from the explicitly laid out version. + core::ir::Value* ConvertArray(const core::type::Array* src_array, + const core::type::Array* dst_array, + core::ir::Value* input) { + // Runtime-sized arrays will never be converted as you cannot load/store them, and + // pipeline-overrides will already have been substituted before this transform. + auto* count = src_array->Count()->As(); + TINT_IR_ASSERT(ir, count && count == dst_array->Count()); + + // Create a local variable to hold the converted result. + // Convert each element one at a time, writing into the local variable. + auto* result = b.Var(ty.ptr(dst_array)); + b.LoopRange(0_u, u32(count->value), 1_u, [&](core::ir::Value* idx) { + auto* extracted = b.Access(src_array->ElemType(), input, idx)->Result(); + auto* converted = ConvertIfNeeded(dst_array->ElemType(), extracted); + auto* dst_ptr = b.Access(ty.ptr(function, dst_array->ElemType()), result, idx); + b.Store(dst_ptr, converted); + }); + + return b.Load(result)->Result(); + } +}; + +} // namespace + +Result ForkExplicitLayoutTypes(core::ir::Module& ir, SpvVersion version) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.ForkExplicitLayoutTypes", + kForkExplicitLayoutTypesCapabilities)); + + State{ir, version}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.h new file mode 100644 index 000000000..0b2ff8a97 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.h @@ -0,0 +1,63 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_FORK_EXPLICIT_LAYOUT_TYPES_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_FORK_EXPLICIT_LAYOUT_TYPES_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} +namespace tint::spirv::writer { +enum class SpvVersion : uint32_t; +} + +namespace tint::spirv::writer::raise { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kForkExplicitLayoutTypesCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kLoosenValidationForShaderIO, + core::ir::Capability::kAllowPointSizeBuiltin, +}; + +/// ForkExplicitLayoutTypes is a transform that forks array and structures types that are shared +/// between address spaces that require explicit layout in SPIR-V and those that cannot have them. +/// +/// @param module the module to transform +/// @returns success or failure +Result ForkExplicitLayoutTypes(core::ir::Module& module, SpvVersion version); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_FORK_EXPLICIT_LAYOUT_TYPES_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc new file mode 100644 index 000000000..4f3a1fd7a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc @@ -0,0 +1,174 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h" + +#include + +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/spirv/ir/builtin_call.h" +#include "src/tint/utils/ice/ice.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// Process the module. + void Process() { + // Find and replace the instructions that need to be modified. + for (auto* inst : ir.Instructions()) { + if (auto* binary = inst->As()) { + if (binary->LHS()->Type()->Is() || + binary->RHS()->Type()->Is()) { + ReplaceBinary(binary); + } + } else if (auto* convert = inst->As()) { + if (convert->Result()->Type()->Is()) { + ReplaceConvert(convert); + } + } + } + } + + /// Replace a binary matrix arithmetic instruction. + /// @param binary the instruction to replace + void ReplaceBinary(core::ir::Binary* binary) { + auto* lhs = binary->LHS(); + auto* rhs = binary->RHS(); + auto* lhs_ty = lhs->Type(); + auto* rhs_ty = rhs->Type(); + auto* ty = binary->Result()->Type(); + + b.InsertBefore(binary, [&] { + // Helper to replace the instruction with a column-wise operation. + auto column_wise = [&](auto op) { + auto* mat = ty->As(); + Vector args; + for (uint32_t col = 0; col < mat->Columns(); col++) { + auto* lhs_col = b.Access(mat->ColumnType(), lhs, u32(col)); + auto* rhs_col = b.Access(mat->ColumnType(), rhs, u32(col)); + auto* add = b.Binary(op, mat->ColumnType(), lhs_col, rhs_col); + args.Push(add->Result()); + } + b.ConstructWithResult(binary->DetachResult(), std::move(args)); + }; + + switch (binary->Op()) { + case core::BinaryOp::kAdd: + column_wise(core::BinaryOp::kAdd); + break; + case core::BinaryOp::kSubtract: + column_wise(core::BinaryOp::kSubtract); + break; + case core::BinaryOp::kMultiply: + // Select the SPIR-V intrinsic that corresponds to the operation being + // performed. + if (lhs_ty->Is()) { + if (rhs_ty->Is()) { + b.CallWithResult( + binary->DetachResult(), spirv::BuiltinFn::kMatrixTimesScalar, lhs, + rhs); + } else if (rhs_ty->Is()) { + b.CallWithResult( + binary->DetachResult(), spirv::BuiltinFn::kMatrixTimesVector, lhs, + rhs); + } else if (rhs_ty->Is()) { + b.CallWithResult( + binary->DetachResult(), spirv::BuiltinFn::kMatrixTimesMatrix, lhs, + rhs); + } + } else { + if (lhs_ty->Is()) { + b.CallWithResult( + binary->DetachResult(), spirv::BuiltinFn::kMatrixTimesScalar, rhs, + lhs); + } else if (lhs_ty->Is()) { + b.CallWithResult( + binary->DetachResult(), spirv::BuiltinFn::kVectorTimesMatrix, lhs, + rhs); + } + } + break; + + default: + TINT_IR_UNREACHABLE(ir) << "unhandled matrix arithmetic instruction"; + } + }); + + binary->Destroy(); + } + + /// Replace a matrix convert instruction. + /// @param convert the instruction to replace + void ReplaceConvert(core::ir::Convert* convert) { + auto* arg = convert->Args()[core::ir::Convert::kValueOperandOffset]; + auto* in_mat = arg->Type()->As(); + auto* out_mat = convert->Result()->Type()->As(); + + b.InsertBefore(convert, [&] { + // Extract and convert each column separately. + Vector args; + for (uint32_t c = 0; c < out_mat->Columns(); c++) { + auto* col = b.Access(in_mat->ColumnType(), arg, u32(c)); + auto* new_col = b.Convert(out_mat->ColumnType(), col); + args.Push(new_col->Result()); + } + + // Reconstruct the result matrix from the converted columns. + b.ConstructWithResult(convert->DetachResult(), std::move(args)); + }); + + convert->Destroy(); + } +}; + +} // namespace + +Result HandleMatrixArithmetic(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.HandleMatrixArithmetic", + kHandleMatrixArithmeticCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h new file mode 100644 index 000000000..5ac41d8e7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_HANDLE_MATRIX_ARITHMETIC_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_HANDLE_MATRIX_ARITHMETIC_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +// The capabilities that the transform can support. +const core::ir::Capabilities kHandleMatrixArithmeticCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// HandleMatrixArithmetic is a transform that converts arithmetic instruction that use matrix into +/// SPIR-V intrinsics or polyfills. +/// @param module the module to transform +/// @returns success or failure +Result HandleMatrixArithmetic(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_HANDLE_MATRIX_ARITHMETIC_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.cc new file mode 100644 index 000000000..144e72b14 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.cc @@ -0,0 +1,102 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/binding_array.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + // Find the access instructions that need replacing. + for (auto* inst : ir.Instructions()) { + auto* load = inst->As(); + if (load == nullptr) { + continue; + } + + auto* ba_type = load->Result()->Type()->As(); + if (ba_type == nullptr) { + continue; + } + TINT_IR_ASSERT(ir, ba_type->IsHandle()); + + auto* ba_ptr = load->From(); + auto* element_ptr_ty = ty.ptr(ba_type->ElemType()); + + load->Result()->ForEachUseUnsorted([&](core::ir::Usage use) { + Switch( + use.instruction, + [&](core::ir::Access* access) { + b.InsertBefore(access, [&]() { + Vector indices_copy = access->Indices(); + auto* element_ptr = b.Access(element_ptr_ty, ba_ptr, indices_copy); + b.LoadWithResult(access->DetachResult(), element_ptr); + access->Destroy(); + }); + }, + TINT_ICE_ON_NO_MATCH); + }); + load->Destroy(); + } + } +}; + +} // namespace + +Result KeepBindingArrayAsPointer(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.KeepBindingArrayAsPointer", + kKeepBindingArrayAsPointerCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.h new file mode 100644 index 000000000..03c6b8a4b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.h @@ -0,0 +1,64 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_KEEP_BINDING_ARRAY_AS_POINTER_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_KEEP_BINDING_ARRAY_AS_POINTER_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +// The capabilities that the transform can support. +const core::ir::Capabilities kKeepBindingArrayAsPointerCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowNonCoreTypes, +}; + +/// KeepBindingArrayAsPointer is a transform that ensures that binding_arrays are never stored by +/// value but only used via a pointer to them. This is used to produce SPIR-V that's more similar to +/// what drivers typically ingest where OpTypeArray is always kept as a pointer. +/// +/// Note that it doesn't handle function parameters so DirectVariableAccess (DVA) for handles must +/// have run prior to this transform. +/// +/// This mismatch between Tint IR and SPIR-V at the time of writing is because Tint IR disallows +/// handle address space pointers as function arguments, while "idiomatic" SPIR-V that drivers are +/// used to use pointers to pass handle types as function arguments. +/// +/// @param module the module to transform +/// @returns success or failure +Result KeepBindingArrayAsPointer(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_KEEP_BINDING_ARRAY_AS_POINTER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.cc new file mode 100644 index 000000000..404409096 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.cc @@ -0,0 +1,284 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/merge_return.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/containers/transform.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +// The capabilities that the transform can support. +const core::ir::Capabilities kMergeReturnCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// PIMPL state for the transform, for a single function. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// The "has not returned" flag. + core::ir::Var* continue_execution = nullptr; + + /// The variable that holds the return value. + /// Null when the function does not return a value. + core::ir::Var* return_val = nullptr; + + /// The set of control instructions whose subsequent instructions need to be conditionalized. + UniqueVector needs_conditionalized_merge{}; + + /// The set of control instructions whose subsequent instructions have been conditionalized. + Hashset has_conditionalized_merge{}; + + /// Process the function. + /// @param fn the function to process + void Process(core::ir::Function* fn) { + if (fn->IsEntryPoint()) { + // Entry points are not called and do not require this transformation to ensure + // convergence. + return; + } + + // Find all of the return instructions. + Vector returns; + fn->ForEachUseSorted([&](const core::ir::Usage& usage) { + if (auto* ret = usage.instruction->As()) { + returns.Push(ret); + } + }); + + // If there exists at least one return that is not the final function body return, then we + // need to transform the function. Otherwise we can bail early here without making changes. + if (returns.IsEmpty() || + (returns.Length() == 1 && returns[0] == fn->Block()->Terminator())) { + return; + } + + // Create a boolean variable that can be used to check whether the function is returning, + // and a variable to hold the return value if needed. + b.InsertBefore(fn->Block()->Front(), [&] { + if (!fn->ReturnType()->Is()) { + return_val = b.Var("return_value", ty.ptr(function, fn->ReturnType())); + } + continue_execution = b.Var("continue_execution", true); + }); + + // Replace every return instruction with an exit instruction, setting a flag to signal that + // execution should not continue. + for (auto* ret : returns) { + ReplaceReturn(ret); + } + + // Conditionalize instructions after control flow instructions that are exited from the site + // of a return instruction.. + // This may discover additional control instructions that need conditionalized merges as we + // introduce new exit instructions that walk back up the control flow stack. + while (!needs_conditionalized_merge.IsEmpty()) { + auto* control = needs_conditionalized_merge.Pop(); + if (has_conditionalized_merge.Add(control)) { + ConditionalizeMerge(control); + } + } + + // Insert the final return at the end of the function. + b.Append(fn->Block(), [&] { + if (return_val) { + b.Return(fn, b.Load(return_val)); + } else { + b.Return(fn); + } + }); + + // Cleanup: if 'continue_execution' was only ever assigned, remove it. + if (continue_execution) { + continue_execution->DestroyIfOnlyAssigned(); + } + } + + /// Replace a return instruction with an exit instruction, setting the flag to signal that + /// execution should not continue, and capturing the return value if present. + /// @param ret the return instruction to replace + void ReplaceReturn(core::ir::Return* ret) { + // We will exit out of the current control instruction to the enclosing block. + auto* control = ret->Block()->Parent(); + + // Set the 'continue_execution' flag to false, and store the return value into + // 'return_value', if present. + b.InsertBefore(ret, [&] { + // Set the flag only if we are not in the function block, where it would be redundant. + if (control) { + b.Store(continue_execution, false); + } + if (return_val) { + b.Store(return_val, ret->Value()); + } + if (control) { + ExitFromControl(control); + } + }); + ret->Destroy(); + } + + /// Conditionalize the instructions that will be in the merge block for @p control by wrapping + /// them in a new `if` instruction that checks the `continue_execution` flag. + /// @param control the control instruction that should have its merge conditionalized + void ConditionalizeMerge(core::ir::ControlInstruction* control) { + auto* next = control->next; + + // If there are no instructions after the control instruction then we must be at the + // top-level function block (where the final return has been removed), so there's nothing to + // conditionalize. + if (next == nullptr) { + return; + } + + // If we are nested somewhere inside a loop/switch instruction, we can just jump out of that + // instead of conditionalizing the subsequent instructions. + auto* exit_target = control->Block()->Parent(); + while (exit_target) { + if (exit_target->IsAnyOf()) { + b.InsertBefore(next, [&] { + auto* load = b.Load(continue_execution); + auto* cond = b.If(b.Not(load)); + b.Append(cond->True(), [&] { // + ExitFromControl(exit_target); + }); + }); + return; + } + exit_target = exit_target->Block()->Parent(); + } + + // If the next instruction is an unreachable, we've made it reachable and need to exit up + // the control flow stack instead. + if (next->Is()) { + if (control->Block()->Parent()) { + b.InsertBefore(next, [&] { // + ExitFromControl(next->Block()->Parent()); + }); + } + next->Destroy(); + return; + } + + // If the next instruction is already an exit instruction, we need to conditionalize the + // merge that it will exit to. + if (auto* exit = next->As()) { + needs_conditionalized_merge.Add(exit->ControlInstruction()); + return; + } + + // The merge block is non-trivial, so we need to wrap all subsequent instructions in a new + // conditional that is based on the `continue_execution` flag. + auto* load = b.Load(continue_execution); + auto* cond = b.If(load); + load->InsertAfter(control); + cond->InsertAfter(load); + while (cond->next) { + auto inst = cond->next; + inst->Remove(); + cond->True()->Append(inst); + + // If the instruction is an exit if, we need to re-target it to the new `if` that we + // created and propagate any of its operands through the new `if` as results. + if (auto* exit_if = inst->As()) { + exit_if->SetIf(cond); + + auto exit_args = exit_if->Args(); + if (!exit_args.IsEmpty()) { + cond->SetResults(tint::Transform<8>(exit_args, [&](auto* arg) { // + return b.InstructionResult(arg->Type()); + })); + } + } + } + // We might not have moved a terminator instruction if we are conditionalizing instructions + // in the function block, since the final return may have been removed. + if (!cond->True()->Back()->Is()) { + cond->True()->Append(b.ExitIf(cond)); + } + + // Now exit up the control flow stack and conditionalize the containing merge block as well. + if (auto* parent = control->Block()->Parent()) { + // Propagate results from the conditional `if` through the new exit. + Vector exit_args; + exit_args.Resize(control->Block()->Parent()->Results().Length()); + TINT_IR_ASSERT(ir, cond->Results().Length() == exit_args.Length()); + for (size_t i = 0; i < cond->Results().Length(); ++i) { + exit_args[i] = cond->Results()[i]; + } + b.Exit(parent, std::move(exit_args))->InsertAfter(cond); + + needs_conditionalized_merge.Add(parent); + } + } + + /// Exit from the target control flow instruction. + /// @param control the control flow instruction to exit from + void ExitFromControl(core::ir::ControlInstruction* control) { + // Produce `undef` values for any results, since they will never be used. + Vector exit_args; + exit_args.Resize(control->Results().Length()); + b.Exit(control, std::move(exit_args)); + + // Mark the control flow instruction as requiring its merge to be conditionalized. + needs_conditionalized_merge.Add(control); + } +}; + +} // namespace + +Result MergeReturn(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.MergeReturn", kMergeReturnCapabilities)); + + // Process each function. + for (auto& fn : ir.functions) { + State{ir}.Process(fn); + } + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.h new file mode 100644 index 000000000..550350372 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/merge_return.h @@ -0,0 +1,48 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_MERGE_RETURN_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_MERGE_RETURN_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +/// MergeReturn is a transform merges multiple return statements in a function into a single return +/// at the end of the function. +/// @param module the module to transform +/// @returns success or failure +Result MergeReturn(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_MERGE_RETURN_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc new file mode 100644 index 000000000..ff6919be7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.cc @@ -0,0 +1,138 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + // Find user-declared functions that have value arguments containing matrices. + for (auto& func : ir.functions) { + for (auto* param : func->Params()) { + if (ContainsMatrix(param->Type())) { + TransformFunction(func); + break; + } + } + } + } + + /// Checks if a type contains a matrix. + /// @param type the type to check + /// @returns true if the type contains a matrix, otherwise false + bool ContainsMatrix(const core::type::Type* type) { + return tint::Switch( + type, // + [&](const core::type::Matrix*) { return true; }, + [&](const core::type::Array* arr) { return ContainsMatrix(arr->ElemType()); }, + [&](const core::type::Struct* str) { + for (auto* member : str->Members()) { + if (ContainsMatrix(member->Type())) { + return true; + } + } + return false; + }, + [&](Default) { return false; }); + } + + /// Transform a function that has value parameters containing matrices. + /// @param func the function to transform + void TransformFunction(core::ir::Function* func) { + Vector replacement_params; + for (auto* param : func->Params()) { + if (ContainsMatrix(param->Type())) { + // Replace the value parameter with a pointer. + auto* new_param = b.FunctionParam(ty.ptr(function, param->Type())); + + // Load from the pointer to get the value. + auto* load = b.Load(new_param); + func->Block()->Prepend(load); + param->ReplaceAllUsesWith(load->Result()); + + // Modify all of the callsites. + func->ForEachUseUnsorted([&](core::ir::Usage use) { + if (auto* call = use.instruction->As()) { + ReplaceCallArgument(call, replacement_params.Length()); + } + }); + + replacement_params.Push(new_param); + } else { + // No matrices, so just copy the parameter as is. + replacement_params.Push(param); + } + } + func->SetParams(std::move(replacement_params)); + } + + /// Replace a function call argument with an equivalent passed by pointer. + void ReplaceCallArgument(core::ir::UserCall* call, size_t arg_index) { + // Copy the argument to a locally declared variable. + auto* arg = call->Args()[arg_index]; + auto* local_var = b.Var(ty.ptr(function, arg->Type())); + local_var->SetInitializer(arg); + local_var->InsertBefore(call); + + call->SetOperand(core::ir::UserCall::kArgsOperandOffset + arg_index, local_var->Result()); + } +}; + +} // namespace + +Result PassMatrixByPointer(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.PassMatrixByPointer")); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h new file mode 100644 index 000000000..87bd4b1e1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_PASS_MATRIX_BY_POINTER_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_PASS_MATRIX_BY_POINTER_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +/// PassMatrixByPointer is a transform that modifies function calls that pass values that contain +/// matrices to pass them by pointer instead. +/// This is used to workaround bugs in some Qualcomm drivers (see crbug.com/tint/2045). +/// @param module the module to transform +/// @returns success or failure +Result PassMatrixByPointer(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_PASS_MATRIX_BY_POINTER_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.cc new file mode 100644 index 000000000..9506c6d0e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.cc @@ -0,0 +1,247 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/raise.h" + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h" +#include "src/tint/lang/core/ir/transform/binary_polyfill.h" +#include "src/tint/lang/core/ir/transform/binding_remapper.h" +#include "src/tint/lang/core/ir/transform/block_decorated_structs.h" +#include "src/tint/lang/core/ir/transform/builtin_polyfill.h" +#include "src/tint/lang/core/ir/transform/builtin_scalarize.h" +#include "src/tint/lang/core/ir/transform/combine_access_instructions.h" +#include "src/tint/lang/core/ir/transform/conversion_polyfill.h" +#include "src/tint/lang/core/ir/transform/decompose_uniform_access.h" +#include "src/tint/lang/core/ir/transform/demote_to_helper.h" +#include "src/tint/lang/core/ir/transform/direct_variable_access.h" +#include "src/tint/lang/core/ir/transform/multiplanar_external_texture.h" +#include "src/tint/lang/core/ir/transform/prepare_immediate_data.h" +#include "src/tint/lang/core/ir/transform/preserve_padding.h" +#include "src/tint/lang/core/ir/transform/prevent_infinite_loops.h" +#include "src/tint/lang/core/ir/transform/remove_uniform_vector_component_loads.h" +#include "src/tint/lang/core/ir/transform/resource_table.h" +#include "src/tint/lang/core/ir/transform/robustness.h" +#include "src/tint/lang/core/ir/transform/signed_integer_polyfill.h" +#include "src/tint/lang/core/ir/transform/single_entry_point.h" +#include "src/tint/lang/core/ir/transform/std140.h" +#include "src/tint/lang/core/ir/transform/substitute_overrides.h" +#include "src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.h" +#include "src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h" +#include "src/tint/lang/spirv/writer/common/option_helpers.h" +#include "src/tint/lang/spirv/writer/raise/builtin_polyfill.h" +#include "src/tint/lang/spirv/writer/raise/case_switch_to_if_else.h" +#include "src/tint/lang/spirv/writer/raise/expand_implicit_splats.h" +#include "src/tint/lang/spirv/writer/raise/fork_explicit_layout_types.h" +#include "src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h" +#include "src/tint/lang/spirv/writer/raise/keep_binding_array_as_pointer.h" +#include "src/tint/lang/spirv/writer/raise/merge_return.h" +#include "src/tint/lang/spirv/writer/raise/pass_matrix_by_pointer.h" +#include "src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.h" +#include "src/tint/lang/spirv/writer/raise/resource_table.h" +#include "src/tint/lang/spirv/writer/raise/shader_io.h" +#include "src/tint/lang/spirv/writer/raise/unary_polyfill.h" +#include "src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h" + +namespace tint::spirv::writer { + +Result Raise(core::ir::Module& module, const Options& options) { + TINT_CHECK_RESULT(core::ir::transform::SingleEntryPoint(module, options.entry_point_name)); + + TINT_CHECK_RESULT( + core::ir::transform::SubstituteOverrides(module, options.substitute_overrides_config)); + + tint::transform::multiplanar::BindingsMap multiplanar_map{}; + RemapperData remapper_data{}; + PopulateRemapperAndMultiplanarOptions(options, remapper_data, multiplanar_map); + + TINT_CHECK_RESULT(core::ir::transform::BindingRemapper(module, remapper_data)); + + if (!options.disable_robustness) { + core::ir::transform::RobustnessConfig config; + if (options.extensions.disable_image_robustness) { + config.clamp_texture = false; + } + config.disable_runtime_sized_array_index_clamping = + options.extensions.disable_runtime_sized_array_index_clamping; + config.use_integer_range_analysis = !options.disable_integer_range_analysis; + TINT_CHECK_RESULT(core::ir::transform::Robustness(module, config)); + + TINT_CHECK_RESULT(core::ir::transform::PreventInfiniteLoops(module)); + } + + if (options.resource_table.has_value()) { + spirv::writer::raise::ResourceTableHelper helper; + TINT_CHECK_RESULT( + core::ir::transform::ResourceTable(module, options.resource_table.value(), &helper)); + } + + // PrepareImmediateData must come before any transform that needs internal immediate data. + core::ir::transform::PrepareImmediateDataConfig immediate_data_config; + if (options.depth_range_offsets) { + TINT_CHECK_RESULT(immediate_data_config.AddInternalImmediateData( + options.depth_range_offsets.value().min, module.symbols.New("tint_frag_depth_min"), + module.Types().f32())); + TINT_CHECK_RESULT(immediate_data_config.AddInternalImmediateData( + options.depth_range_offsets.value().max, module.symbols.New("tint_frag_depth_max"), + module.Types().f32())); + } + TINT_CHECK_RESULT_UNWRAP(immediate_data_layout, core::ir::transform::PrepareImmediateData( + module, immediate_data_config)); + + core::ir::transform::BinaryPolyfillConfig binary_polyfills; + binary_polyfills.bitshift_modulo = true; + binary_polyfills.int_div_mod = !options.disable_polyfill_integer_div_mod; + TINT_CHECK_RESULT(core::ir::transform::BinaryPolyfill(module, binary_polyfills)); + + core::ir::transform::BuiltinPolyfillConfig core_polyfills; + core_polyfills.clamp_int = true; + core_polyfills.count_leading_zeros = true; + core_polyfills.count_trailing_zeros = true; + core_polyfills.extract_bits = core::ir::transform::BuiltinPolyfillLevel::kClampOrRangeCheck; + core_polyfills.first_leading_bit = true; + core_polyfills.first_trailing_bit = true; + core_polyfills.insert_bits = core::ir::transform::BuiltinPolyfillLevel::kClampOrRangeCheck; + core_polyfills.saturate = true; + core_polyfills.texture_sample_base_clamp_to_edge_2d_f32 = true; + core_polyfills.dot_4x8_packed = options.extensions.dot_4x8_packed; + core_polyfills.pack_unpack_4x8 = true; + core_polyfills.pack_4xu8_clamp = true; + core_polyfills.pack_unpack_4x8_norm = options.workarounds.polyfill_pack_unpack_4x8_norm; + core_polyfills.abs_signed_int = true; + core_polyfills.subgroup_broadcast_f16 = options.workarounds.polyfill_subgroup_broadcast_f16; + TINT_CHECK_RESULT(core::ir::transform::BuiltinPolyfill(module, core_polyfills)); + + core::ir::transform::ConversionPolyfillConfig conversion_polyfills; + conversion_polyfills.ftoi = true; + TINT_CHECK_RESULT(core::ir::transform::ConversionPolyfill(module, conversion_polyfills)); + + TINT_CHECK_RESULT(core::ir::transform::MultiplanarExternalTexture(module, multiplanar_map)); + + if (!options.disable_workgroup_init && + !options.extensions.use_zero_initialize_workgroup_memory) { + TINT_CHECK_RESULT(core::ir::transform::ZeroInitWorkgroupMemory(module)); + } + + // PreservePadding must come before DirectVariableAccess. + TINT_CHECK_RESULT(core::ir::transform::PreservePadding(module)); + + core::ir::transform::DirectVariableAccessOptions dva_options; + dva_options.transform_function = true; + dva_options.transform_private = true; + dva_options.transform_handle = options.workarounds.dva_transform_handle; + TINT_CHECK_RESULT(core::ir::transform::DirectVariableAccess(module, dva_options)); + + // Fixup loads of binding_arrays of handles that may have been introduced by + // DirectVariableAccess (DVA). Vulkan drivers that need DVA of handle expect binding_arrays to + // stay as pointer and many mishandle by-value binding_arrays. + if (options.workarounds.dva_transform_handle) { + TINT_CHECK_RESULT(raise::KeepBindingArrayAsPointer(module)); + } + + if (options.workarounds.pass_matrix_by_pointer) { + // PassMatrixByPointer must come after PreservePadding+DirectVariableAccess. + TINT_CHECK_RESULT(raise::PassMatrixByPointer(module)); + } + + TINT_CHECK_RESULT(core::ir::transform::Bgra8UnormPolyfill(module)); + + if (!options.extensions.use_uniform_buffers) { + // DecomposeUniformAccess must come before BlockDecoratedStructs, which will wrap the + // uniform variable in a structure. + TINT_CHECK_RESULT(core::ir::transform::DecomposeUniformAccess(module)); + } else { + TINT_CHECK_RESULT(core::ir::transform::Std140(module)); + } + TINT_CHECK_RESULT(core::ir::transform::BlockDecoratedStructs(module)); + + TINT_CHECK_RESULT(core::ir::transform::VectorizeScalarMatrixConstructors(module)); + + // CombineAccessInstructions must come after DirectVariableAccess and BlockDecoratedStructs. + // We run this transform as some Qualcomm drivers struggle with partial access chains that + // produce pointers to matrices. + TINT_CHECK_RESULT(core::ir::transform::CombineAccessInstructions(module)); + + // RemoveUniformVectorComponentLoads is used to work around a Qualcomm driver bug. + // See crbug.com/452350626. + TINT_CHECK_RESULT(core::ir::transform::RemoveUniformVectorComponentLoads(module)); + + if (!options.extensions.use_demote_to_helper_invocation) { + // DemoteToHelper must come before any transform that introduces non-core instructions. + TINT_CHECK_RESULT(core::ir::transform::DemoteToHelper(module)); + } + + raise::PolyfillConfig config = { + .use_vulkan_memory_model = options.extensions.use_vulkan_memory_model, + .version = options.spirv_version, + .subgroup_shuffle_clamped = options.workarounds.subgroup_shuffle_clamped, + .texture_sample_compare_depth_cube_array = + options.workarounds.texture_sample_compare_depth_cube_array}; + TINT_CHECK_RESULT(raise::BuiltinPolyfill(module, config)); + TINT_CHECK_RESULT(raise::ExpandImplicitSplats(module)); + + core::ir::transform::BuiltinScalarizeConfig scalarize_config{ + .scalarize_clamp = options.workarounds.scalarize_max_min_clamp, + .scalarize_max = options.workarounds.scalarize_max_min_clamp, + .scalarize_min = options.workarounds.scalarize_max_min_clamp}; + TINT_CHECK_RESULT(core::ir::transform::BuiltinScalarize(module, scalarize_config)); + + core::ir::transform::SignedIntegerPolyfillConfig signed_integer_cfg{ + .signed_negation = true, .signed_arithmetic = true, .signed_shiftleft = true}; + TINT_CHECK_RESULT(core::ir::transform::SignedIntegerPolyfill(module, signed_integer_cfg)); + + // AMD mesa front end optimizer bug for unary negation and abs. + // Fixed in 25.3 - See crbug.com/448294721 + raise::UnaryPolyfillConfig unary_polyfill_cfg = { + .polyfill_f32_negation = options.workarounds.polyfill_unary_f32_negation, + .polyfill_f32_abs = options.workarounds.polyfill_f32_abs}; + + TINT_CHECK_RESULT(raise::UnaryPolyfill(module, unary_polyfill_cfg)); + + // kAllowAnyInputAttachmentIndexType required after ExpandImplicitSplats + TINT_CHECK_RESULT(raise::HandleMatrixArithmetic(module)); + TINT_CHECK_RESULT(raise::MergeReturn(module)); + if (options.workarounds.polyfill_case_switch) { + TINT_CHECK_RESULT(raise::CaseSwitchToIfElse(module)); + } + TINT_CHECK_RESULT(raise::RemoveUnreachableInLoopContinuing(module)); + TINT_CHECK_RESULT(raise::ShaderIO( + module, raise::ShaderIOConfig{immediate_data_layout, options.emit_vertex_point_size, + !options.extensions.use_storage_input_output_16, + options.polyfill_pixel_center, options.depth_range_offsets})); + + // ForkExplicitLayoutTypes must come after DecomposeUniformAccess, since it rewrites + // host-shareable array types to use the explicitly laid array type defined by the SPIR-V + // dialect. + TINT_CHECK_RESULT(raise::ForkExplicitLayoutTypes(module, options.spirv_version)); + + TINT_CHECK_RESULT(raise::VarForDynamicIndex(module)); + + return Success; +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.h new file mode 100644 index 000000000..c5c0e8bce --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/raise.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_RAISE_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_RAISE_H_ + +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer { + +/// Raise a core IR module to the SPIR-V dialect of the IR. +/// @param module the core IR module to raise to SPIR-V dialect +/// @param options the SPIR-V writer options +/// @returns success or failure +Result Raise(core::ir::Module& module, const Options& options); + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_RAISE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.cc new file mode 100644 index 000000000..a5b3b7721 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.cc @@ -0,0 +1,105 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.h" + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// Process the module. + void Process() { + // Find all unreachable instructions. + for (auto* inst : ir.Instructions()) { + if (auto* unreachable = inst->As()) { + Process(unreachable); + } + } + } + + /// Check and replace an unreachable instruction if necessary. + /// @param unreachable the instruction to check and maybe replace + void Process(core::ir::Unreachable* unreachable) { + // Walk up the control stack to see if we are inside a loop continuing block. + auto* block = unreachable->Block(); + while (block->Parent()) { + auto* control = block->Parent(); + if (auto* loop = control->As()) { + if (loop->Continuing() == block) { + Replace(unreachable); + return; + } + } + block = control->Block(); + } + } + + /// Replace an unreachable instruction. + /// @param unreachable the instruction to replace + void Replace(core::ir::Unreachable* unreachable) { + auto* control = unreachable->Block()->Parent(); + + // Fill the exit argument with `undef`. + Vector exit_args; + exit_args.Resize(control->Results().Length()); + + // Replace the `unreachable` with an instruction that exits from the control construct. + auto* exit = b.Exit(unreachable->Block()->Parent(), std::move(exit_args)); + unreachable->ReplaceWith(exit); + unreachable->Destroy(); + } +}; + +} // namespace + +Result RemoveUnreachableInLoopContinuing(core::ir::Module& ir) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.RemoveUnreachableInLoopContinuing", + kRemoveUnreachableInLoopContinuingCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.h new file mode 100644 index 000000000..9728cacf9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/remove_unreachable_in_loop_continuing.h @@ -0,0 +1,57 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_REMOVE_UNREACHABLE_IN_LOOP_CONTINUING_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_REMOVE_UNREACHABLE_IN_LOOP_CONTINUING_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +// The capabilities that the transform can support. +const core::ir::Capabilities kRemoveUnreachableInLoopContinuingCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// RemoveUnreachableInLoopContinuing is a transform that replaces unreachable statements that are +/// nested inside a loop continuing block, as SPIR-V's structured control flow rules prohibit this. +/// @param module the module to transform +/// @returns success or failure +Result RemoveUnreachableInLoopContinuing(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_REMOVE_UNREACHABLE_IN_LOOP_CONTINUING_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.cc new file mode 100644 index 000000000..9b52862e8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.cc @@ -0,0 +1,58 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/resource_table.h" + +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/resource_type.h" +#include "src/tint/lang/spirv/type/resource_table.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::spirv::writer::raise { + +// Returns a map of types to the var which is used to access the memory of that type +Hashmap ResourceTableHelper::GenerateVars( + core::ir::Builder& b, + const BindingPoint& bp, + const std::vector& types) const { + Hashmap res; + + for (auto& type : types) { + auto* t = core::type::ResourceTypeToType(b.ir.Types(), type); + + auto* spv_ty = b.ir.Types().Get(t); + auto* v = b.Var(b.ir.Types().ptr(handle, spv_ty)); + v->SetBindingPoint(bp.group, bp.binding); + res.Add(t, v); + } + + return res; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.h new file mode 100644 index 000000000..5696f3dc6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/resource_table.h @@ -0,0 +1,51 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_RESOURCE_TABLE_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_RESOURCE_TABLE_H_ + +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/transform/resource_table.h" + +namespace tint::spirv::writer::raise { + +class ResourceTableHelper : public core::ir::transform::ResourceTableHelper { + public: + ~ResourceTableHelper() override = default; + + // Returns a map of types to the var which is used to access the memory of that type + Hashmap GenerateVars( + core::ir::Builder& b, + const BindingPoint& bp, + const std::vector& types) const override; +}; + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_RESOURCE_TABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.cc new file mode 100644 index 000000000..4da197383 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.cc @@ -0,0 +1,336 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/shader_io.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/transform/shader_io.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/utils/ice/ice.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the parts of the shader IO transform specific to SPIR-V. +/// For SPIR-V, we declare a global variable for each input and output. The wrapper entry point then +/// loads from and stores to these variables. We also modify the type of the SampleMask builtin to +/// be an array, as required by Vulkan. +struct StateImpl : core::ir::transform::ShaderIOBackendState { + /// The input variables. + Vector input_vars; + /// The output variables. + Vector output_vars; + + /// The configuration options. + const ShaderIOConfig& config; + + // Final output value of 'position' builtin from the vertex shader. + core::ir::Value* vert_out_position = nullptr; + + // IO index for vertex position emulation interpolant + std::optional center_pos_vert_idx; + + // IO index for fragment position emulation interpolant + std::optional center_pos_frag_idx; + + /// Constructor + StateImpl(core::ir::Module& mod, core::ir::Function* f, const ShaderIOConfig& cfg) + : ShaderIOBackendState(mod, f), config(cfg) {} + + /// Destructor + ~StateImpl() override {} + + /// Add a new interpolant that will be used to emulate the position builtin as if it always is + /// pixel centered. + /// @param entries the entries to emit + /// @param addrspace the address to use for the global variables + uint32_t AddCenterPosInterpolant(Vector& entries, + core::AddressSpace addrspace) { + // Verbose way of finding the smallest free location (id). This of course needs to be the + // same id value for both vertex and fragment. + std::set existing_locations; + for (auto io : entries) { + if (io.attributes.location.has_value()) { + existing_locations.insert(io.attributes.location.value()); + } + } + uint32_t free_location = 0u; + // We only need to search through existing_locations.size + 1 because either we will simply + // add an index to the end or there will be a hole in the range of locations + for (uint32_t i = 0u; i < (existing_locations.size() + 1); i++) { + if (existing_locations.find(i) == existing_locations.end()) { + free_location = i; + break; + } + } + + auto io_attrib = core::IOAttributes{ + .location = free_location, + .interpolation = core::Interpolation{.type = core::InterpolationType::kLinear, + .sampling = core::InterpolationSampling::kCenter}}; + + if (addrspace == core::AddressSpace::kOut) { + return AddOutput(ir.symbols.New("center_pos"), ty.vec4f(), io_attrib); + } + return AddInput(ir.symbols.New("center_pos"), ty.vec4f(), io_attrib); + } + + /// Declare a global variable for each IO entry listed in @p entries. + /// @param vars the list of variables + /// @param entries the entries to emit + /// @param addrspace the address to use for the global variables + /// @param access the access mode to use for the global variables + /// @param name_suffix the suffix to add to struct and variable names + void MakeVars(Vector& vars, + Vector& entries, + core::AddressSpace addrspace, + core::Access access, + const char* name_suffix) { + if (func->IsVertex() && addrspace == core::AddressSpace::kOut && + config.polyfill_pixel_center) { + center_pos_vert_idx = AddCenterPosInterpolant(entries, addrspace); + + } else if (func->IsFragment() && addrspace == core::AddressSpace::kIn && + config.polyfill_pixel_center) { + center_pos_frag_idx = AddCenterPosInterpolant(entries, addrspace); + } + + for (auto io : entries) { + StringStream name; + name << ir.NameOf(func).Name(); + + if (io.attributes.builtin) { + // SampleMask must be an array for Vulkan. + if (io.attributes.builtin == core::BuiltinValue::kSampleMask) { + io.type = ty.array(); + } + name << "_" << io.attributes.builtin.value(); + + // Vulkan requires that fragment integer builtin inputs be Flat decorated. + if (func->IsFragment() && addrspace == core::AddressSpace::kIn && + io.type->IsIntegerScalarOrVector()) { + io.attributes.interpolation = + core::Interpolation{core::InterpolationType::kFlat}; + } + } + if (io.attributes.location) { + name << "_loc" << io.attributes.location.value(); + if (io.attributes.blend_src.has_value()) { + name << "_idx" << io.attributes.blend_src.value(); + } + } + name << name_suffix; + + // Replace f16 types with f32 types if necessary. + auto* store_type = io.type; + if (config.polyfill_f16_io) { + if (store_type->DeepestElement()->Is()) { + store_type = ty.MatchWidth(ty.f32(), io.type); + } + } + + // Create an IO variable and add it to the root block. + auto* ptr = ty.ptr(addrspace, store_type, access); + auto* var = b.Var(name.str(), ptr); + var->SetAttributes(io.attributes); + ir.root_block->Append(var); + vars.Push(var); + } + } + + /// @copydoc ShaderIO::BackendState::FinalizeInputs + Vector FinalizeInputs() override { + MakeVars(input_vars, inputs, core::AddressSpace::kIn, core::Access::kRead, "_Input"); + return tint::Empty; + } + + /// @copydoc ShaderIO::BackendState::FinalizeOutputs + const core::type::Type* FinalizeOutputs() override { + MakeVars(output_vars, outputs, core::AddressSpace::kOut, core::Access::kWrite, "_Output"); + return ty.void_(); + } + + /// @copydoc ShaderIO::BackendState::GetInput + core::ir::Value* GetInput(core::ir::Builder& builder, uint32_t idx) override { + // Load the input from the global variable declared earlier. + auto* ptr = ty.ptr(core::AddressSpace::kIn, inputs[idx].type, core::Access::kRead); + auto* from = input_vars[idx]->Result(); + + // SampleMask becomes an array for SPIR-V, so load from the first element. + if (inputs[idx].attributes.builtin == core::BuiltinValue::kSampleMask) { + from = builder.Access(ptr, input_vars[idx], 0_u)->Result(); + } + + auto* value = builder.Load(from)->Result(); + + // Convert f32 values to f16 values if needed. + if (config.polyfill_f16_io && inputs[idx].type->DeepestElement()->Is()) { + value = builder.Convert(inputs[idx].type, value)->Result(); + } + + if (inputs[idx].attributes.builtin == core::BuiltinValue::kPosition && + center_pos_frag_idx.has_value()) { + // This fix is idempotent in that if it was not needed it will still apply correctly. + auto* vec_xy = builder.Swizzle(ty.vec2f(), value, {0, 1}); + auto* floor_xy = builder.Call(ty.vec2f(), core::BuiltinFn::kFloor, vec_xy); + auto p5_const = builder.Constant(0.5_f); + auto* plus_p5 = builder.Add(floor_xy, builder.Splat(ty.vec2f(), p5_const)); + + auto* xyzw_from_user_center = builder.Load(input_vars[center_pos_frag_idx.value()]); + + auto* user_center_z = builder.Swizzle(ty.f32(), xyzw_from_user_center, {2}); + auto* user_center_w = builder.Swizzle(ty.f32(), xyzw_from_user_center, {3}); + + auto* viewport_user_center_z = + ViewportMappedFragDepth(builder, user_center_z->Result()); + value = builder.Construct(ty.vec4f(), plus_p5, viewport_user_center_z, user_center_w) + ->Result(); + } + + return value; + } + + /// Propagate outputs from the inner function call to their final destination. + /// @param builder the IR builder for new instructions + /// @param inner_result the return value from calling the original entry point function + void SetBackendOutputs(core::ir::Builder& builder, core::ir::Value* inner_result) override { + if (center_pos_vert_idx.has_value()) { + SetOutput(builder, center_pos_vert_idx.value(), inner_result); + } + } + + /// @copydoc ShaderIO::BackendState::SetOutput + void SetOutput(core::ir::Builder& builder, uint32_t idx, core::ir::Value* value) override { + // Store the output to the global variable declared earlier. + auto& output = outputs[idx]; + auto* ptr = ty.ptr(core::AddressSpace::kOut, output.type, core::Access::kWrite); + auto* to = output_vars[idx]->Result(); + + // SampleMask becomes an array for SPIR-V, so store to the first element. + if (output.attributes.builtin == core::BuiltinValue::kSampleMask) { + to = builder.Access(ptr, to, 0_u)->Result(); + } + + if (output.attributes.builtin == core::BuiltinValue::kPosition) { + vert_out_position = value; + } + + if (center_pos_vert_idx.has_value() && center_pos_vert_idx == idx) { + // Special center position polyfilled from within vertex shader. + TINT_IR_ASSERT(ir, vert_out_position); + auto one_div_w = + builder.Divide(1_f, builder.Swizzle(ty.f32(), vert_out_position, {3u})); + auto z_div_w = + builder.Multiply(one_div_w, builder.Swizzle(ty.f32(), vert_out_position, {2u})); + value = + builder + .Construct(ty.vec4f(), builder.Swizzle(ty.vec2f(), vert_out_position, {0, 1}), + z_div_w, one_div_w) + ->Result(); + } + + // Clamp frag_depth values if necessary. + if (output.attributes.builtin == core::BuiltinValue::kFragDepth) { + value = ClampFragDepth(builder, value); + } + + // Convert f16 values to f32 values if needed. + if (config.polyfill_f16_io && value->Type()->DeepestElement()->Is()) { + value = builder.Convert(to->Type()->UnwrapPtr(), value)->Result(); + } + + builder.Store(to, value); + } + + /// Remap viewport z if necessary. + /// @param builder the builder to use for new instructions + /// @param frag_depth the incoming frag_depth value + /// @returns the clamped value + core::ir::Value* ViewportMappedFragDepth(core::ir::Builder& builder, + core::ir::Value* frag_depth) { + if (!config.depth_range_offsets) { + return frag_depth; + } + + auto* immediate_data = config.immediate_data_layout.var; + auto min_idx = u32(config.immediate_data_layout.IndexOf(config.depth_range_offsets->min)); + auto max_idx = u32(config.immediate_data_layout.IndexOf(config.depth_range_offsets->max)); + auto* min = builder.Load(builder.Access>(immediate_data, min_idx)); + auto* max = builder.Load(builder.Access>(immediate_data, max_idx)); + // Viewport remapping depth normalization equation. + // https://www.w3.org/TR/webgpu/#coordinate-systems#:~:text=Viewport%20coordinates + auto* max_minus_min = builder.Subtract(max, min); + auto* rhs = builder.Multiply(max_minus_min, frag_depth); + return builder.Add(min, rhs)->Result(); + } + + /// Clamp a frag_depth builtin value if necessary. + /// @param builder the builder to use for new instructions + /// @param frag_depth the incoming frag_depth value + /// @returns the clamped value + core::ir::Value* ClampFragDepth(core::ir::Builder& builder, core::ir::Value* frag_depth) { + if (!config.depth_range_offsets) { + return frag_depth; + } + + auto* immediate_data = config.immediate_data_layout.var; + auto min_idx = u32(config.immediate_data_layout.IndexOf(config.depth_range_offsets->min)); + auto max_idx = u32(config.immediate_data_layout.IndexOf(config.depth_range_offsets->max)); + auto* min = builder.Load(builder.Access>(immediate_data, min_idx)); + auto* max = builder.Load(builder.Access>(immediate_data, max_idx)); + return builder.Clamp(frag_depth, min, max)->Result(); + } + + /// @copydoc ShaderIO::BackendState::NeedsVertexPointSize + bool NeedsVertexPointSize() const override { return config.emit_vertex_point_size; } +}; +} // namespace + +Result ShaderIO(core::ir::Module& ir, const ShaderIOConfig& config) { + TINT_CHECK_RESULT(ValidateAndDumpIfNeeded(ir, "spirv.ShaderIO", kShaderIOCapabilities)); + + core::ir::transform::RunShaderIOBase(ir, [&](core::ir::Module& mod, core::ir::Function* func) { + return std::make_unique(mod, func, config); + }); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.h new file mode 100644 index 000000000..ef7d5fefb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/shader_io.h @@ -0,0 +1,76 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_SHADER_IO_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_SHADER_IO_H_ + +#include "src/tint/lang/core/ir/transform/prepare_immediate_data.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kShaderIOCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kLoosenValidationForShaderIO, +}; + +/// ShaderIOConfig describes the set of configuration options for the ShaderIO transform. +struct ShaderIOConfig { + /// immediate data layout information + const core::ir::transform::ImmediateDataLayout& immediate_data_layout; + + /// true if a vertex point size builtin output should be added + bool emit_vertex_point_size = false; + /// true if f16 IO types should be replaced with f32 types and converted + bool polyfill_f16_io = false; + /// true if we should force pixel centers via polyfill when multi-sampling. + bool polyfill_pixel_center = false; + /// offsets for clamping frag depth + std::optional depth_range_offsets{}; +}; + +/// ShaderIO is a transform that moves each entry point function's parameters and return value to +/// global variables to prepare them for SPIR-V codegen. +/// @param module the module to transform +/// @param config the configuration +/// @returns success or failure +Result ShaderIO(core::ir::Module& module, const ShaderIOConfig& config); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_SHADER_IO_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.cc new file mode 100644 index 000000000..9e5e18492 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.cc @@ -0,0 +1,121 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/unary_polyfill.h" + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +using namespace tint::core::fluent_types; // NOLINT +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +struct State { + core::ir::Module& ir; + UnaryPolyfillConfig config; + core::ir::Builder b{ir}; + core::type::Manager& ty{ir.Types()}; + + void Process() { + Vector unary_worklist; + Vector builtin_worklist; + for (auto* inst : ir.Instructions()) { + if (auto* unary = inst->As()) { + if (config.polyfill_f32_negation && unary->Op() == core::UnaryOp::kNegation && + unary->Result()->Type()->DeepestElement()->Is()) { + unary_worklist.Push(unary); + } + } else if (auto* builtin = inst->As()) { + if (config.polyfill_f32_abs && builtin->Func() == core::BuiltinFn::kAbs && + builtin->Result()->Type()->DeepestElement()->Is()) { + builtin_worklist.Push(builtin); + } + } + } + + for (auto* unary : unary_worklist) { + PolyfillF32Negation(unary); + } + for (auto* builtin : builtin_worklist) { + PolyfillF32Abs(builtin); + } + } + + void PolyfillF32Negation(core::ir::Unary* unary) { + auto* val = unary->Val(); + auto* type = val->Type(); + + // AMD mesa front end optimizer bug for unary negation and abs. + // Fixed in 25.3 - See crbug.com/448294721 + // Note we use bitcast as a hammer to avoid the optimizer seeing through other possible + // workarounds. + b.InsertBefore(unary, [&] { + auto* uint_ty = ty.MatchWidth(ty.u32(), type); + auto* u32_val = b.Bitcast(uint_ty, val); + auto* mask = b.MatchWidth(0x80000000_u, uint_ty); + auto* xor_res = b.Xor(u32_val, mask); + b.BitcastWithResult(unary->DetachResult(), xor_res->Result()); + }); + unary->Destroy(); + } + + void PolyfillF32Abs(core::ir::CoreBuiltinCall* builtin) { + auto* val = builtin->Args()[0]; + auto* type = val->Type(); + + // AMD mesa front end optimizer bug for unary negation and abs. + // Fixed in 25.3 - See crbug.com/448294721 + // Note we use bitcast as a hammer to avoid the optimizer seeing through other possible + // workarounds. + b.InsertBefore(builtin, [&] { + auto* uint_ty = ty.MatchWidth(ty.u32(), type); + auto* u32_val = b.Bitcast(uint_ty, val); + auto* mask = b.MatchWidth(0x7FFFFFFF_u, uint_ty); + auto* and_res = b.And(u32_val, mask); + b.BitcastWithResult(builtin->DetachResult(), and_res->Result()); + }); + builtin->Destroy(); + } +}; + +} // namespace + +Result UnaryPolyfill(core::ir::Module& module, const UnaryPolyfillConfig& config) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(module, "spirv.UnaryPolyfill", kPolyfillUnaryCapabilities)); + + State{module, config}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.h new file mode 100644 index 000000000..36bf2f6cc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/unary_polyfill.h @@ -0,0 +1,65 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_UNARY_POLYFILL_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_UNARY_POLYFILL_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::spirv::writer::raise { + +// The capabilities that the transform can support. +const core::ir::Capabilities kPolyfillUnaryCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, +}; + +/// Configuration for the UnaryPolyfill transform. +struct UnaryPolyfillConfig { + /// If true, polyfill f32 negation with bit manipulation. + bool polyfill_f32_negation = false; + /// If true, polyfill f32 abs with sign() * x. + bool polyfill_f32_abs = false; +}; + +/// UnaryPolyfill is a transform that replaces unary instructions with polyfills. +/// @param module the module to transform +/// @param config the configuration used in the polyfill function +/// @returns success or failure +Result UnaryPolyfill(core::ir::Module& module, const UnaryPolyfillConfig& config); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_UNARY_POLYFILL_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc new file mode 100644 index 000000000..6cbb5f939 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc @@ -0,0 +1,260 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h" + +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/utils/containers/hashmap.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::spirv::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// An access that needs replacing. + struct AccessToReplace { + /// The access instruction. + core::ir::Access* access = nullptr; + /// The index of the first dynamic index. + size_t first_dynamic_index = 0; + /// The object type that corresponds to the source of the first dynamic index. + const core::type::Type* dynamic_index_source_type = nullptr; + /// If the access indexes a vector, then the type of that vector + const core::type::Vector* vector_access_type = nullptr; + }; + + /// A partial access chain that uses constant indices to get to an object that will be + /// dynamically indexed. + struct PartialAccess { + /// The base object. + core::ir::Value* base = nullptr; + /// The list of constant indices to get from the base to the source object. + Vector indices; + + /// @returns the hash code of the PartialAccess + tint::HashCode HashCode() const { return Hash(base, indices); } + + /// An equality helper for PartialAccess. + bool operator==(const PartialAccess& other) const { + return base == other.base && indices == other.indices; + } + }; + + /// Traversal action for WalkAccessChain. + enum class Action { kStop, kContinue }; + + /// Walk an the access chain @p access, calling @p callback for each intermediate type. + template + void WalkAccessChain(core::ir::Access* access, CALLBACK&& callback) { + auto indices = access->Indices(); + auto* type = access->Object()->Type(); + for (size_t i = 0; i < indices.Length(); i++) { + if (callback(i, indices[i], type) == Action::kStop) { + break; + } + auto* const_idx = indices[i]->As(); + type = const_idx ? type->Element(const_idx->Value()->ValueAs()) + : type->Elements().type; + } + } + + /// Check if @p access needs to be replaced. + /// @returns the access descriptor or std::nullopt + std::optional ShouldReplace(core::ir::Access* access) { + if (access->Result()->Type()->Is()) { + // No need to modify accesses into pointer types. + return {}; + } + + std::optional result; + WalkAccessChain(access, + [&](size_t i, core::ir::Value* index, const core::type::Type* type) { + if (auto* vec = type->As()) { + // If we haven't found a dynamic index before the vector, then the + // transform doesn't need to hoist the access into a var as a vector + // value can be dynamically indexed. If we have found a dynamic + // index before the vector, then make a note that we're indexing a + // vector as we can't obtain a pointer to a vector element, so this + // needs to be handled specially. + if (result) { + result->vector_access_type = vec; + } + return Action::kStop; + } + + // Check if this is the first dynamic index. + if (!result && !index->Is()) { + result = AccessToReplace{access, i, type}; + } + + return Action::kContinue; + }); + + return result; + } + + /// Process the module. + void Process() { + // Find the access instructions that need replacing. + Vector worklist; + for (auto* inst : ir.Instructions()) { + if (auto* access = inst->As()) { + if (auto to_replace = ShouldReplace(access)) { + worklist.Push(to_replace.value()); + } + } + } + + // Replace each access instruction that we recorded. + Hashmap object_to_var; + Hashmap source_object_to_value; + for (const auto& to_replace : worklist) { + auto* access = to_replace.access; + auto* source_object = access->Object(); + + // If the access starts with at least one constant index, extract the source of the + // first dynamic access to avoid copying the whole object. + if (to_replace.first_dynamic_index > 0) { + PartialAccess partial_access = { + access->Object(), access->Indices().Truncate(to_replace.first_dynamic_index)}; + source_object = + source_object_to_value.GetOrAdd(partial_access, [&]() -> core::ir::Value* { + // If the source is a constant, then the partial access will also produce a + // constant. Extract the constant::Value and use that as the new source + // object. + if (source_object->Is()) { + for (const auto& i : partial_access.indices) { + auto idx = + i->As()->Value()->ValueAs(); + source_object = b.Constant( + source_object->As()->Value()->Index(idx)); + } + return source_object; + } + + // Extract a non-constant intermediate source using an access instruction + // that we insert immediately after the definition of the root source + // object. + auto* intermediate_source = b.Access(to_replace.dynamic_index_source_type, + source_object, partial_access.indices); + b.InsertInBlockAfter(source_object, [&] { b.Append(intermediate_source); }); + return intermediate_source->Result(); + }); + } + + // Declare a variable and copy the source object to it. + auto* var = object_to_var.GetOrAdd(source_object, [&] { + // If the source object is a constant we use a module-scope variable, as it could be + // indexed by multiple functions. Otherwise, we declare a function-scope variable + // immediately after the definition of the source object. + core::ir::Var* decl = nullptr; + if (source_object->Is()) { + decl = b.Var(ty.ptr(core::AddressSpace::kPrivate, source_object->Type(), + core::Access::kReadWrite)); + ir.root_block->Append(decl); + } else { + b.InsertInBlockAfter(source_object, [&] { + decl = b.Var(ty.ptr(core::AddressSpace::kFunction, source_object->Type(), + core::Access::kReadWrite)); + + // If we ever support value declarations at module-scope, we will need to + // modify the partial access logic above since `access` instructions cannot + // be used in the root block. + TINT_IR_ASSERT(ir, decl->Block() != ir.root_block); + }); + } + + decl->SetInitializer(source_object); + return decl->Result(); + }); + + // Create a new access instruction using the new variable as the source. + Vector indices{ + access->Indices().Offset(to_replace.first_dynamic_index)}; + const core::type::Type* access_type = access->Result()->Type(); + core::ir::Value* vector_index = nullptr; + if (to_replace.vector_access_type) { + // The old access indexed the element of a vector. + // Its not valid to obtain the address of an element of a vector, so we need to + // access up to the vector, then use LoadVectorElement to load the element. As a + // vector element is always a scalar, we know the last index of the access is the + // index on the vector. Pop that index to obtain the index to pass to + // LoadVectorElement(), and perform the rest of the access chain. + access_type = to_replace.vector_access_type; + vector_index = indices.Pop(); + } + + auto addrspace = var->Type()->As()->AddressSpace(); + core::ir::Instruction* new_access = + b.Access(ty.ptr(addrspace, access_type, core::Access::kReadWrite), var, indices); + new_access->InsertBefore(access); + + core::ir::Instruction* load = nullptr; + if (to_replace.vector_access_type) { + load = b.LoadVectorElementWithResult(access->DetachResult(), new_access->Result(), + vector_index); + } else { + load = b.LoadWithResult(access->DetachResult(), new_access); + } + access->ReplaceWith(load); + access->Destroy(); + } + } +}; + +} // namespace + +Result VarForDynamicIndex(core::ir::Module& ir) { + TINT_CHECK_RESULT( + ValidateAndDumpIfNeeded(ir, "spirv.VarForDynamicIndex", kVarForDynamicIndexCapabilities)); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::spirv::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h new file mode 100644 index 000000000..f7452f018 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h @@ -0,0 +1,61 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_RAISE_VAR_FOR_DYNAMIC_INDEX_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_RAISE_VAR_FOR_DYNAMIC_INDEX_H_ + +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::spirv::writer::raise { + +/// The capabilities that the transform can support. +const core::ir::Capabilities kVarForDynamicIndexCapabilities{ + core::ir::Capability::kAllowDuplicateBindings, + core::ir::Capability::kAllowAnyInputAttachmentIndexType, + core::ir::Capability::kAllowNonCoreTypes, + core::ir::Capability::kAllow8BitIntegers, + core::ir::Capability::kLoosenValidationForShaderIO, + core::ir::Capability::kAllowPointSizeBuiltin, +}; + +/// VarForDynamicIndex is a transform that copies array and matrix values that are dynamically +/// indexed to a temporary local `var` before performing the index. This transform is used by the +/// SPIR-V writer as there is no SPIR-V instruction that can dynamically index a non-pointer +/// composite. +/// @param module the module to transform +/// @returns success or failure +Result VarForDynamicIndex(core::ir::Module& module); + +} // namespace tint::spirv::writer::raise + +#endif // SRC_TINT_LANG_SPIRV_WRITER_RAISE_VAR_FOR_DYNAMIC_INDEX_H_ diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/writer.cc b/3rdparty/dawn/src/tint/lang/spirv/writer/writer.cc new file mode 100644 index 000000000..17d13c6a1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/writer.cc @@ -0,0 +1,182 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/spirv/writer/writer.h" + +#include + +#include "src/tint/lang/core/ir/analysis/subgroup_matrix.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/referenced_module_vars.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/spirv/writer/common/option_helpers.h" +#include "src/tint/lang/spirv/writer/printer/printer.h" +#include "src/tint/lang/spirv/writer/raise/raise.h" + +// Included by 'ast_printer.h', included again here for './tools/run gen' track the dependency. +#include "spirv/unified1/spirv.h" // IWYU pragma: export + +namespace tint::spirv::writer { + +Result CanGenerate(const core::ir::Module& ir, const Options& options) { + // The enum is accessible in the API so ensure we have a valid value. + switch (options.spirv_version) { + case SpvVersion::kSpv13: + case SpvVersion::kSpv14: + case SpvVersion::kSpv15: + break; + default: + return Failure("unsupported SPIR-V version"); + } + + // Check optionally supported types against their required options. + for (auto* ty : ir.Types()) { + if (ty->Is()) { + if (!options.extensions.use_vulkan_memory_model) { + return Failure("using subgroup matrices requires the Vulkan Memory Model"); + } + } + if (ty->Is()) { + return Failure("buffers are not supported by the SPIR-V backend"); + } + } + + // If a remapped entry point name is provided, it must not be empty, and must not contain + // embedded null characters. + if (!options.remapped_entry_point_name.empty()) { + if (options.remapped_entry_point_name.find('\0') != std::string::npos) { + return Failure("remapped entry point name contains null character"); + } + + // Check for multiple entry points. + // TODO(375388101): Remove this check when SingleEntryPoint is part of the backend. + bool has_entry_point = false; + for (auto& func : ir.functions) { + if (func->IsEntryPoint()) { + if (has_entry_point) { + return Failure("module must only contain a single entry point"); + } + has_entry_point = true; + } + } + } + + core::ir::Function* ep_func = nullptr; + for (auto* f : ir.functions) { + if (!f->IsEntryPoint()) { + continue; + } + if (ir.NameOf(f).NameView() == options.entry_point_name) { + ep_func = f; + break; + } + } + + // No entrypoint, so no bindings needed + if (!ep_func) { + return Failure("entry point not found"); + } + + core::ir::ReferencedModuleVars referenced_module_vars{ir}; + auto& refs = referenced_module_vars.TransitiveReferences(ep_func); + + // Check for unsupported module-scope variable address spaces. + for (auto* var : refs) { + auto* ptr = var->Result()->Type()->As(); + if (ptr->AddressSpace() == core::AddressSpace::kPixelLocal) { + return Failure("pixel_local address space is not supported by the SPIR-V backend"); + } + } + + // Check for calls to unsupported builtin functions. + for (auto* inst : ir.Instructions()) { + auto* call = inst->As(); + if (!call) { + continue; + } + + if (call->Func() == core::BuiltinFn::kPrint) { + return Failure("print is not supported by the SPIR-V backend"); + } + if (call->Func() == core::BuiltinFn::kHasResource || + call->Func() == core::BuiltinFn::kGetResource) { + if (!options.resource_table) { + return Failure("hasResource and getResource require a resource table"); + } + } + } + + // Check for unsupported shader IO builtins. + auto check_io_attributes = [&](const core::IOAttributes& attributes) -> Result { + if (attributes.color.has_value()) { + return Failure("@color attribute is not supported by the SPIR-V backend"); + } + return Success; + }; + // Check input attributes. + for (auto* param : ep_func->Params()) { + if (auto* str = param->Type()->As()) { + for (auto* member : str->Members()) { + TINT_CHECK_RESULT(check_io_attributes(member->Attributes())); + } + } else { + TINT_CHECK_RESULT(check_io_attributes(param->Attributes())); + } + } + // Check output attributes. + if (auto* str = ep_func->ReturnType()->As()) { + for (auto* member : str->Members()) { + TINT_CHECK_RESULT(check_io_attributes(member->Attributes())); + } + } else { + TINT_CHECK_RESULT(check_io_attributes(ep_func->ReturnAttributes())); + } + + TINT_CHECK_RESULT(ValidateBindingOptions(options)); + + return Success; +} + +Result Generate(core::ir::Module& ir, const Options& options) { + // There are currently no plans on supporting override-expressions, so we can pull this + // information out before the raise. If we want to support overrides then this either needs to + // happen in raise, before the builtins are polyfilled, or the analysis needs to also look for + // `*` operations with subgroup matrices. + auto sm_info = core::ir::analysis::GatherSubgroupMatrixInfo(ir); + + // Raise from core-dialect to SPIR-V-dialect. + TINT_CHECK_RESULT(Raise(ir, options)); + + TINT_CHECK_RESULT_UNWRAP(res, Print(ir, options)); + res.subgroup_matrix_info = sm_info; + + return res; +} + +} // namespace tint::spirv::writer diff --git a/3rdparty/dawn/src/tint/lang/spirv/writer/writer.h b/3rdparty/dawn/src/tint/lang/spirv/writer/writer.h new file mode 100644 index 000000000..33c7873ea --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/spirv/writer/writer.h @@ -0,0 +1,53 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_SPIRV_WRITER_WRITER_H_ +#define SRC_TINT_LANG_SPIRV_WRITER_WRITER_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/spirv/writer/common/options.h" +#include "src/tint/lang/spirv/writer/common/output.h" +#include "src/tint/utils/result.h" + +namespace tint::spirv::writer { + +/// Check if the module @p ir is supported by the SPIR-V backend with @p options. +/// @param ir the module +/// @param options the writer options +/// @returns Success or a failure message indicating why SPIR-V generation would fail +Result CanGenerate(const core::ir::Module& ir, const Options& options); + +/// Generate SPIR-V for a program, according to a set of configuration options. +/// The result will contain the SPIR-V or failure. +/// @param ir the IR module to translate to SPIR-V +/// @param options the configuration options to use when generating SPIR-V +/// @returns the resulting SPIR-V and supplementary information, or failure. +Result Generate(core::ir::Module& ir, const Options& options); + +} // namespace tint::spirv::writer + +#endif // SRC_TINT_LANG_SPIRV_WRITER_WRITER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/allowed_features.h b/3rdparty/dawn/src/tint/lang/wgsl/allowed_features.h new file mode 100644 index 000000000..4d4ae4bc7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/allowed_features.h @@ -0,0 +1,70 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_ALLOWED_FEATURES_H_ +#define SRC_TINT_LANG_WGSL_ALLOWED_FEATURES_H_ + +#include + +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/utils/reflection.h" + +namespace tint::wgsl { + +/// AllowedFeatures describes the set of extensions and language features that are allowed by the +/// current environment. +struct AllowedFeatures { + /// The extensions that are allowed. + std::unordered_set extensions; + /// The language features that are allowed. + std::unordered_set features; + + /// Helper to produce an AllowedFeatures object that allows all extensions and features. + /// @returns the AllowedFeatures object + static AllowedFeatures Everything() { + AllowedFeatures allowed_features; + + // Allow all extensions. + for (auto extension : wgsl::kAllExtensions) { + allowed_features.extensions.insert(extension); + } + + // Allow all language features. + for (auto feature : wgsl::kAllLanguageFeatures) { + allowed_features.features.insert(feature); + } + + return allowed_features; + } + + /// Reflect the fields of this class so that it can be used by tint::ForeachField(). + TINT_REFLECT(AllowedFeatures, extensions, features); +}; + +} // namespace tint::wgsl + +#endif // SRC_TINT_LANG_WGSL_ALLOWED_FEATURES_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.cc new file mode 100644 index 000000000..4b6ab2030 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.cc @@ -0,0 +1,43 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/accessor_expression.h" + +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::AccessorExpression); + +namespace tint::ast { + +AccessorExpression::AccessorExpression(NodeID nid, const Source& src, const Expression* obj) + : Base(nid, src), object(obj) { + TINT_ASSERT(object); +} + +AccessorExpression::~AccessorExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.h new file mode 100644 index 000000000..4d6dc8908 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/accessor_expression.h @@ -0,0 +1,53 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_ACCESSOR_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_ACCESSOR_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// Base class for IndexAccessorExpression and MemberAccessorExpression +class AccessorExpression : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the member accessor expression source + /// @param object the object + AccessorExpression(NodeID nid, const Source& source, const Expression* object); + + /// Destructor + ~AccessorExpression() override; + + /// The object being accessed + const Expression* const object; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_ACCESSOR_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/alias.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/alias.cc new file mode 100644 index 000000000..9ef7d6915 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/alias.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/alias.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Alias); + +namespace tint::ast { + +Alias::Alias(NodeID nid, const Source& src, const Identifier* n, Type subtype) + : Base(nid, src, n), type(subtype) { + TINT_ASSERT(type); +} + +Alias::~Alias() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/alias.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/alias.h new file mode 100644 index 000000000..8ee7b8b09 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/alias.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_ALIAS_H_ +#define SRC_TINT_LANG_WGSL_AST_ALIAS_H_ + +#include + +#include "src/tint/lang/wgsl/ast/type.h" +#include "src/tint/lang/wgsl/ast/type_decl.h" + +namespace tint::ast { + +/// A type alias type. Holds a name and pointer to another type. +class Alias final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param name the symbol for the alias + /// @param subtype the alias'd type + Alias(NodeID nid, const Source& src, const Identifier* name, Type subtype); + + /// Destructor + ~Alias() override; + + /// the alias type + const Type type; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_ALIAS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.cc new file mode 100644 index 000000000..41960a88c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.cc @@ -0,0 +1,47 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/assignment_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::AssignmentStatement); + +namespace tint::ast { + +AssignmentStatement::AssignmentStatement(NodeID nid, + const Source& src, + const Expression* l, + const Expression* r) + : Base(nid, src), lhs(l), rhs(r) { + TINT_ASSERT(lhs); + TINT_ASSERT(rhs); +} + +AssignmentStatement::~AssignmentStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.h new file mode 100644 index 000000000..21bbdc82d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/assignment_statement.h @@ -0,0 +1,61 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_ASSIGNMENT_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_ASSIGNMENT_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// An assignment statement +class AssignmentStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the assignment statement source + /// @param lhs the left side of the expression + /// @param rhs the right side of the expression + AssignmentStatement(NodeID nid, + const Source& source, + const Expression* lhs, + const Expression* rhs); + + /// Destructor + ~AssignmentStatement() override; + + /// left side expression + const Expression* const lhs; + + /// right side expression + const Expression* const rhs; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_ASSIGNMENT_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.cc new file mode 100644 index 000000000..e02da0c5b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.cc @@ -0,0 +1,36 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/attribute.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Attribute); + +namespace tint::ast { + +Attribute::~Attribute() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.h new file mode 100644 index 000000000..706b78cd6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/attribute.h @@ -0,0 +1,79 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/node.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint::ast { + +/// The base class for all attributes +class Attribute : public Castable { + public: + ~Attribute() override; + + /// @returns the WGSL name for the attribute + virtual std::string Name() const = 0; + + protected: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + Attribute(NodeID nid, const Source& src) : Base(nid, src) {} +}; + +/// @param attributes the list of attributes to search +/// @returns true if `attributes` includes a attribute of type `T` +template +bool HasAttribute(VectorRef attributes) { + for (auto* attr : attributes) { + if (attr->IsAnyOf()) { + return true; + } + } + return false; +} + +/// @param attributes the list of attributes to search +/// @returns a pointer to `T` from `attributes` if found, otherwise nullptr. +template +const T* GetAttribute(VectorRef attributes) { + for (auto* attr : attributes) { + if (attr->Is()) { + return attr->As(); + } + } + return nullptr; +} + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.cc new file mode 100644 index 000000000..9b175ed73 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.cc @@ -0,0 +1,48 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/binary_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BinaryExpression); + +namespace tint::ast { + +BinaryExpression::BinaryExpression(NodeID nid, + const Source& src, + core::BinaryOp o, + const Expression* l, + const Expression* r) + : Base(nid, src), op(o), lhs(l), rhs(r) { + TINT_ASSERT(lhs); + TINT_ASSERT(rhs); +} + +BinaryExpression::~BinaryExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.h new file mode 100644 index 000000000..317a694ac --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/binary_expression.h @@ -0,0 +1,291 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BINARY_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_BINARY_EXPRESSION_H_ + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// An binary expression +class BinaryExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the binary expression source + /// @param op the operation type + /// @param lhs the left side of the expression + /// @param rhs the right side of the expression + BinaryExpression(NodeID nid, + const Source& source, + core::BinaryOp op, + const Expression* lhs, + const Expression* rhs); + /// Move constructor + BinaryExpression(BinaryExpression&&); + ~BinaryExpression() override; + + /// @returns true if the op is and + bool IsAnd() const { return op == core::BinaryOp::kAnd; } + /// @returns true if the op is or + bool IsOr() const { return op == core::BinaryOp::kOr; } + /// @returns true if the op is xor + bool IsXor() const { return op == core::BinaryOp::kXor; } + /// @returns true if the op is logical and + bool IsLogicalAnd() const { return op == core::BinaryOp::kLogicalAnd; } + /// @returns true if the op is logical or + bool IsLogicalOr() const { return op == core::BinaryOp::kLogicalOr; } + /// @returns true if the op is equal + bool IsEqual() const { return op == core::BinaryOp::kEqual; } + /// @returns true if the op is not equal + bool IsNotEqual() const { return op == core::BinaryOp::kNotEqual; } + /// @returns true if the op is less than + bool IsLessThan() const { return op == core::BinaryOp::kLessThan; } + /// @returns true if the op is greater than + bool IsGreaterThan() const { return op == core::BinaryOp::kGreaterThan; } + /// @returns true if the op is less than equal + bool IsLessThanEqual() const { return op == core::BinaryOp::kLessThanEqual; } + /// @returns true if the op is greater than equal + bool IsGreaterThanEqual() const { return op == core::BinaryOp::kGreaterThanEqual; } + /// @returns true if the op is shift left + bool IsShiftLeft() const { return op == core::BinaryOp::kShiftLeft; } + /// @returns true if the op is shift right + bool IsShiftRight() const { return op == core::BinaryOp::kShiftRight; } + /// @returns true if the op is add + bool IsAdd() const { return op == core::BinaryOp::kAdd; } + /// @returns true if the op is subtract + bool IsSubtract() const { return op == core::BinaryOp::kSubtract; } + /// @returns true if the op is multiply + bool IsMultiply() const { return op == core::BinaryOp::kMultiply; } + /// @returns true if the op is divide + bool IsDivide() const { return op == core::BinaryOp::kDivide; } + /// @returns true if the op is modulo + bool IsModulo() const { return op == core::BinaryOp::kModulo; } + /// @returns true if the op is an arithmetic operation + bool IsArithmetic() const; + /// @returns true if the op is a comparison operation + bool IsComparison() const; + /// @returns true if the op is a bitwise operation + bool IsBitwise() const; + /// @returns true if the op is a bit shift operation + bool IsBitshift() const; + /// @returns true if the op is a logical expression + bool IsLogical() const; + + /// the binary op type + const core::BinaryOp op; + /// the left side expression + const Expression* const lhs; + /// the right side expression + const Expression* const rhs; +}; + +/// @param op the operator +/// @returns true if the op is an arithmetic operation +inline bool IsArithmetic(core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kAdd: + case core::BinaryOp::kSubtract: + case core::BinaryOp::kMultiply: + case core::BinaryOp::kDivide: + case core::BinaryOp::kModulo: + return true; + default: + return false; + } +} + +/// @param op the operator +/// @returns true if the op is a comparison operation +inline bool IsComparison(core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kEqual: + case core::BinaryOp::kNotEqual: + case core::BinaryOp::kLessThan: + case core::BinaryOp::kLessThanEqual: + case core::BinaryOp::kGreaterThan: + case core::BinaryOp::kGreaterThanEqual: + return true; + default: + return false; + } +} + +/// @param op the operator +/// @returns true if the op is a bitwise operation +inline bool IsBitwise(core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kAnd: + case core::BinaryOp::kOr: + case core::BinaryOp::kXor: + return true; + default: + return false; + } +} + +/// @param op the operator +/// @returns true if the op is a bit shift operation +inline bool IsBitshift(core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kShiftLeft: + case core::BinaryOp::kShiftRight: + return true; + default: + return false; + } +} + +inline bool BinaryExpression::IsLogical() const { + switch (op) { + case core::BinaryOp::kLogicalAnd: + case core::BinaryOp::kLogicalOr: + return true; + default: + return false; + } +} + +inline bool BinaryExpression::IsArithmetic() const { + return ast::IsArithmetic(op); +} + +inline bool BinaryExpression::IsComparison() const { + return ast::IsComparison(op); +} + +inline bool BinaryExpression::IsBitwise() const { + return ast::IsBitwise(op); +} + +inline bool BinaryExpression::IsBitshift() const { + return ast::IsBitshift(op); +} + +/// @returns the human readable name of the given core::BinaryOp +/// @param op the core::BinaryOp +constexpr const char* FriendlyName(core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kAnd: + return "and"; + case core::BinaryOp::kOr: + return "or"; + case core::BinaryOp::kXor: + return "xor"; + case core::BinaryOp::kLogicalAnd: + return "logical_and"; + case core::BinaryOp::kLogicalOr: + return "logical_or"; + case core::BinaryOp::kEqual: + return "equal"; + case core::BinaryOp::kNotEqual: + return "not_equal"; + case core::BinaryOp::kLessThan: + return "less_than"; + case core::BinaryOp::kGreaterThan: + return "greater_than"; + case core::BinaryOp::kLessThanEqual: + return "less_than_equal"; + case core::BinaryOp::kGreaterThanEqual: + return "greater_than_equal"; + case core::BinaryOp::kShiftLeft: + return "shift_left"; + case core::BinaryOp::kShiftRight: + return "shift_right"; + case core::BinaryOp::kAdd: + return "add"; + case core::BinaryOp::kSubtract: + return "subtract"; + case core::BinaryOp::kMultiply: + return "multiply"; + case core::BinaryOp::kDivide: + return "divide"; + case core::BinaryOp::kModulo: + return "modulo"; + } + return ""; +} + +/// @returns the WGSL operator of the core::BinaryOp +/// @param op the core::BinaryOp +constexpr const char* Operator(core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kAnd: + return "&"; + case core::BinaryOp::kOr: + return "|"; + case core::BinaryOp::kXor: + return "^"; + case core::BinaryOp::kLogicalAnd: + return "&&"; + case core::BinaryOp::kLogicalOr: + return "||"; + case core::BinaryOp::kEqual: + return "=="; + case core::BinaryOp::kNotEqual: + return "!="; + case core::BinaryOp::kLessThan: + return "<"; + case core::BinaryOp::kGreaterThan: + return ">"; + case core::BinaryOp::kLessThanEqual: + return "<="; + case core::BinaryOp::kGreaterThanEqual: + return ">="; + case core::BinaryOp::kShiftLeft: + return "<<"; + case core::BinaryOp::kShiftRight: + return ">>"; + case core::BinaryOp::kAdd: + return "+"; + case core::BinaryOp::kSubtract: + return "-"; + case core::BinaryOp::kMultiply: + return "*"; + case core::BinaryOp::kDivide: + return "/"; + case core::BinaryOp::kModulo: + return "%"; + } + return ""; +} + +/// @param out the stream to write to +/// @param op the core::BinaryOp +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, core::BinaryOp op) { + out << FriendlyName(op); + return out; +} + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BINARY_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.cc new file mode 100644 index 000000000..2da958f1c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.cc @@ -0,0 +1,47 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/binding_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BindingAttribute); + +namespace tint::ast { + +BindingAttribute::BindingAttribute(NodeID nid, const Source& src, const Expression* exp) + : Base(nid, src), expr(exp) {} + +BindingAttribute::~BindingAttribute() = default; + +std::string BindingAttribute::Name() const { + return "binding"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.h new file mode 100644 index 000000000..0645810d6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/binding_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BINDING_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_BINDING_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A binding attribute +class BindingAttribute final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the binding expression + BindingAttribute(NodeID nid, const Source& src, const Expression* expr); + ~BindingAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// the binding expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BINDING_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.cc new file mode 100644 index 000000000..a76d40452 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.cc @@ -0,0 +1,47 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/blend_src_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BlendSrcAttribute); + +namespace tint::ast { + +BlendSrcAttribute::BlendSrcAttribute(NodeID nid, const Source& src, const Expression* exp) + : Base(nid, src), expr(exp) {} + +BlendSrcAttribute::~BlendSrcAttribute() = default; + +std::string BlendSrcAttribute::Name() const { + return "blend_src"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.h new file mode 100644 index 000000000..8c63fbe8c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/blend_src_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BLEND_SRC_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_BLEND_SRC_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// An blend_src attribute for shader IO. +class BlendSrcAttribute final : public Castable { + public: + /// Create a blend_src ttribute. + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the numeric id expression + BlendSrcAttribute(NodeID nid, const Source& src, const Expression* expr); + ~BlendSrcAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The blend_src expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BLEND_SRC_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.cc new file mode 100644 index 000000000..577f4ae4a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.cc @@ -0,0 +1,51 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/block_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BlockStatement); + +namespace tint::ast { + +BlockStatement::BlockStatement(NodeID nid, + const Source& src, + VectorRef stmts, + VectorRef attrs) + : Base(nid, src), statements(std::move(stmts)), attributes(attrs) { + for (auto* stmt : statements) { + TINT_ASSERT(stmt); + } + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +BlockStatement::~BlockStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.h new file mode 100644 index 000000000..56f04348a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/block_statement.h @@ -0,0 +1,75 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BLOCK_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_BLOCK_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/ast/statement.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/diagnostic/source.h" + +// Forward declarations +namespace tint::ast { +class Attribute; +} // namespace tint::ast + +namespace tint::ast { + +/// A block statement +class BlockStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the block statement source + /// @param statements the statements + /// @param attributes the block statement attributes + BlockStatement(NodeID nid, + const Source& source, + VectorRef statements, + VectorRef attributes); + + /// Destructor + ~BlockStatement() override; + + /// @returns true if the block has no statements + bool Empty() const { return statements.IsEmpty(); } + + /// @returns the last statement in the block or nullptr if block empty + const Statement* Last() const { return statements.IsEmpty() ? nullptr : statements.Back(); } + + /// the statement list + const tint::Vector statements; + + /// the attribute list + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BLOCK_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.cc new file mode 100644 index 000000000..5314756b8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.cc @@ -0,0 +1,41 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/bool_literal_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BoolLiteralExpression); + +namespace tint::ast { + +BoolLiteralExpression::BoolLiteralExpression(NodeID nid, const Source& src, bool val) + : Base(nid, src), value(val) {} + +BoolLiteralExpression::~BoolLiteralExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.h new file mode 100644 index 000000000..d285c178c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/bool_literal_expression.h @@ -0,0 +1,53 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BOOL_LITERAL_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_BOOL_LITERAL_EXPRESSION_H_ + +#include + +#include "src/tint/lang/wgsl/ast/literal_expression.h" + +namespace tint::ast { + +/// A boolean literal +class BoolLiteralExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param value the bool literals value + BoolLiteralExpression(NodeID nid, const Source& src, bool value); + ~BoolLiteralExpression() override; + + /// The boolean literal value + const bool value; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BOOL_LITERAL_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.cc new file mode 100644 index 000000000..e6ec458c0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.cc @@ -0,0 +1,43 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/break_if_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BreakIfStatement); + +namespace tint::ast { + +BreakIfStatement::BreakIfStatement(NodeID nid, const Source& src, const Expression* cond) + : Base(nid, src), condition(cond) { + TINT_ASSERT(condition); +} + +BreakIfStatement::~BreakIfStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.h new file mode 100644 index 000000000..b3b63566d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_if_statement.h @@ -0,0 +1,56 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BREAK_IF_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_BREAK_IF_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A break-if statement +class BreakIfStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param condition the if condition + BreakIfStatement(NodeID nid, const Source& src, const Expression* condition); + + /// Destructor + ~BreakIfStatement() override; + + /// The if condition or nullptr if none set + const Expression* const condition; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BREAK_IF_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.cc new file mode 100644 index 000000000..cefc25b22 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.cc @@ -0,0 +1,40 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/break_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BreakStatement); + +namespace tint::ast { + +BreakStatement::BreakStatement(NodeID nid, const Source& src) : Base(nid, src) {} + +BreakStatement::~BreakStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.h new file mode 100644 index 000000000..386aac12a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/break_statement.h @@ -0,0 +1,49 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BREAK_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_BREAK_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// An break statement +class BreakStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + BreakStatement(NodeID nid, const Source& src); + + /// Destructor + ~BreakStatement() override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BREAK_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/builder.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/builder.cc new file mode 100644 index 000000000..5695e7679 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/builder.cc @@ -0,0 +1,100 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/builder.h" + +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint::ast { + +Builder::VarOptions::~VarOptions() = default; +Builder::LetOptions::~LetOptions() = default; +Builder::ConstOptions::~ConstOptions() = default; +Builder::OverrideOptions::~OverrideOptions() = default; + +Builder::Builder() : ast_(ast_nodes_.Create(AllocateNodeID(), Source{})) {} + +Builder::Builder(Builder&& rhs) + : last_ast_node_id_(std::move(rhs.last_ast_node_id_)), + ast_nodes_(std::move(rhs.ast_nodes_)), + ast_(rhs.ast_), + symbols_(std::move(rhs.symbols_)), + diagnostics_(std::move(rhs.diagnostics_)) { + rhs.MarkAsMoved(); +} + +Builder::~Builder() = default; + +Builder& Builder::operator=(Builder&& rhs) { + rhs.MarkAsMoved(); + AssertNotMoved(); + last_ast_node_id_ = std::move(rhs.last_ast_node_id_); + ast_nodes_ = std::move(rhs.ast_nodes_); + ast_ = std::move(rhs.ast_); + symbols_ = std::move(rhs.symbols_); + diagnostics_ = std::move(rhs.diagnostics_); + + return *this; +} + +bool Builder::IsValid() const { + return !diagnostics_.ContainsErrors(); +} + +void Builder::MarkAsMoved() { + AssertNotMoved(); + moved_ = true; +} + +void Builder::AssertNotMoved() const { + TINT_ASSERT(!moved_) << "Attempting to use Builder after it has been moved"; +} + +Builder::TypesBuilder::TypesBuilder(Builder* pb) : builder(pb) {} + +const ast::Statement* Builder::WrapInStatement(const ast::Expression* expr) { + // Create a temporary variable of inferred type from expr. + return Decl(Let(symbols_.New(), expr)); +} + +const ast::VariableDeclStatement* Builder::WrapInStatement(const ast::Variable* v) { + return create(v); +} + +const ast::Statement* Builder::WrapInStatement(const ast::Statement* stmt) { + return stmt; +} + +const ast::Function* Builder::WrapInFunction(VectorRef stmts) { + return Func("test_function", {}, ty.void_(), std::move(stmts), + Vector{ + create(ast::PipelineStage::kCompute), + WorkgroupSize(1_u, 1_u, 1_u), + }); +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/builder.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/builder.h new file mode 100644 index 000000000..7a1b8b767 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/builder.h @@ -0,0 +1,3621 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BUILDER_H_ +#define SRC_TINT_LANG_WGSL_AST_BUILDER_H_ + +#include + +#include "src/tint/api/common/override_id.h" + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/interpolation.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/sampler_kind.h" +#include "src/tint/lang/core/type/texel_buffer.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/wgsl/ast/alias.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/binary_expression.h" +#include "src/tint/lang/wgsl/ast/binding_attribute.h" +#include "src/tint/lang/wgsl/ast/blend_src_attribute.h" +#include "src/tint/lang/wgsl/ast/bool_literal_expression.h" +#include "src/tint/lang/wgsl/ast/break_if_statement.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/case_statement.h" +#include "src/tint/lang/wgsl/ast/color_attribute.h" +#include "src/tint/lang/wgsl/ast/compound_assignment_statement.h" +#include "src/tint/lang/wgsl/ast/const.h" +#include "src/tint/lang/wgsl/ast/const_assert.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/diagnostic_attribute.h" +#include "src/tint/lang/wgsl/ast/diagnostic_control.h" +#include "src/tint/lang/wgsl/ast/diagnostic_directive.h" +#include "src/tint/lang/wgsl/ast/diagnostic_rule_name.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/enable.h" +#include "src/tint/lang/wgsl/ast/float_literal_expression.h" +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h" +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/int_literal_expression.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/invariant_attribute.h" +#include "src/tint/lang/wgsl/ast/let.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/member_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/module.h" +#include "src/tint/lang/wgsl/ast/must_use_attribute.h" +#include "src/tint/lang/wgsl/ast/override.h" +#include "src/tint/lang/wgsl/ast/parameter.h" +#include "src/tint/lang/wgsl/ast/phony_expression.h" +#include "src/tint/lang/wgsl/ast/requires.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/stage_attribute.h" +#include "src/tint/lang/wgsl/ast/struct.h" +#include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h" +#include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h" +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/ast/type.h" +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" +#include "src/tint/lang/wgsl/ast/var.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/while_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/utils/memory/block_allocator.h" +#include "src/tint/utils/symbol/symbol_table.h" +#include "src/tint/utils/text/string.h" + +#ifdef CURRENTLY_IN_TINT_PUBLIC_HEADER +#error "internal tint header being #included from tint.h" +#endif + +// Forward declarations +namespace tint::ast { +class CloneContext; +class VariableDeclStatement; +} // namespace tint::ast + +namespace tint::ast { + +/// Evaluates to true if T is a Infer, AInt or AFloat. +template +static constexpr const bool IsInferOrAbstract = + std::is_same_v, core::fluent_types::Infer> || core::IsAbstract>; + +// Forward declare metafunction that evaluates to true iff T can be wrapped in a statement. +template +struct CanWrapInStatement; + +/// Builder is a mutable builder for AST nodes. +/// To construct a Program, populate the builder and then `std::move` it to a +/// Program. +class Builder { + /// Evaluates to true if T is a Source + template + static constexpr const bool IsSource = std::is_same_v; + + /// Evaluates to true if T is a Number or bool. + template + static constexpr const bool IsScalar = + std::is_integral_v> || + std::is_floating_point_v> || std::is_same_v; + + /// Evaluates to true if T can be converted to an identifier. + template + static constexpr const bool IsIdentifierLike = std::is_same_v || // Symbol + std::is_enum_v || // Enum + traits::IsStringLike; // String + + /// A helper used to disable overloads if the first type in `TYPES` is a Source. Used to avoid + /// ambiguities in overloads that take a Source as the first parameter and those that + /// perfectly-forward the first argument. + template + using DisableIfSource = + std::enable_if_t>>>; + + /// A helper used to disable overloads if the first type in `TYPES` is a scalar type. Used to + /// avoid ambiguities in overloads that take a scalar as the first parameter and those that + /// perfectly-forward the first argument. + template + using DisableIfScalar = + std::enable_if_t>>>; + + /// A helper used to enable overloads if the first type in `TYPES` is a scalar type. Used to + /// avoid ambiguities in overloads that take a scalar as the first parameter and those that + /// perfectly-forward the first argument. + template + using EnableIfScalar = + std::enable_if_t>>>; + + /// A helper used to disable overloads if the first type in `TYPES` is a Vector or + /// VectorRef. + template + using DisableIfVectorLike = + std::enable_if_t>>>; + + /// A helper used to enable overloads if the first type in `TYPES` is identifier-like. + template + using EnableIfIdentifierLike = + std::enable_if_t>>>; + + /// A helper used to disable overloads if the first type in `TYPES` is Infer or an abstract + /// numeric. + template + using DisableIfInferOrAbstract = + std::enable_if_t>>>; + + /// VarOptions is a helper for accepting an arbitrary number of order independent options for + /// constructing an ast::Var. + struct VarOptions { + template + explicit VarOptions(Builder& b, ARGS&&... args) { + (Set(b, std::forward(args)), ...); + } + ~VarOptions(); + + ast::Type type; + const ast::Expression* address_space = nullptr; + const ast::Expression* access = nullptr; + const ast::Expression* initializer = nullptr; + Vector attributes; + + private: + void Set(Builder&, ast::Type t) { type = t; } + void Set(Builder& b, core::AddressSpace addr_space) { + if (addr_space != core::AddressSpace::kUndefined) { + address_space = b.Expr(addr_space); + } + } + void Set(Builder& b, core::Access ac) { + if (ac != core::Access::kUndefined) { + access = b.Expr(ac); + } + } + void Set(Builder&, const ast::Expression* c) { initializer = c; } + void Set(Builder&, VectorRef l) { attributes = std::move(l); } + void Set(Builder&, const ast::Attribute* a) { attributes.Push(a); } + }; + + /// LetOptions is a helper for accepting an arbitrary number of order independent options for + /// constructing an ast::Let. + struct LetOptions { + template + explicit LetOptions(ARGS&&... args) { + static constexpr bool has_init = + (traits::IsTypeOrDerived, ast::Expression> || ...); + static_assert(has_init, "Let() must be constructed with an initializer expression"); + (Set(std::forward(args)), ...); + } + ~LetOptions(); + + ast::Type type; + const ast::Expression* initializer = nullptr; + Vector attributes; + + private: + void Set(ast::Type t) { type = t; } + void Set(const ast::Expression* c) { initializer = c; } + void Set(VectorRef l) { attributes = std::move(l); } + void Set(const ast::Attribute* a) { attributes.Push(a); } + }; + + /// ConstOptions is a helper for accepting an arbitrary number of order independent options for + /// constructing an ast::Const. + struct ConstOptions { + template + explicit ConstOptions(ARGS&&... args) { + static constexpr bool has_init = + (traits::IsTypeOrDerived, ast::Expression> || ...); + static_assert(has_init, "Const() must be constructed with an initializer expression"); + (Set(std::forward(args)), ...); + } + ~ConstOptions(); + + ast::Type type; + const ast::Expression* initializer = nullptr; + Vector attributes; + + private: + void Set(ast::Type t) { type = t; } + void Set(const ast::Expression* c) { initializer = c; } + void Set(VectorRef l) { attributes = std::move(l); } + void Set(const ast::Attribute* a) { attributes.Push(a); } + }; + + /// OverrideOptions is a helper for accepting an arbitrary number of order independent options + /// for constructing an ast::Override. + struct OverrideOptions { + template + explicit OverrideOptions(ARGS&&... args) { + (Set(std::forward(args)), ...); + } + ~OverrideOptions(); + + ast::Type type; + const ast::Expression* initializer = nullptr; + Vector attributes; + + private: + void Set(ast::Type t) { type = t; } + void Set(const ast::Expression* c) { initializer = c; } + void Set(VectorRef l) { attributes = std::move(l); } + void Set(const ast::Attribute* a) { attributes.Push(a); } + }; + + public: + /// ASTNodeAllocator is an alias to BlockAllocator + using ASTNodeAllocator = BlockAllocator; + + /// Constructor + Builder(); + + /// Move constructor + /// @param rhs the builder to move + Builder(Builder&& rhs); + + /// Destructor + ~Builder(); + + /// Move assignment operator + /// @param rhs the builder to move + /// @return this builder + Builder& operator=(Builder&& rhs); + + /// @returns a reference to the program's AST nodes storage + ASTNodeAllocator& ASTNodes() { + AssertNotMoved(); + return ast_nodes_; + } + + /// @returns a reference to the program's AST nodes storage + const ASTNodeAllocator& ASTNodes() const { + AssertNotMoved(); + return ast_nodes_; + } + + /// @returns a reference to the program's AST root Module + ast::Module& AST() { + AssertNotMoved(); + return *ast_; + } + + /// @returns a reference to the program's AST root Module + const ast::Module& AST() const { + AssertNotMoved(); + return *ast_; + } + + /// @returns a reference to the program's SymbolTable + SymbolTable& Symbols() { + AssertNotMoved(); + return symbols_; + } + + /// @returns a reference to the program's SymbolTable + const SymbolTable& Symbols() const { + AssertNotMoved(); + return symbols_; + } + + /// @returns a reference to the program's diagnostics + diag::List& Diagnostics() { + AssertNotMoved(); + return diagnostics_; + } + + /// @returns a reference to the program's diagnostics + const diag::List& Diagnostics() const { + AssertNotMoved(); + return diagnostics_; + } + + /// @returns true if the program has no error diagnostics and is not missing + /// information + bool IsValid() const; + + /// @returns the last allocated (numerically highest) AST node identifier. + ast::NodeID LastAllocatedNodeID() const { return last_ast_node_id_; } + + /// @returns the next sequentially unique node identifier. + ast::NodeID AllocateNodeID() { + auto out = ast::NodeID{last_ast_node_id_.value + 1}; + last_ast_node_id_ = out; + return out; + } + + /// Creates a new ast::Node owned by the Builder. When the + /// Builder is destructed, the ast::Node will also be destructed. + /// @param source the Source of the node + /// @param args the arguments to pass to the constructor + /// @returns the node pointer + template + requires(traits::IsTypeOrDerived) + T* create(const Source& source, ARGS&&... args) { + AssertNotMoved(); + return ast_nodes_.Create(AllocateNodeID(), source, std::forward(args)...); + } + + /// Creates a new ast::Node owned by the Builder, injecting the current + /// Source as set by the last call to SetSource() as the only argument to the + /// constructor. + /// When the Builder is destructed, the ast::Node will also be + /// destructed. + /// @returns the node pointer + template + requires(traits::IsTypeOrDerived) + T* create() { + AssertNotMoved(); + return ast_nodes_.Create(AllocateNodeID(), source_); + } + + /// Creates a new ast::Node owned by the Builder, injecting the current + /// Source as set by the last call to SetSource() as the first argument to the + /// constructor. + /// When the Builder is destructed, the ast::Node will also be + /// destructed. + /// @param arg0 the first arguments to pass to the constructor + /// @param args the remaining arguments to pass to the constructor + /// @returns the node pointer + template + std::enable_if_t && + !traits::IsTypeOrDerived, + T>* + create(ARG0&& arg0, ARGS&&... args) { + AssertNotMoved(); + return ast_nodes_.Create(AllocateNodeID(), source_, std::forward(arg0), + std::forward(args)...); + } + + /// Marks this builder as moved, preventing any further use of the builder. + void MarkAsMoved(); + + ////////////////////////////////////////////////////////////////////////////// + // TypesBuilder + ////////////////////////////////////////////////////////////////////////////// + + /// TypesBuilder holds basic `tint` types and methods for constructing + /// complex types. + class TypesBuilder { + public: + /// Constructor + /// @param builder the program builder + explicit TypesBuilder(Builder* builder); + + /// @return the C type `T`. + template + ast::Type Of() const { + return CToAST::get(this); + } + + /// @param type the type to return + /// @return type (passthrough) + ast::Type operator()(const ast::Type& type) const { return type; } + + /// Creates a type + /// @param name the name + /// @param args the optional template arguments + /// @returns the type + template , + typename = std::enable_if_t, ast::Type>>> + ast::Type operator()(NAME&& name, ARGS&&... args) const { + if constexpr (traits::IsTypeOrDerived, ast::Expression>) { + static_assert(sizeof...(ARGS) == 0); + return {name}; + } else { + return {builder->Expr( + builder->Ident(std::forward(name), std::forward(args)...))}; + } + } + + /// Creates a type + /// @param source the Source of the node + /// @param name the name + /// @param args the optional template arguments + /// @returns the type + template , ast::Type>>> + ast::Type operator()(const Source& source, NAME&& name, ARGS&&... args) const { + return {builder->Expr( + builder->Ident(source, std::forward(name), std::forward(args)...))}; + } + + /// @returns a a nullptr expression wrapped in an ast::Type + ast::Type void_() const { return ast::Type{}; } + + /// @returns a 'bool' type + ast::Type bool_() const { return (*this)("bool"); } + + /// @param source the Source of the node + /// @returns a 'bool' type + ast::Type bool_(const Source& source) const { return (*this)(source, "bool"); } + + /// @returns a 'f16' type + ast::Type f16() const { return (*this)("f16"); } + + /// @param source the Source of the node + /// @returns a 'f16' type + ast::Type f16(const Source& source) const { return (*this)(source, "f16"); } + + /// @returns a 'f32' type + ast::Type f32() const { return (*this)("f32"); } + + /// @param source the Source of the node + /// @returns a 'f32' type + ast::Type f32(const Source& source) const { return (*this)(source, "f32"); } + + /// @returns a 'i32' type + ast::Type i32() const { return (*this)("i32"); } + + /// @param source the Source of the node + /// @returns a 'i32' type + ast::Type i32(const Source& source) const { return (*this)(source, "i32"); } + + /// @returns a 'u32' type + ast::Type u32() const { return (*this)("u32"); } + + /// @param source the Source of the node + /// @returns a 'u32' type + ast::Type u32(const Source& source) const { return (*this)(source, "u32"); } + + /// @returns a 'i8' type + ast::Type i8() const { return (*this)("i8"); } + + /// @param source the Source of the node + /// @returns a 'i8' type + ast::Type i8(const Source& source) const { return (*this)(source, "i8"); } + + /// @returns a 'u8' type + ast::Type u8() const { return (*this)("u8"); } + + /// @param source the Source of the node + /// @returns a 'u8' type + ast::Type u8(const Source& source) const { return (*this)(source, "u8"); } + + /// @param type vector subtype + /// @param n vector width in elements + /// @return a @p n element vector of @p type + ast::Type vec(ast::Type type, uint32_t n) const { return vec(builder->source_, type, n); } + + /// @param source the Source of the node + /// @param type vector subtype + /// @param n vector width in elements + /// @return a @p n element vector of @p type + ast::Type vec(const Source& source, ast::Type type, uint32_t n) const { + switch (n) { + case 2: + return vec2(source, type); + case 3: + return vec3(source, type); + case 4: + return vec4(source, type); + } + TINT_ICE() << "invalid vector width " << n; + return ast::Type{}; + } + + /// @param type vector subtype + /// @return a 2-element vector of @p type + ast::Type vec2(ast::Type type) const { return vec2(builder->source_, type); } + + /// @param source the vector source + /// @param type vector subtype + /// @return a 2-element vector of @p type + ast::Type vec2(const Source& source, ast::Type type) const { + return (*this)(source, "vec2", type); + } + + /// @param type vector subtype + /// @return a 3-element vector of @p type + ast::Type vec3(ast::Type type) const { return vec3(builder->source_, type); } + + /// @param source the vector source + /// @param type vector subtype + /// @return a 3-element vector of @p type + ast::Type vec3(const Source& source, ast::Type type) const { + return (*this)(source, "vec3", type); + } + + /// @param type vector subtype + /// @return a 4-element vector of @p type + ast::Type vec4(ast::Type type) const { return vec4(builder->source_, type); } + + /// @param source the vector source + /// @param type vector subtype + /// @return a 4-element vector of @p type + ast::Type vec4(const Source& source, ast::Type type) const { + return (*this)(source, "vec4", type); + } + + /// @param source the Source of the node + /// @return a 2-element vector of the type `T` + template + ast::Type vec2(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "vec2"); + } else { + return (*this)(source, "vec2", Of()); + } + } + + /// @param source the Source of the node + /// @return a 3-element vector of the type `T` + template + ast::Type vec3(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "vec3"); + } else { + return (*this)(source, "vec3", Of()); + } + } + + /// @param source the Source of the node + /// @return a 4-element vector of the type `T` + template + ast::Type vec4(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "vec4"); + } else { + return (*this)(source, "vec4", Of()); + } + } + + /// @return a 2-element vector of the type `T` + template + ast::Type vec2() const { + return vec2(builder->source_); + } + + /// @return a 3-element vector of the type `T` + template + ast::Type vec3() const { + return vec3(builder->source_); + } + + /// @return a 4-element vector of the type `T` + template + ast::Type vec4() const { + return vec4(builder->source_); + } + + /// @param source the Source of the node + /// @param n vector width in elements + /// @return a @p n element vector of @p type + template + ast::Type vec(const Source& source, uint32_t n) const { + switch (n) { + case 2: + return vec2(source); + case 3: + return vec3(source); + case 4: + return vec4(source); + } + TINT_ICE() << "invalid vector width " << n; + return ast::Type{}; + } + + /// @return a @p N element vector of @p type + template + ast::Type vec() const { + return vec(builder->source_, N); + } + + /// @param n vector width in elements + /// @return a @p n element vector of @p type + template + ast::Type vec(uint32_t n) const { + return vec(builder->source_, n); + } + + /// @param type matrix subtype + /// @param columns number of columns for the matrix + /// @param rows number of rows for the matrix + /// @return a matrix of @p type + ast::Type mat(ast::Type type, uint32_t columns, uint32_t rows) const { + return mat(builder->source_, type, columns, rows); + } + + /// @param source the Source of the node + /// @param type matrix subtype + /// @param columns number of columns for the matrix + /// @param rows number of rows for the matrix + /// @return a matrix of @p type + ast::Type mat(const Source& source, ast::Type type, uint32_t columns, uint32_t rows) const { + if (DAWN_LIKELY(columns >= 2 && columns <= 4 && rows >= 2 && rows <= 4)) { + static constexpr std::array names = { + "mat2x2", "mat2x3", "mat2x4", // + "mat3x2", "mat3x3", "mat3x4", // + "mat4x2", "mat4x3", "mat4x4", // + }; + auto i = (columns - 2) * 3 + (rows - 2); + return (*this)(source, names[i], type); + } + TINT_ICE() << "invalid matrix dimensions " << columns << "x" << rows; + return ast::Type{}; + } + + /// @param type matrix subtype + /// @return a 2x3 matrix of @p type. + ast::Type mat2x2(ast::Type type) const { return (*this)("mat2x2", type); } + + /// @param type matrix subtype + /// @return a 2x3 matrix of @p type. + ast::Type mat2x3(ast::Type type) const { return (*this)("mat2x3", type); } + + /// @param type matrix subtype + /// @return a 2x4 matrix of @p type. + ast::Type mat2x4(ast::Type type) const { return (*this)("mat2x4", type); } + + /// @param type matrix subtype + /// @return a 3x2 matrix of @p type. + ast::Type mat3x2(ast::Type type) const { return (*this)("mat3x2", type); } + + /// @param type matrix subtype + /// @return a 3x3 matrix of @p type. + ast::Type mat3x3(ast::Type type) const { return (*this)("mat3x3", type); } + + /// @param type matrix subtype + /// @return a 3x4 matrix of @p type. + ast::Type mat3x4(ast::Type type) const { return (*this)("mat3x4", type); } + + /// @param type matrix subtype + /// @return a 4x2 matrix of @p type. + ast::Type mat4x2(ast::Type type) const { return (*this)("mat4x2", type); } + + /// @param type matrix subtype + /// @return a 4x3 matrix of @p type. + ast::Type mat4x3(ast::Type type) const { return (*this)("mat4x3", type); } + + /// @param type matrix subtype + /// @return a 4x4 matrix of @p type. + ast::Type mat4x4(ast::Type type) const { return (*this)("mat4x4", type); } + + /// @param source the source of the type + /// @return a 2x2 matrix of the type `T` + template + ast::Type mat2x2(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat2x2"); + } else { + return (*this)(source, "mat2x2", Of()); + } + } + + /// @param source the source of the type + /// @return a 2x3 matrix of the type `T` + template + ast::Type mat2x3(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat2x3"); + } else { + return (*this)(source, "mat2x3", Of()); + } + } + + /// @param source the source of the type + /// @return a 2x4 matrix of the type `T` + template + ast::Type mat2x4(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat2x4"); + } else { + return (*this)(source, "mat2x4", Of()); + } + } + + /// @param source the source of the type + /// @return a 3x2 matrix of the type `T` + template + ast::Type mat3x2(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat3x2"); + } else { + return (*this)(source, "mat3x2", Of()); + } + } + + /// @param source the source of the type + /// @return a 3x3 matrix of the type `T` + template + ast::Type mat3x3(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat3x3"); + } else { + return (*this)(source, "mat3x3", Of()); + } + } + + /// @param source the source of the type + /// @return a 3x4 matrix of the type `T` + template + ast::Type mat3x4(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat3x4"); + } else { + return (*this)(source, "mat3x4", Of()); + } + } + + /// @param source the source of the type + /// @return a 4x2 matrix of the type `T` + template + ast::Type mat4x2(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat4x2"); + } else { + return (*this)(source, "mat4x2", Of()); + } + } + + /// @param source the source of the type + /// @return a 4x3 matrix of the type `T` + template + ast::Type mat4x3(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat4x3"); + } else { + return (*this)(source, "mat4x3", Of()); + } + } + + /// @param source the source of the type + /// @return a 4x4 matrix of the type `T` + template + ast::Type mat4x4(const Source& source) const { + if constexpr (IsInferOrAbstract) { + return (*this)(source, "mat4x4"); + } else { + return (*this)(source, "mat4x4", Of()); + } + } + + /// @return a 2x2 matrix of the type `T` + template + ast::Type mat2x2() const { + return mat2x2(builder->source_); + } + + /// @return a 2x3 matrix of the type `T` + template + ast::Type mat2x3() const { + return mat2x3(builder->source_); + } + + /// @return a 2x4 matrix of the type `T` + template + ast::Type mat2x4() const { + return mat2x4(builder->source_); + } + + /// @return a 3x2 matrix of the type `T` + template + ast::Type mat3x2() const { + return mat3x2(builder->source_); + } + + /// @return a 3x3 matrix of the type `T` + template + ast::Type mat3x3() const { + return mat3x3(builder->source_); + } + + /// @return a 3x4 matrix of the type `T` + template + ast::Type mat3x4() const { + return mat3x4(builder->source_); + } + + /// @return a 4x2 matrix of the type `T` + template + ast::Type mat4x2() const { + return mat4x2(builder->source_); + } + + /// @return a 4x3 matrix of the type `T` + template + ast::Type mat4x3() const { + return mat4x3(builder->source_); + } + + /// @return a 4x4 matrix of the type `T` + template + ast::Type mat4x4() const { + return mat4x4(builder->source_); + } + + /// @param source the Source of the node + /// @param columns number of columns for the matrix + /// @param rows number of rows for the matrix + /// @return a matrix of @p type + template + ast::Type mat(const Source& source, uint32_t columns, uint32_t rows) const { + switch ((columns - 2) * 3 + (rows - 2)) { + case 0: + return mat2x2(source); + case 1: + return mat2x3(source); + case 2: + return mat2x4(source); + case 3: + return mat3x2(source); + case 4: + return mat3x3(source); + case 5: + return mat3x4(source); + case 6: + return mat4x2(source); + case 7: + return mat4x3(source); + case 8: + return mat4x4(source); + default: + TINT_ICE() << "invalid matrix dimensions " << columns << "x" << rows; + return ast::Type{}; + } + } + + /// @param columns number of columns for the matrix + /// @param rows number of rows for the matrix + /// @return a matrix of @p type + template + ast::Type mat(uint32_t columns, uint32_t rows) const { + return mat(builder->source_, columns, rows); + } + + /// @return a matrix of @p type + template + ast::Type mat() const { + return mat(builder->source_, COLUMNS, ROWS); + } + + /// @param subtype the array element type + /// @return an array of type `T` + ast::Type array(ast::Type subtype) const { return array(builder->source_, subtype); } + + /// @param source the Source of the node + /// @param subtype the array element type + /// @return an array of type `T` + ast::Type array(const Source& source, ast::Type subtype) const { + return ast::Type{builder->Expr( + builder->create(source, builder->Sym("array"), + Vector{ + subtype.expr, + }))}; + } + + /// @param subtype the array element type + /// @param n the array size. nullptr represents a runtime-array + /// @return an array of size `n` of type `T` + template > + ast::Type array(ast::Type subtype, COUNT&& n) const { + return array(builder->source_, subtype, std::forward(n)); + } + + /// @param source the Source of the node + /// @param subtype the array element type + /// @param n the array size. nullptr represents a runtime-array + /// @return an array of size `n` of type `T` + template > + ast::Type array(const Source& source, ast::Type subtype, COUNT&& n) const { + return ast::Type{builder->Expr( + builder->create(source, builder->Sym("array"), + Vector{ + subtype.expr, + builder->Expr(std::forward(n)), + }))}; + } + + /// @param source the Source of the node + /// @return a inferred-size or runtime-sized array of type `T` + template > + ast::Type array(const Source& source) const { + if constexpr (N == 0) { + return ast::Type{builder->Expr( + builder->create(source, builder->Sym("array"), + Vector{ + Of().expr, + }))}; + } else { + return ast::Type{builder->Expr(builder->create( + source, builder->Sym("array"), + Vector{ + Of().expr, + builder->Expr(builder->source_, core::u32(N)), + }))}; + } + } + + /// @return an array of size `N` of type `T` + template + ast::Type array() const { + if constexpr (std::is_same_v) { + static_assert(N == 0, "arrays with a count cannot be inferred"); + return (*this)(builder->source_, "array"); + } else { + return array(builder->source_); + } + } + + /// Creates an alias type + /// @param name the alias name + /// @param type the alias type + /// @returns the alias pointer + template + const ast::Alias* alias(NAME&& name, ast::Type type) const { + return alias(builder->source_, std::forward(name), type); + } + + /// Creates an alias type + /// @param source the Source of the node + /// @param name the alias name + /// @param type the alias type + /// @returns the alias pointer + template + const ast::Alias* alias(const Source& source, NAME&& name, ast::Type type) const { + return builder->create(source, builder->Ident(std::forward(name)), + type); + } + + /// @param address_space the address space of the pointer + /// @param type the type of the pointer + /// @param access the optional access control of the pointer + /// @return the pointer to `type` with the given core::AddressSpace + ast::Type ptr(core::AddressSpace address_space, + ast::Type type, + core::Access access = core::Access::kUndefined) const { + return ptr(builder->source_, address_space, type, access); + } + + /// @param source the Source of the node + /// @param address_space the address space of the pointer + /// @param type the type of the pointer + /// @param access the optional access control of the pointer + /// @return the pointer to `type` with the given core::AddressSpace + ast::Type ptr(const Source& source, + core::AddressSpace address_space, + ast::Type type, + core::Access access = core::Access::kUndefined) const { + if (access != core::Access::kUndefined) { + return (*this)(source, "ptr", address_space, type, access); + } else { + return (*this)(source, "ptr", address_space, type); + } + } + + /// @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 core::AddressSpace. + template + ast::Type ptr(core::AddressSpace address_space, + core::Access access = core::Access::kUndefined) const { + return ptr(builder->source_, address_space, access); + } + + /// @param source the Source of the node + /// @return the pointer to type `T` with the core::AddressSpace `ADDRESS` and access + /// control `ACCESS`. + template + ast::Type ptr(const Source& source) const { + return ptr(source, ADDRESS, ACCESS); + } + + /// @param type the type of the pointer + /// @return the pointer to the given type with the core::AddressSpace `ADDRESS` and + /// access control `ACCESS`. + template + 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 core::AddressSpace `ADDRESS` and + /// access control `ACCESS`. + template + ast::Type ptr(const Source& source, ast::Type type) const { + return ptr(source, ADDRESS, type, ACCESS); + } + + /// @return the pointer to type `T` with the core::AddressSpace `ADDRESS` and access + /// control `ACCESS`. + template + ast::Type ptr() const { + return ptr(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` the core::AddressSpace `ADDRESS` and access control + /// `ACCESS`. + template + ast::Type ptr(const Source& source, + core::AddressSpace address_space, + core::Access access = core::Access::kUndefined) const { + if (access != core::Access::kUndefined) { + return (*this)(source, "ptr", address_space, Of(), access); + } else { + return (*this)(source, "ptr", address_space, Of()); + } + } + + /// @param source the Source of the node + /// @param type the type of the atomic + /// @return the atomic to `type` + ast::Type atomic(const Source& source, ast::Type type) const { + return (*this)(source, "atomic", type); + } + + /// @param type the type of the atomic + /// @return the atomic to `type` + ast::Type atomic(ast::Type type) const { return (*this)("atomic", type); } + + /// @return the atomic to type `T` + template + ast::Type atomic() const { + return atomic(Of()); + } + + /// @param kind the kind of sampler + /// @returns the sampler + ast::Type sampler(core::type::SamplerKind kind) const { + return sampler(builder->source_, kind); + } + + /// @param source the Source of the node + /// @param kind the kind of sampler + /// @returns the sampler + ast::Type sampler(const Source& source, core::type::SamplerKind kind) const { + switch (kind) { + case core::type::SamplerKind::kSampler: + return (*this)(source, "sampler"); + case core::type::SamplerKind::kComparisonSampler: + return (*this)(source, "sampler_comparison"); + } + TINT_ICE() << "invalid sampler kind " << kind; + return ast::Type{}; + } + + /// @param dims the dimensionality of the texture + /// @returns the depth texture + ast::Type depth_texture(core::type::TextureDimension dims) const { + return depth_texture(builder->source_, dims); + } + + /// @param source the Source of the node + /// @param dims the dimensionality of the texture + /// @returns the depth texture + ast::Type depth_texture(const Source& source, core::type::TextureDimension dims) const { + switch (dims) { + case core::type::TextureDimension::k2d: + return (*this)(source, "texture_depth_2d"); + case core::type::TextureDimension::k2dArray: + return (*this)(source, "texture_depth_2d_array"); + case core::type::TextureDimension::kCube: + return (*this)(source, "texture_depth_cube"); + case core::type::TextureDimension::kCubeArray: + return (*this)(source, "texture_depth_cube_array"); + default: + break; + } + TINT_ICE() << "invalid depth_texture dimensions: " << dims; + return ast::Type{}; + } + + /// @param dims the dimensionality of the texture + /// @returns the multisampled depth texture + ast::Type depth_multisampled_texture(core::type::TextureDimension dims) const { + return depth_multisampled_texture(builder->source_, dims); + } + + /// @param source the Source of the node + /// @param dims the dimensionality of the texture + /// @returns the multisampled depth texture + ast::Type depth_multisampled_texture(const Source& source, + core::type::TextureDimension dims) const { + if (dims == core::type::TextureDimension::k2d) { + return (*this)(source, "texture_depth_multisampled_2d"); + } + TINT_ICE() << "invalid depth_multisampled_texture dimensions: " << dims; + return ast::Type{}; + } + + /// @param dims the dimensionality of the texture + /// @param subtype the texture subtype. + /// @returns the sampled texture + ast::Type sampled_texture(core::type::TextureDimension dims, ast::Type subtype) const { + return sampled_texture(builder->source_, dims, subtype); + } + + /// @param source the Source of the node + /// @param dims the dimensionality of the texture + /// @param subtype the texture subtype. + /// @returns the sampled texture + ast::Type sampled_texture(const Source& source, + core::type::TextureDimension dims, + ast::Type subtype) const { + switch (dims) { + case core::type::TextureDimension::k1d: + return (*this)(source, "texture_1d", subtype); + case core::type::TextureDimension::k2d: + return (*this)(source, "texture_2d", subtype); + case core::type::TextureDimension::k3d: + return (*this)(source, "texture_3d", subtype); + case core::type::TextureDimension::k2dArray: + return (*this)(source, "texture_2d_array", subtype); + case core::type::TextureDimension::kCube: + return (*this)(source, "texture_cube", subtype); + case core::type::TextureDimension::kCubeArray: + return (*this)(source, "texture_cube_array", subtype); + default: + break; + } + TINT_ICE() << "invalid sampled_texture dimensions: " << dims; + return ast::Type{}; + } + + /// @param dims the dimensionality of the texture + /// @param subtype the texture subtype. + /// @returns the multisampled texture + ast::Type multisampled_texture(core::type::TextureDimension dims, ast::Type subtype) const { + return multisampled_texture(builder->source_, dims, subtype); + } + + /// @param source the Source of the node + /// @param dims the dimensionality of the texture + /// @param subtype the texture subtype. + /// @returns the multisampled texture + ast::Type multisampled_texture(const Source& source, + core::type::TextureDimension dims, + ast::Type subtype) const { + if (dims == core::type::TextureDimension::k2d) { + return (*this)(source, "texture_multisampled_2d", subtype); + } + TINT_ICE() << "invalid multisampled_texture dimensions: " << dims; + return ast::Type{}; + } + + /// @param dims the dimensionality of the texture + /// @param format the texel format of the texture + /// @param access the access control of the texture + /// @returns the storage texture + ast::Type storage_texture(core::type::TextureDimension dims, + core::TexelFormat format, + core::Access access) const { + return storage_texture(builder->source_, dims, format, access); + } + + /// @param source the Source of the node + /// @param dims the dimensionality of the texture + /// @param format the texel format of the texture + /// @param access the access control of the texture + /// @returns the storage texture + ast::Type storage_texture(const Source& source, + core::type::TextureDimension dims, + core::TexelFormat format, + core::Access access) const { + switch (dims) { + case core::type::TextureDimension::k1d: + return (*this)(source, "texture_storage_1d", format, access); + case core::type::TextureDimension::k2d: + return (*this)(source, "texture_storage_2d", format, access); + case core::type::TextureDimension::k2dArray: + return (*this)(source, "texture_storage_2d_array", format, access); + case core::type::TextureDimension::k3d: + return (*this)(source, "texture_storage_3d", format, access); + default: + break; + } + TINT_ICE() << "invalid storage_texture dimensions: " << dims; + return ast::Type{}; + } + + /// @returns the external texture + ast::Type external_texture() const { return (*this)("texture_external"); } + + /// @returns the texel buffer + ast::Type texel_buffer(core::TexelFormat format, core::Access access) const { + return (*this)("texel_buffer", format, access); + } + + /// @param subtype the texture subtype. + /// @returns the input attachment + ast::Type input_attachment(ast::Type subtype) const { + return (*this)("input_attachment", subtype); + } + + /// @param source the Source of the node + /// @returns the external texture + ast::Type external_texture(const Source& source) const { + return (*this)(source, "texture_external"); + } + + /// @param kind the subgroup matrix kind + /// @param el the subgroup matrix element type + /// @param cols the column count + /// @param rows the row count + /// @returns the subgroup matrix + ast::Type subgroup_matrix(core::SubgroupMatrixKind kind, + ast::Type el, + uint32_t cols, + uint32_t rows) const { + auto c = core::AInt(cols); + auto r = core::AInt(rows); + switch (kind) { + case core::SubgroupMatrixKind::kLeft: + return (*this)("subgroup_matrix_left", el, c, r); + case core::SubgroupMatrixKind::kRight: + return (*this)("subgroup_matrix_right", el, c, r); + case core::SubgroupMatrixKind::kResult: + return (*this)("subgroup_matrix_result", el, c, r); + case core::SubgroupMatrixKind::kUndefined: + TINT_UNREACHABLE(); + } + } + + /// @param size the buffer size (0 is unsized) + /// @returns the buffer + ast::Type buffer(uint32_t size = 0) const { + if (size == 0) { + return (*this)("buffer"); + } + auto n = core::AInt(size); + return (*this)("buffer", n); + } + + /// @param el the binding_array element type + /// @param size the number of binding array elements + /// @returns the binding array + template > + ast::Type binding_array(ast::Type el, COUNT&& size) const { + return ast::Type{builder->Expr(builder->create( + builder->source_, builder->Sym("binding_array"), + Vector{ + el.expr, + builder->Expr(std::forward(size)), + }))}; + } + + /// @param type the type + /// @return an ast::Type of the type declaration. + ast::Type Of(const ast::TypeDecl* type) const { return (*this)(type->name->symbol); } + + /// The Builder + Builder* const builder; + + private: + /// CToAST is specialized for various `T` types and each specialization + /// contains a single static `get()` method for obtaining the corresponding + /// AST type for the C type `T`. + /// `get()` has the signature: + /// `static ast::Type get(Types* t)` + template + struct CToAST {}; + }; + + ////////////////////////////////////////////////////////////////////////////// + // AST helper methods + ////////////////////////////////////////////////////////////////////////////// + + /// @return a new unnamed symbol + Symbol Sym() { return Symbols().New(); } + + /// Passthrough + /// @param sym the symbol + /// @return `sym` + Symbol Sym(Symbol sym) { return sym; } + + /// @param name the symbol string + /// @return a Symbol with the given name + Symbol Sym(std::string_view name) { return Symbols().Register(name); } + + /// @param enumerator the enumerator + /// @return a Symbol with the given enum value + template >>> + Symbol Sym(ENUM&& enumerator) { + return Sym(tint::ToString(enumerator)); + } + + /// @return nullptr + const ast::Identifier* Ident(std::nullptr_t) { return nullptr; } + + /// @param identifier the identifier symbol + /// @return an ast::Identifier with the given symbol + template + const ast::Identifier* Ident(IDENTIFIER&& identifier) { + if constexpr (traits::IsTypeOrDerived, ast::Identifier>) { + return identifier; // Passthrough + } else { + return Ident(source_, std::forward(identifier)); + } + } + + /// @param source the source information + /// @param identifier the identifier symbol + /// @return an ast::Identifier with the given symbol + template + const ast::Identifier* Ident(const Source& source, IDENTIFIER&& identifier) { + return create(source, Sym(std::forward(identifier))); + } + + /// @param identifier the identifier symbol + /// @param args the templated identifier arguments + /// @return an ast::Identifier with the given symbol and template arguments + template > + const ast::Identifier* Ident(IDENTIFIER&& identifier, ARGS&&... args) { + return Ident(source_, std::forward(identifier), std::forward(args)...); + } + + /// @param source the source information + /// @param identifier the identifier symbol + /// @param args the templated identifier arguments + /// @return an ast::Identifier with the given symbol and template arguments + template + const ast::Identifier* Ident(const Source& source, IDENTIFIER&& identifier, ARGS&&... args) { + auto arg_exprs = ExprList(std::forward(args)...); + if (arg_exprs.IsEmpty()) { + return create(source, Sym(std::forward(identifier))); + } + return create(source, Sym(std::forward(identifier)), + std::move(arg_exprs)); + } + + /// @param expr the expression + /// @return expr (passthrough) + template + requires(traits::IsTypeOrDerived) + const T* Expr(const T* expr) { + return expr; + } + + /// @param type an ast::Type + /// @return type.expr + const ast::IdentifierExpression* Expr(ast::Type type) { return type.expr; } + + /// @param ident the identifier + /// @return an ast::IdentifierExpression with the given identifier + const ast::IdentifierExpression* Expr(const ast::Identifier* ident) { + return ident ? create(ident->source, ident) : nullptr; + } + + /// Passthrough for nullptr + /// @return nullptr + const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; } + + /// @param name the identifier name + /// @return an ast::IdentifierExpression with the given name + template > + const ast::IdentifierExpression* Expr(NAME&& name) { + auto* ident = Ident(source_, name); + return create(ident->source, ident); + } + + /// @param source the source information + /// @param name the identifier name + /// @return an ast::IdentifierExpression with the given name + template > + const ast::IdentifierExpression* Expr(const Source& source, NAME&& name) { + return create(source, Ident(source, name)); + } + + /// @param variable the AST variable + /// @return an ast::IdentifierExpression with the variable's symbol + const ast::IdentifierExpression* Expr(const ast::Variable* variable) { + auto* ident = Ident(variable->source, variable->name->symbol); + return create(ident->source, ident); + } + + /// @param source the source information + /// @param variable the AST variable + /// @return an ast::IdentifierExpression with the variable's symbol + const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) { + return create(source, Ident(source, variable->name->symbol)); + } + + /// @param source the source information + /// @param value the boolean value + /// @return a Scalar constructor for the given value + template + std::enable_if_t, const ast::BoolLiteralExpression*> Expr( + const Source& source, + BOOL value) { + return create(source, value); + } + + /// @param source the source information + /// @param value the float value + /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value + const ast::FloatLiteralExpression* Expr(const Source& source, core::f32 value) { + return create(source, static_cast(value.value), + ast::FloatLiteralExpression::Suffix::kF); + } + + /// @param source the source information + /// @param value the float value + /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value + const ast::FloatLiteralExpression* Expr(const Source& source, core::f16 value) { + return create(source, static_cast(value.value), + ast::FloatLiteralExpression::Suffix::kH); + } + + /// @param source the source information + /// @param value the integer value + /// @return an unsuffixed IntLiteralExpression for the AInt value + const ast::IntLiteralExpression* Expr(const Source& source, core::AInt value) { + return create(source, value, + ast::IntLiteralExpression::Suffix::kNone); + } + + /// @param source the source information + /// @param value the integer value + /// @return an unsuffixed FloatLiteralExpression for the AFloat value + const ast::FloatLiteralExpression* Expr(const Source& source, core::AFloat value) { + return create(source, value.value, + ast::FloatLiteralExpression::Suffix::kNone); + } + + /// @param source the source information + /// @param value the integer value + /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value + const ast::IntLiteralExpression* Expr(const Source& source, core::i32 value) { + return create(source, value, + ast::IntLiteralExpression::Suffix::kI); + } + + /// @param source the source information + /// @param value the unsigned int value + /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value + const ast::IntLiteralExpression* Expr(const Source& source, core::u32 value) { + return create(source, value, + ast::IntLiteralExpression::Suffix::kU); + } + + /// @param value the scalar value + /// @return literal expression of the appropriate type + template > + const auto* Expr(SCALAR&& value) { + return Expr(source_, std::forward(value)); + } + + /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to + /// `list`. + /// @param list the list to append too + /// @param arg the arg to create + template + void Append(Vector& list, ARG&& arg) { + list.Push(Expr(std::forward(arg))); + } + + /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`, + /// then appends them to `list`. + /// @param list the list to append too + /// @param arg0 the first argument + /// @param args the rest of the arguments + template + void Append(Vector& list, ARG0&& arg0, ARGS&&... args) { + Append(list, std::forward(arg0)); + Append(list, std::forward(args)...); + } + + /// @return EmptyType + EmptyType ExprList() { return Empty; } + + /// @param args the list of expressions + /// @return the list of expressions converted to `ast::Expression`s using + /// `Expr()`, + template > + auto ExprList(ARGS&&... args) { + return Vector{Expr(args)...}; + } + + /// @param list the list of expressions + /// @return `list` + template + Vector ExprList(Vector&& list) { + return std::move(list); + } + + /// @param list the list of expressions + /// @return `list` + VectorRef ExprList(VectorRef list) { + return list; + } + + /// @param expr the expression for the bitcast + /// @return a bitcast call of type `ty`, with the values of `expr` converted to + /// `ast::Expression`s using `Expr()` + template + const ast::CallExpression* Bitcast(EXPR&& expr) { + return Bitcast(ty.Of(), std::forward(expr)); + } + + /// @param type the type to cast to + /// @param expr the expression for the bitcast + /// @return a bitcast call of @p type constructed with the values `expr`. + template + const ast::CallExpression* Bitcast(ast::Type type, EXPR&& expr) { + return Bitcast(source_, type, Expr(std::forward(expr))); + } + + /// @param source the source information + /// @param type the type to cast to + /// @param expr the expression for the bitcast + /// @return a bitcast call of @p type constructed with the values `expr`. + template + const ast::CallExpression* Bitcast(const Source& source, ast::Type type, EXPR&& expr) { + return Call(source, Ident(wgsl::BuiltinFn::kBitcast, type), Expr(std::forward(expr))); + } + + /// @param type the vector type + /// @param size the vector size + /// @param args the arguments for the vector constructor + /// @return an `ast::CallExpression` of a `size`-element vector of + /// type `type`, constructed with the values @p args. + template + const ast::CallExpression* vec(ast::Type type, uint32_t size, ARGS&&... args) { + return vec(source_, type, size, std::forward(args)...); + } + + /// @param source the source of the call + /// @param type the vector type + /// @param size the vector size + /// @param args the arguments for the vector constructor + /// @return an `ast::CallExpression` of a `size`-element vector of + /// type `type`, constructed with the values @p args. + template + const ast::CallExpression* vec(const Source& source, + ast::Type type, + uint32_t size, + ARGS&&... args) { + return Call(source, ty.vec(type, size), std::forward(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. + const ast::Enable* Enable(wgsl::Extension extension) { + auto* ext = create(extension); + auto* enable = create(Vector{ext}); + AST().AddEnable(enable); + return enable; + } + + /// Adds the extension to the list of enable directives at the top of the module. + /// @param source the enable source + /// @param extension the extension to enable + /// @return an `ast::Enable` enabling the given extension. + const ast::Enable* Enable(const Source& source, wgsl::Extension extension) { + auto* ext = create(source, extension); + auto* enable = create(source, Vector{ext}); + AST().AddEnable(enable); + return enable; + } + + /// Adds the language feature to the list of requires directives at the top of the module. + /// @param feature the feature to require + /// @return a `ast::Requires` requiring the given language feature. + const ast::Requires* Require(wgsl::LanguageFeature feature) { + auto* req = create(Requires::LanguageFeatures({feature})); + AST().AddRequires(req); + return req; + } + + /// Adds the language feature to the list of requires directives at the top of the module. + /// @param source the requires source + /// @param feature the feature to require + /// @return a `ast::Requires` requiring the given language feature. + const ast::Requires* Require(const Source& source, wgsl::LanguageFeature feature) { + auto* req = create(source, Requires::LanguageFeatures({feature})); + AST().AddRequires(req); + return req; + } + + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Type - specifies the variable's type + /// * core::AddressSpace - specifies the variable's address space + /// * core::Access - specifies the variable's access control + /// * ast::Expression* - specifies the variable's initializer expression + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns a `ast::Var` with the given name, type and additional + /// options + template > + const ast::Var* Var(NAME&& name, OPTIONS&&... options) { + return Var(source_, std::forward(name), std::forward(options)...); + } + + /// @param source the variable source + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Type - specifies the variable's type + /// * core::AddressSpace - specifies the variable's address space + /// * core::Access - specifies the variable's access control + /// * ast::Expression* - specifies the variable's initializer expression + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns a `ast::Var` with the given name, address_space and type + template + const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) { + VarOptions opts(*this, std::forward(options)...); + return create(source, Ident(std::forward(name)), opts.type, + opts.address_space, opts.access, opts.initializer, + std::move(opts.attributes)); + } + + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Const` with the given name, type and additional options + template > + const ast::Const* Const(NAME&& name, OPTIONS&&... options) { + return Const(source_, std::forward(name), std::forward(options)...); + } + + /// @param source the variable source + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Identifier* - specifies the variable's type + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Const` with the given name, type and additional options + template + const ast::Const* Const(const Source& source, NAME&& name, OPTIONS&&... options) { + ConstOptions opts(std::forward(options)...); + return create(source, Ident(std::forward(name)), opts.type, + opts.initializer, std::move(opts.attributes)); + } + + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Let` with the given name, type and additional options + template > + const ast::Let* Let(NAME&& name, OPTIONS&&... options) { + return Let(source_, std::forward(name), std::forward(options)...); + } + + /// @param source the variable source + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Let` with the given name, type and additional options + template + const ast::Let* Let(const Source& source, NAME&& name, OPTIONS&&... options) { + LetOptions opts(std::forward(options)...); + return create(source, Ident(std::forward(name)), opts.type, + opts.initializer, std::move(opts.attributes)); + } + + /// @param name the parameter name + /// @param type the parameter type + /// @param attributes optional parameter attributes + /// @returns an `ast::Parameter` with the given name and type + template + const ast::Parameter* Param(NAME&& name, + ast::Type type, + VectorRef attributes = Empty) { + return Param(source_, std::forward(name), type, std::move(attributes)); + } + + /// @param source the parameter source + /// @param name the parameter name + /// @param type the parameter type + /// @param attributes optional parameter attributes + /// @returns an `ast::Parameter` with the given name and type + template + const ast::Parameter* Param(const Source& source, + NAME&& name, + ast::Type type, + VectorRef attributes = Empty) { + return create(source, Ident(std::forward(name)), type, + std::move(attributes)); + } + + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Type - specifies the variable's type + /// * core::AddressSpace - specifies the variable address space + /// * core::Access - specifies the variable's access control + /// * ast::Expression* - specifies the variable's initializer expression + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns a new `ast::Var`, which is automatically registered as a global variable with the + /// ast::Module. + template > + const ast::Var* GlobalVar(NAME&& name, OPTIONS&&... options) { + return GlobalVar(source_, std::forward(name), std::forward(options)...); + } + + /// @param source the variable source + /// @param name the variable name + /// @param options the extra options passed to the ast::Var initializer + /// Can be any of the following, in any order: + /// * ast::Type - specifies the variable's type + /// * core::AddressSpace - specifies the variable address space + /// * core::Access - specifies the variable's access control + /// * ast::Expression* - specifies the variable's initializer expression + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns a new `ast::Var`, which is automatically registered as a global variable with the + /// ast::Module. + template + const ast::Var* GlobalVar(const Source& source, NAME&& name, OPTIONS&&... options) { + auto* variable = Var(source, std::forward(name), std::forward(options)...); + AST().AddGlobalVariable(variable); + return variable; + } + + /// @param name the variable name + /// @param options the extra options passed to the ast::Const initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Const` with the given name, type and additional options, which is + /// automatically registered as a global variable with the ast::Module. + template > + const ast::Const* GlobalConst(NAME&& name, OPTIONS&&... options) { + return GlobalConst(source_, std::forward(name), std::forward(options)...); + } + + /// @param source the variable source + /// @param name the variable name + /// @param options the extra options passed to the ast::Const initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Const` with the given name, type and additional options, which is + /// automatically registered as a global variable with the ast::Module. + template + const ast::Const* GlobalConst(const Source& source, NAME&& name, OPTIONS&&... options) { + auto* variable = Const(source, std::forward(name), std::forward(options)...); + AST().AddGlobalVariable(variable); + return variable; + } + + /// @param name the variable name + /// @param options the extra options passed to the ast::Override initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Override` with the given name, type and additional options, which is + /// automatically registered as a global variable with the ast::Module. + template > + const ast::Override* Override(NAME&& name, OPTIONS&&... options) { + return Override(source_, std::forward(name), std::forward(options)...); + } + + /// @param source the variable source + /// @param name the variable name + /// @param options the extra options passed to the ast::Override initializer + /// Can be any of the following, in any order: + /// * ast::Expression* - specifies the variable's initializer expression (required) + /// * ast::Type - specifies the variable's type + /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector) + /// Note that non-repeatable arguments of the same type will use the last argument's value. + /// @returns an `ast::Override` with the given name, type and additional options, which is + /// automatically registered as a global variable with the ast::Module. + template + const ast::Override* Override(const Source& source, NAME&& name, OPTIONS&&... options) { + OverrideOptions opts(std::forward(options)...); + auto* variable = create(source, Ident(std::forward(name)), opts.type, + opts.initializer, std::move(opts.attributes)); + AST().AddGlobalVariable(variable); + return variable; + } + + /// @param source the source information + /// @param condition the assertion condition + /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement + /// with the ast::Module. + template + const ast::ConstAssert* GlobalConstAssert(const Source& source, EXPR&& condition) { + auto* sa = ConstAssert(source, std::forward(condition)); + AST().AddConstAssert(sa); + return sa; + } + + /// @param condition the assertion condition + /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement + /// with the ast::Module. + template > + const ast::ConstAssert* GlobalConstAssert(EXPR&& condition) { + auto* sa = ConstAssert(std::forward(condition)); + AST().AddConstAssert(sa); + return sa; + } + + /// @param source the source information + /// @param condition the assertion condition + /// @returns a new `ast::ConstAssert` with the given assertion condition + template + const ast::ConstAssert* ConstAssert(const Source& source, EXPR&& condition) { + return create(source, Expr(std::forward(condition))); + } + + /// @param condition the assertion condition + /// @returns a new `ast::ConstAssert` with the given assertion condition + template > + const ast::ConstAssert* ConstAssert(EXPR&& condition) { + return create(Expr(std::forward(condition))); + } + + /// @param source the source information + /// @param expr the expression to take the address of + /// @return an ast::UnaryOpExpression that takes the address of `expr` + template + const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) { + return create(source, core::UnaryOp::kAddressOf, + Expr(std::forward(expr))); + } + + /// @param expr the expression to take the address of + /// @return an ast::UnaryOpExpression that takes the address of `expr` + template + const ast::UnaryOpExpression* AddressOf(EXPR&& expr) { + return create(core::UnaryOp::kAddressOf, + Expr(std::forward(expr))); + } + + /// @param source the source information + /// @param expr the expression to perform an indirection on + /// @return an ast::UnaryOpExpression that dereferences the pointer `expr` + template + const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) { + return create(source, core::UnaryOp::kIndirection, + Expr(std::forward(expr))); + } + + /// @param expr the expression to perform an indirection on + /// @return an ast::UnaryOpExpression that dereferences the pointer `expr` + template + const ast::UnaryOpExpression* Deref(EXPR&& expr) { + return create(core::UnaryOp::kIndirection, + Expr(std::forward(expr))); + } + + /// @param expr the expression to perform a unary not on + /// @return an ast::UnaryOpExpression that is the unary not of the input + /// expression + template + const ast::UnaryOpExpression* Not(EXPR&& expr) { + return create(core::UnaryOp::kNot, Expr(std::forward(expr))); + } + + /// @param source the source information + /// @param expr the expression to perform a unary not on + /// @return an ast::UnaryOpExpression that is the unary not of the input + /// expression + template + const ast::UnaryOpExpression* Not(const Source& source, EXPR&& expr) { + return create(source, core::UnaryOp::kNot, + Expr(std::forward(expr))); + } + + /// @param expr the expression to perform a unary complement on + /// @return an ast::UnaryOpExpression that is the unary complement of the + /// input expression + template + const ast::UnaryOpExpression* Complement(EXPR&& expr) { + return create(core::UnaryOp::kComplement, + Expr(std::forward(expr))); + } + + /// @param expr the expression to perform a unary negation on + /// @return an ast::UnaryOpExpression that is the unary negation of the + /// input expression + template + const ast::UnaryOpExpression* Negation(EXPR&& expr) { + return create(core::UnaryOp::kNegation, + Expr(std::forward(expr))); + } + + /// @param args the arguments for the constructor + /// @returns an ast::CallExpression to the type `T`, with the arguments of @p args converted to + /// `ast::Expression`s using Expr(). + template > + const ast::CallExpression* Call(ARGS&&... args) { + return Call(source_, ty.Of(), std::forward(args)...); + } + + /// @param source the source of the call + /// @param args the arguments for the constructor + /// @returns an ast::CallExpression to the type `T` with the arguments of @p args converted to + /// `ast::Expression`s using Expr(). + template + const ast::CallExpression* Call(const Source& source, ARGS&&... args) { + return Call(source, ty.Of(), std::forward(args)...); + } + + /// @param target the call target + /// @param args the function call arguments + /// @returns an ast::CallExpression to the target @p target, with the arguments of @p args + /// converted to `ast::Expression`s using Expr(). + template , + typename = DisableIfScalar> + const ast::CallExpression* Call(TARGET&& target, ARGS&&... args) { + return Call(source_, Expr(std::forward(target)), std::forward(args)...); + } + + /// @param source the source of the call + /// @param target the call target + /// @param args the function call arguments + /// @returns an ast::CallExpression to the target @p target, with the arguments of @p args + /// converted to `ast::Expression`s using Expr(). + template > + const ast::CallExpression* Call(const Source& source, TARGET&& target, ARGS&&... args) { + return create(source, Expr(std::forward(target)), + ExprList(std::forward(args)...)); + } + + /// @param source the source information + /// @param call the call expression to wrap in a call statement + /// @returns a `ast::CallStatement` for the given call expression + const ast::CallStatement* CallStmt(const Source& source, const ast::CallExpression* call) { + return create(source, call); + } + + /// @param call the call expression to wrap in a call statement + /// @returns a `ast::CallStatement` for the given call expression + const ast::CallStatement* CallStmt(const ast::CallExpression* call) { + return create(call); + } + + /// @param source the source information + /// @returns a `ast::PhonyExpression` + const ast::PhonyExpression* Phony(const Source& source) { + return create(source); + } + + /// @returns a `ast::PhonyExpression` + const ast::PhonyExpression* Phony() { return create(); } + + /// @param expr the expression to ignore + /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony + /// (underscore) variable. + template + const ast::AssignmentStatement* Ignore(EXPR&& expr) { + return create(Phony(), Expr(expr)); + } + + /// @param lhs the left hand argument to the addition operation + /// @param rhs the right hand argument to the addition operation + /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs` + template + const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kAdd, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the addition operation + /// @param rhs the right hand argument to the addition operation + /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs` + template + const ast::BinaryExpression* Add(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kAdd, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the and operation + /// @param rhs the right hand argument to the and operation + /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs` + template + const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kAnd, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the or operation + /// @param rhs the right hand argument to the or operation + /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs` + template + const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kOr, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the subtraction operation + /// @param rhs the right hand argument to the subtraction operation + /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs` + template + const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) { + return create( + core::BinaryOp::kSubtract, Expr(std::forward(lhs)), Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the multiplication operation + /// @param rhs the right hand argument to the multiplication operation + /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs` + template + const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) { + return create( + core::BinaryOp::kMultiply, Expr(std::forward(lhs)), Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the multiplication operation + /// @param rhs the right hand argument to the multiplication operation + /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs` + template + const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kMultiply, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the division operation + /// @param rhs the right hand argument to the division operation + /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs` + template + const ast::BinaryExpression* Div(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kDivide, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the division operation + /// @param rhs the right hand argument to the division operation + /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs` + template + const ast::BinaryExpression* Div(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kDivide, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the modulo operation + /// @param rhs the right hand argument to the modulo operation + /// @returns a `ast::BinaryExpression` applying modulo of `lhs` by `rhs` + template + const ast::BinaryExpression* Mod(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kModulo, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the bit shift right operation + /// @param rhs the right hand argument to the bit shift right operation + /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs` + template + const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kShiftRight, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the bit shift right operation + /// @param rhs the right hand argument to the bit shift right operation + /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs` + template + const ast::BinaryExpression* Shr(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kShiftRight, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the bit shift left operation + /// @param rhs the right hand argument to the bit shift left operation + /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs` + template + const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) { + return create( + core::BinaryOp::kShiftLeft, Expr(std::forward(lhs)), Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the bit shift left operation + /// @param rhs the right hand argument to the bit shift left operation + /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs` + template + const ast::BinaryExpression* Shl(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kShiftLeft, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the xor operation + /// @param rhs the right hand argument to the xor operation + /// @returns a `ast::BinaryExpression` bitwise xor-ing `lhs` and `rhs` + template + const ast::BinaryExpression* Xor(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kXor, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the logical and operation + /// @param rhs the right hand argument to the logical and operation + /// @returns a `ast::BinaryExpression` of `lhs` && `rhs` + template + const ast::BinaryExpression* LogicalAnd(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kLogicalAnd, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the logical and operation + /// @param rhs the right hand argument to the logical and operation + /// @returns a `ast::BinaryExpression` of `lhs` && `rhs` + template + const ast::BinaryExpression* LogicalAnd(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kLogicalAnd, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the logical or operation + /// @param rhs the right hand argument to the logical or operation + /// @returns a `ast::BinaryExpression` of `lhs` || `rhs` + template + const ast::BinaryExpression* LogicalOr(LHS&& lhs, RHS&& rhs) { + return create( + core::BinaryOp::kLogicalOr, Expr(std::forward(lhs)), Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the logical or operation + /// @param rhs the right hand argument to the logical or operation + /// @returns a `ast::BinaryExpression` of `lhs` || `rhs` + template + const ast::BinaryExpression* LogicalOr(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kLogicalOr, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the greater than operation + /// @param rhs the right hand argument to the greater than operation + /// @returns a `ast::BinaryExpression` of `lhs` > `rhs` + template + const ast::BinaryExpression* GreaterThan(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kGreaterThan, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the greater than or equal operation + /// @param rhs the right hand argument to the greater than or equal operation + /// @returns a `ast::BinaryExpression` of `lhs` >= `rhs` + template + const ast::BinaryExpression* GreaterThanEqual(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kGreaterThanEqual, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the less than operation + /// @param rhs the right hand argument to the less than operation + /// @returns a `ast::BinaryExpression` of `lhs` < `rhs` + template + const ast::BinaryExpression* LessThan(LHS&& lhs, RHS&& rhs) { + return create( + core::BinaryOp::kLessThan, Expr(std::forward(lhs)), Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the less than or equal operation + /// @param rhs the right hand argument to the less than or equal operation + /// @returns a `ast::BinaryExpression` of `lhs` <= `rhs` + template + const ast::BinaryExpression* LessThanEqual(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kLessThanEqual, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the equal expression + /// @param rhs the right hand argument to the equal expression + /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` + template + const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) { + return create(core::BinaryOp::kEqual, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param lhs the left hand argument to the equal expression + /// @param rhs the right hand argument to the equal expression + /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` + template + const ast::BinaryExpression* Equal(const Source& source, LHS&& lhs, RHS&& rhs) { + return create(source, core::BinaryOp::kEqual, + Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// @param lhs the left hand argument to the not-equal expression + /// @param rhs the right hand argument to the not-equal expression + /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` for + /// disequality + template + const ast::BinaryExpression* NotEqual(LHS&& lhs, RHS&& rhs) { + return create( + core::BinaryOp::kNotEqual, Expr(std::forward(lhs)), Expr(std::forward(rhs))); + } + + /// @param source the source information + /// @param object the object for the index accessor expression + /// @param index the index argument for the index accessor expression + /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index + template + const ast::IndexAccessorExpression* IndexAccessor(const Source& source, + OBJECT&& object, + INDEX&& index) { + return create(source, Expr(std::forward(object)), + Expr(std::forward(index))); + } + + /// @param object the object for the index accessor expression + /// @param index the index argument for the index accessor expression + /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index + template + const ast::IndexAccessorExpression* IndexAccessor(OBJECT&& object, INDEX&& index) { + return create(Expr(std::forward(object)), + Expr(std::forward(index))); + } + + /// @param source the source information + /// @param object the object for the member accessor expression + /// @param member the member argument for the member accessor expression + /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member + template + const ast::MemberAccessorExpression* MemberAccessor(const Source& source, + OBJECT&& object, + MEMBER&& member) { + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is currently invalid for a structure to hold a templated member"); + return create(source, Expr(std::forward(object)), + Ident(std::forward(member))); + } + + /// @param object the object for the member accessor expression + /// @param member the member argument for the member accessor expression + /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member + template + const ast::MemberAccessorExpression* MemberAccessor(OBJECT&& object, MEMBER&& member) { + return MemberAccessor(source_, std::forward(object), std::forward(member)); + } + + /// Creates a ast::StructMemberSizeAttribute + /// @param source the source information + /// @param val the size value + /// @returns the size attribute pointer + template + const ast::StructMemberSizeAttribute* MemberSize(const Source& source, EXPR&& val) { + return create(source, Expr(std::forward(val))); + } + + /// Creates a ast::StructMemberSizeAttribute + /// @param val the size value + /// @returns the size attribute pointer + template + const ast::StructMemberSizeAttribute* MemberSize(EXPR&& val) { + return create(source_, Expr(std::forward(val))); + } + + /// Creates a ast::StructMemberAlignAttribute + /// @param source the source information + /// @param val the align value expression + /// @returns the align attribute pointer + template + const ast::StructMemberAlignAttribute* MemberAlign(const Source& source, EXPR&& val) { + return create(source, Expr(std::forward(val))); + } + + /// Creates a ast::StructMemberAlignAttribute + /// @param val the align value expression + /// @returns the align attribute pointer + template + const ast::StructMemberAlignAttribute* MemberAlign(EXPR&& val) { + return create(source_, Expr(std::forward(val))); + } + + /// Creates the ast::GroupAttribute + /// @param value group attribute index expresion + /// @returns the group attribute pointer + template + const ast::GroupAttribute* Group(EXPR&& value) { + return create(Expr(std::forward(value))); + } + + /// Creates the ast::GroupAttribute + /// @param source the source + /// @param value group attribute index expression + /// @returns the group attribute pointer + template + const ast::GroupAttribute* Group(const Source& source, EXPR&& value) { + return create(source, Expr(std::forward(value))); + } + + /// Creates the ast::BindingAttribute + /// @param value the binding index expression + /// @returns the binding deocration pointer + template + const ast::BindingAttribute* Binding(EXPR&& value) { + return create(Expr(std::forward(value))); + } + + /// Creates the ast::BindingAttribute + /// @param source the source + /// @param value the binding index expression + /// @returns the binding deocration pointer + template + const ast::BindingAttribute* Binding(const Source& source, EXPR&& value) { + return create(source, Expr(std::forward(value))); + } + + /// Creates an ast::Function and registers it with the ast::Module. + /// @param name the function name + /// @param params the function parameters + /// @param type the function return type + /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will + /// be automatically placed into a block, or nullptr for a stub function. + /// @param attributes the optional function attributes + /// @param return_type_attributes the optional function return type attributes + /// @returns the function pointer + template > + const ast::Function* Func(NAME&& name, + VectorRef params, + ast::Type type, + BODY&& body, + VectorRef attributes = Empty, + VectorRef return_type_attributes = Empty) { + return Func(source_, std::forward(name), std::move(params), type, + std::forward(body), std::move(attributes), + std::move(return_type_attributes)); + } + + /// Creates an ast::Function and registers it with the ast::Module. + /// @param source the source information + /// @param name the function name + /// @param params the function parameters + /// @param type the function return type + /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will + /// be automatically placed into a block, or nullptr for a stub function. + /// @param attributes the optional function attributes + /// @param return_type_attributes the optional function return type attributes + /// @returns the function pointer + template > + const ast::Function* Func(const Source& source, + NAME&& name, + VectorRef params, + ast::Type type, + BODY&& body, + VectorRef attributes = Empty, + VectorRef return_type_attributes = Empty) { + const ast::BlockStatement* block = nullptr; + using BODY_T = traits::PtrElTy; + if constexpr (traits::IsTypeOrDerived || + std::is_same_v) { + block = body; + } else { + block = Block(std::forward(body)); + } + auto* func = + create(source, Ident(std::forward(name)), std::move(params), type, + block, std::move(attributes), std::move(return_type_attributes)); + AST().AddFunction(func); + return func; + } + + /// Creates an ast::BreakStatement + /// @param source the source information + /// @returns the break statement pointer + const ast::BreakStatement* Break(const Source& source) { + return create(source); + } + + /// Creates an ast::BreakStatement + /// @returns the break statement pointer + const ast::BreakStatement* Break() { return create(); } + + /// Creates a ast::BreakIfStatement with input condition + /// @param source the source information for the if statement + /// @param condition the if statement condition expression + /// @returns the break-if statement pointer + template + const ast::BreakIfStatement* BreakIf(const Source& source, CONDITION&& condition) { + return create(source, Expr(std::forward(condition))); + } + + /// Creates a ast::BreakIfStatement with input condition + /// @param condition the if statement condition expression + /// @returns the break-if statement pointer + template + const ast::BreakIfStatement* BreakIf(CONDITION&& condition) { + return create(Expr(std::forward(condition))); + } + + /// Creates an ast::ContinueStatement + /// @param source the source information + /// @returns the continue statement pointer + const ast::ContinueStatement* Continue(const Source& source) { + return create(source); + } + + /// Creates an ast::ContinueStatement + /// @returns the continue statement pointer + const ast::ContinueStatement* Continue() { return create(); } + + /// Creates an ast::ReturnStatement with no return value + /// @param source the source information + /// @returns the return statement pointer + const ast::ReturnStatement* Return(const Source& source) { + return create(source); + } + + /// Creates an ast::ReturnStatement with no return value + /// @returns the return statement pointer + const ast::ReturnStatement* Return() { return create(); } + + /// Creates an ast::ReturnStatement with the given return value + /// @param source the source information + /// @param val the return value + /// @returns the return statement pointer + template + const ast::ReturnStatement* Return(const Source& source, EXPR&& val) { + return create(source, Expr(std::forward(val))); + } + + /// Creates an ast::ReturnStatement with the given return value + /// @param val the return value + /// @returns the return statement pointer + template > + const ast::ReturnStatement* Return(EXPR&& val) { + return create(Expr(std::forward(val))); + } + + /// Creates an ast::DiscardStatement + /// @param source the source information + /// @returns the discard statement pointer + const ast::DiscardStatement* Discard(const Source& source) { + return create(source); + } + + /// Creates an ast::DiscardStatement + /// @returns the discard statement pointer + const ast::DiscardStatement* Discard() { return create(); } + + /// Creates a ast::Alias registering it with the AST().TypeDecls(). + /// @param name the alias name + /// @param type the alias target type + /// @returns the alias type + template + const ast::Alias* Alias(NAME&& name, ast::Type type) { + return Alias(source_, std::forward(name), type); + } + + /// Creates a ast::Alias registering it with the AST().TypeDecls(). + /// @param source the source information + /// @param name the alias name + /// @param type the alias target type + /// @returns the alias type + template + const ast::Alias* Alias(const Source& source, NAME&& name, ast::Type type) { + auto out = ty.alias(source, std::forward(name), type); + AST().AddTypeDecl(out); + return out; + } + + /// Creates a ast::Struct registering it with the AST().TypeDecls(). + /// @param name the struct name + /// @param members the struct members + /// @param attributes the optional struct attributes + /// @returns the struct type + template + const ast::Struct* Structure(NAME&& name, + VectorRef members, + VectorRef attributes = Empty) { + return Structure(source_, std::forward(name), std::move(members), + std::move(attributes)); + } + + /// Creates a ast::Struct registering it with the AST().TypeDecls(). + /// @param source the source information + /// @param name the struct name + /// @param members the struct members + /// @param attributes the optional struct attributes + /// @returns the struct type + template + const ast::Struct* Structure(const Source& source, + NAME&& name, + VectorRef members, + VectorRef attributes = Empty) { + auto* type = create(source, Ident(std::forward(name)), + std::move(members), std::move(attributes)); + AST().AddTypeDecl(type); + return type; + } + + /// Creates a ast::StructMember + /// @param name the struct member name + /// @param type the struct member type + /// @param attributes the optional struct member attributes + /// @returns the struct member pointer + template > + const ast::StructMember* Member(NAME&& name, + ast::Type type, + VectorRef attributes = Empty) { + return Member(source_, std::forward(name), type, std::move(attributes)); + } + + /// Creates a ast::StructMember + /// @param source the struct member source + /// @param name the struct member name + /// @param type the struct member type + /// @param attributes the optional struct member attributes + /// @returns the struct member pointer + template + const ast::StructMember* Member(const Source& source, + NAME&& name, + ast::Type type, + VectorRef attributes = Empty) { + return create(source, Ident(std::forward(name)), type, + std::move(attributes)); + } + + /// Creates a ast::BlockStatement with input statements and attributes + /// @param statements the statements of the block + /// @param attributes the optional attributes of the block + /// @returns the block statement pointer + const ast::BlockStatement* Block(VectorRef statements, + VectorRef attributes = Empty) { + return Block(source_, std::move(statements), std::move(attributes)); + } + + /// Creates a ast::BlockStatement with input statements and attributes + /// @param source the source information for the block + /// @param statements the statements of the block + /// @param attributes the optional attributes of the block + /// @returns the block statement pointer + const ast::BlockStatement* Block(const Source& source, + VectorRef statements, + VectorRef attributes = Empty) { + return create(source, std::move(statements), std::move(attributes)); + } + + /// Creates a ast::BlockStatement with a parameter list of input statements + /// @param statements the optional statements of the block + /// @returns the block statement pointer + template , + typename = DisableIfVectorLike> + const ast::BlockStatement* Block(STATEMENTS&&... statements) { + return Block(source_, std::forward(statements)...); + } + + /// Creates a ast::BlockStatement with a parameter list of input statements + /// @param source the source information for the block + /// @param statements the optional statements of the block + /// @returns the block statement pointer + template > + const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) { + return create(source, + Vector{ + std::forward(statements)..., + }, + Empty); + } + + /// A wrapper type for the Else statement used to create If statements. + struct ElseStmt { + /// Default constructor - no else statement. + ElseStmt() : stmt(nullptr) {} + /// Constructor + /// @param s The else statement + explicit ElseStmt(const ast::Statement* s) : stmt(s) {} + /// The else statement, or nullptr. + const ast::Statement* stmt; + }; + + /// Creates a ast::IfStatement with input condition, body, and optional + /// else statement + /// @param source the source information for the if statement + /// @param condition the if statement condition expression + /// @param body the if statement body + /// @param else_stmt optional else statement + /// @param attributes optional attributes + /// @returns the if statement pointer + template + const ast::IfStatement* If(const Source& source, + CONDITION&& condition, + const ast::BlockStatement* body, + const ElseStmt else_stmt = ElseStmt(), + VectorRef attributes = Empty) { + return create(source, Expr(std::forward(condition)), body, + else_stmt.stmt, std::move(attributes)); + } + + /// Creates a ast::IfStatement with input condition, body, and optional + /// else statement + /// @param condition the if statement condition expression + /// @param body the if statement body + /// @param else_stmt optional else statement + /// @param attributes optional attributes + /// @returns the if statement pointer + template + const ast::IfStatement* If(CONDITION&& condition, + const ast::BlockStatement* body, + const ElseStmt else_stmt = ElseStmt(), + VectorRef attributes = Empty) { + return create(Expr(std::forward(condition)), body, + else_stmt.stmt, std::move(attributes)); + } + + /// Creates an Else object. + /// @param stmt else statement + /// @returns the Else object + ElseStmt Else(const ast::Statement* stmt) { return ElseStmt(stmt); } + + /// Creates a ast::AssignmentStatement with input lhs and rhs expressions + /// @param source the source information + /// @param lhs the left hand side expression initializer + /// @param rhs the right hand side expression initializer + /// @returns the assignment statement pointer + template + const ast::AssignmentStatement* Assign(const Source& source, + LhsExpressionInit&& lhs, + RhsExpressionInit&& rhs) { + return create(source, Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// Creates a ast::AssignmentStatement with input lhs and rhs expressions + /// @param lhs the left hand side expression initializer + /// @param rhs the right hand side expression initializer + /// @returns the assignment statement pointer + template + const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, RhsExpressionInit&& rhs) { + return create(Expr(std::forward(lhs)), + Expr(std::forward(rhs))); + } + + /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs + /// expressions, and a binary operator. + /// @param source the source information + /// @param lhs the left hand side expression initializer + /// @param rhs the right hand side expression initializer + /// @param op the binary operator + /// @returns the compound assignment statement pointer + template + const ast::CompoundAssignmentStatement* CompoundAssign(const Source& source, + LhsExpressionInit&& lhs, + RhsExpressionInit&& rhs, + core::BinaryOp op) { + return create( + source, Expr(std::forward(lhs)), + Expr(std::forward(rhs)), op); + } + + /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs + /// expressions, and a binary operator. + /// @param lhs the left hand side expression initializer + /// @param rhs the right hand side expression initializer + /// @param op the binary operator + /// @returns the compound assignment statement pointer + template + const ast::CompoundAssignmentStatement* CompoundAssign(LhsExpressionInit&& lhs, + RhsExpressionInit&& rhs, + core::BinaryOp op) { + return create(Expr(std::forward(lhs)), + Expr(std::forward(rhs)), + op); + } + + /// Creates an ast::IncrementDecrementStatement with input lhs. + /// @param source the source information + /// @param lhs the left hand side expression initializer + /// @returns the increment decrement statement pointer + template + const ast::IncrementDecrementStatement* Increment(const Source& source, + LhsExpressionInit&& lhs) { + return create( + source, Expr(std::forward(lhs)), true); + } + + /// Creates a ast::IncrementDecrementStatement with input lhs. + /// @param lhs the left hand side expression initializer + /// @returns the increment decrement statement pointer + template + const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) { + return create(Expr(std::forward(lhs)), + true); + } + + /// Creates an ast::IncrementDecrementStatement with input lhs. + /// @param source the source information + /// @param lhs the left hand side expression initializer + /// @returns the increment decrement statement pointer + template + const ast::IncrementDecrementStatement* Decrement(const Source& source, + LhsExpressionInit&& lhs) { + return create( + source, Expr(std::forward(lhs)), false); + } + + /// Creates a ast::IncrementDecrementStatement with input lhs. + /// @param lhs the left hand side expression initializer + /// @returns the increment decrement statement pointer + template + const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) { + return create(Expr(std::forward(lhs)), + false); + } + + /// Creates a ast::LoopStatement with input body and optional continuing + /// @param source the source information + /// @param body the loop body + /// @param continuing the optional continuing block + /// @param attributes optional attributes + /// @returns the loop statement pointer + const ast::LoopStatement* Loop(const Source& source, + const ast::BlockStatement* body, + const ast::BlockStatement* continuing = nullptr, + VectorRef attributes = Empty) { + return create(source, body, continuing, std::move(attributes)); + } + + /// Creates a ast::LoopStatement with input body and optional continuing + /// @param body the loop body + /// @param continuing the optional continuing block + /// @param attributes optional attributes + /// @returns the loop statement pointer + const ast::LoopStatement* Loop(const ast::BlockStatement* body, + const ast::BlockStatement* continuing = nullptr, + VectorRef attributes = Empty) { + return create(body, continuing, std::move(attributes)); + } + + /// Creates a ast::ForLoopStatement with input body and optional initializer, condition, + /// continuing, and attributes. + /// @param source the source information + /// @param init the optional loop initializer + /// @param cond the optional loop condition + /// @param cont the optional loop continuing + /// @param body the loop body + /// @param attributes optional attributes + /// @returns the for loop statement pointer + template + const ast::ForLoopStatement* For(const Source& source, + const ast::Statement* init, + COND&& cond, + const ast::Statement* cont, + const ast::BlockStatement* body, + VectorRef attributes = Empty) { + return create(source, init, Expr(std::forward(cond)), cont, + body, std::move(attributes)); + } + + /// Creates a ast::ForLoopStatement with input body and optional initializer, condition, + /// continuing, and attributes. + /// @param init the optional loop initializer + /// @param cond the optional loop condition + /// @param cont the optional loop continuing + /// @param body the loop body + /// @param attributes optional attributes + /// @returns the for loop statement pointer + template + const ast::ForLoopStatement* For(const ast::Statement* init, + COND&& cond, + const ast::Statement* cont, + const ast::BlockStatement* body, + VectorRef attributes = Empty) { + return create(init, Expr(std::forward(cond)), cont, body, + std::move(attributes)); + } + + /// Creates a ast::WhileStatement with input body, condition, and optional attributes. + /// @param source the source information + /// @param cond the loop condition + /// @param body the loop body + /// @param attributes optional attributes + /// @returns the while statement pointer + template + const ast::WhileStatement* While(const Source& source, + COND&& cond, + const ast::BlockStatement* body, + VectorRef attributes = Empty) { + return create(source, Expr(std::forward(cond)), body, + std::move(attributes)); + } + + /// Creates a ast::WhileStatement with input body, condition, and optional attributes. + /// @param cond the condition + /// @param body the loop body + /// @param attributes optional attributes + /// @returns the while loop statement pointer + template + const ast::WhileStatement* While(COND&& cond, + const ast::BlockStatement* body, + VectorRef attributes = Empty) { + return create(Expr(std::forward(cond)), body, + std::move(attributes)); + } + + /// Creates a ast::VariableDeclStatement for the input variable + /// @param source the source information + /// @param var the variable to wrap in a decl statement + /// @returns the variable decl statement pointer + const ast::VariableDeclStatement* Decl(const Source& source, const ast::Variable* var) { + return create(source, var); + } + + /// Creates a ast::VariableDeclStatement for the input variable + /// @param var the variable to wrap in a decl statement + /// @returns the variable decl statement pointer + const ast::VariableDeclStatement* Decl(const ast::Variable* var) { + return create(var); + } + + /// Creates a ast::SwitchStatement with input expression and cases + /// @param source the source information + /// @param condition the condition expression initializer + /// @param cases case statements + /// @returns the switch statement pointer + template > + const ast::SwitchStatement* Switch(const Source& source, + ExpressionInit&& condition, + Cases&&... cases) { + return create( + source, Expr(std::forward(condition)), + Vector{std::forward(cases)...}, + Empty, Empty); + } + + /// Creates a ast::SwitchStatement with input expression and cases + /// @param condition the condition expression initializer + /// @param cases case statements + /// @returns the switch statement pointer + template , + typename = DisableIfVectorLike> + const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) { + return create( + Expr(std::forward(condition)), + Vector{std::forward(cases)...}, + Empty, Empty); + } + + /// Creates a ast::SwitchStatement with input expression, cases, and optional attributes + /// @param source the source information + /// @param condition the condition expression initializer + /// @param cases case statements + /// @param stmt_attributes optional statement attributes + /// @param body_attributes optional body attributes + /// @returns the switch statement pointer + template + const ast::SwitchStatement* Switch(const Source& source, + ExpressionInit&& condition, + VectorRef cases, + VectorRef stmt_attributes = Empty, + VectorRef body_attributes = Empty) { + return create(source, Expr(std::forward(condition)), + cases, std::move(stmt_attributes), + std::move(body_attributes)); + } + + /// Creates a ast::SwitchStatement with input expression, cases, and optional attributes + /// @param condition the condition expression initializer + /// @param cases case statements + /// @param stmt_attributes optional statement attributes + /// @param body_attributes optional body attributes + /// @returns the switch statement pointer + template > + const ast::SwitchStatement* Switch(ExpressionInit&& condition, + VectorRef cases, + VectorRef stmt_attributes = Empty, + VectorRef body_attributes = Empty) { + return create(Expr(std::forward(condition)), cases, + std::move(stmt_attributes), std::move(body_attributes)); + } + + /// Creates a ast::CaseStatement with input list of selectors, and body + /// @param selectors list of selectors + /// @param body the case body + /// @returns the case statement pointer + const ast::CaseStatement* Case(VectorRef selectors, + const ast::BlockStatement* body = nullptr) { + return Case(source_, std::move(selectors), body); + } + + /// Creates a ast::CaseStatement with input list of selectors, and body + /// @param source the source information + /// @param selectors list of selectors + /// @param body the case body + /// @returns the case statement pointer + const ast::CaseStatement* Case(const Source& source, + VectorRef selectors, + const ast::BlockStatement* body = nullptr) { + return create(source, std::move(selectors), body ? body : Block()); + } + + /// Convenient overload that takes a single selector + /// @param selector a single case selector + /// @param body the case body + /// @returns the case statement pointer + const ast::CaseStatement* Case(const ast::CaseSelector* selector, + const ast::BlockStatement* body = nullptr) { + return Case(Vector{selector}, body ? body : Block()); + } + + /// Convenience function that creates a 'default' ast::CaseStatement + /// @param body the case body + /// @returns the case statement pointer + const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) { + return DefaultCase(source_, body); + } + + /// Convenience function that creates a 'default' ast::CaseStatement + /// @param source the source information + /// @param body the case body + /// @returns the case statement pointer + const ast::CaseStatement* DefaultCase(const Source& source, + const ast::BlockStatement* body = nullptr) { + return Case(source, Vector{DefaultCaseSelector(source)}, body); + } + + /// Convenience function that creates a case selector + /// @param source the source information + /// @param expr the selector expression + /// @returns the selector pointer + template + const ast::CaseSelector* CaseSelector(const Source& source, EXPR&& expr) { + return create(source, Expr(std::forward(expr))); + } + + /// Convenience function that creates a case selector + /// @param expr the selector expression + /// @returns the selector pointer + template + const ast::CaseSelector* CaseSelector(EXPR&& expr) { + return create(source_, Expr(std::forward(expr))); + } + + /// Convenience function that creates a default case selector + /// @param source the source information + /// @returns the selector pointer + const ast::CaseSelector* DefaultCaseSelector(const Source& source) { + return create(source, nullptr); + } + + /// Convenience function that creates a default case selector + /// @returns the selector pointer + const ast::CaseSelector* DefaultCaseSelector() { return create(nullptr); } + + /// Creates an ast::BuiltinAttribute + /// @param builtin the builtin value + /// @returns the builtin attribute pointer + const ast::BuiltinAttribute* Builtin(core::BuiltinValue builtin) { + return Builtin(source_, builtin); + } + + /// Creates an ast::BuiltinAttribute + /// @param source the source information + /// @param builtin the builtin value + /// @returns the builtin attribute pointer + const ast::BuiltinAttribute* Builtin(const Source& source, core::BuiltinValue builtin) { + return Builtin(source, builtin, core::BuiltinDepthMode::kUndefined); + } + + /// Creates an ast::BuiltinAttribute + /// @param source the source information + /// @param builtin the builtin value + /// @param depth_mode the depth mode + /// @returns the builtin attribute pointer + const ast::BuiltinAttribute* Builtin(const Source& source, + core::BuiltinValue builtin, + core::BuiltinDepthMode depth_mode) { + return create(source, builtin, depth_mode); + } + + /// Creates an ast::InterpolateAttribute + /// @param type the interpolation type + /// @returns the interpolate attribute pointer + const ast::InterpolateAttribute* Interpolate(core::InterpolationType type) { + return Interpolate(source_, type); + } + + /// Creates an ast::InterpolateAttribute + /// @param source the source information + /// @param type the interpolation type + /// @returns the interpolate attribute pointer + const ast::InterpolateAttribute* Interpolate(const Source& source, + core::InterpolationType type) { + return Interpolate(source, type, core::InterpolationSampling::kUndefined); + } + + /// Creates an ast::InterpolateAttribute + /// @param type the interpolation type + /// @param sampling the interpolation sampling + /// @returns the interpolate attribute pointer + const ast::InterpolateAttribute* Interpolate(core::InterpolationType type, + core::InterpolationSampling sampling) { + return Interpolate(source_, type, sampling); + } + + /// Creates an ast::InterpolateAttribute + /// @param source the source information + /// @param type the interpolation type + /// @param sampling the interpolation sampling + /// @returns the interpolate attribute pointer + const ast::InterpolateAttribute* Interpolate(const Source& source, + core::InterpolationType type, + core::InterpolationSampling sampling) { + core::Interpolation interpolation{type, sampling}; + return create(source, interpolation); + } + + /// Creates an ast::InterpolateAttribute using flat interpolation + /// @param source the source information + /// @returns the interpolate attribute pointer + const ast::InterpolateAttribute* Flat(const Source& source) { + return Interpolate(source, core::InterpolationType::kFlat); + } + + /// Creates an ast::InterpolateAttribute using flat interpolation + /// @returns the interpolate attribute pointer + const ast::InterpolateAttribute* Flat() { return Interpolate(core::InterpolationType::kFlat); } + + /// Creates an ast::InvariantAttribute + /// @param source the source information + /// @returns the invariant attribute pointer + const ast::InvariantAttribute* Invariant(const Source& source) { + return create(source); + } + + /// Creates an ast::InvariantAttribute + /// @returns the invariant attribute pointer + const ast::InvariantAttribute* Invariant() { return create(source_); } + + /// Creates an ast::MustUseAttribute + /// @param source the source information + /// @returns the invariant attribute pointer + const ast::MustUseAttribute* MustUse(const Source& source) { + return create(source); + } + + /// Creates an ast::MustUseAttribute + /// @returns the invariant attribute pointer + const ast::MustUseAttribute* MustUse() { return create(source_); } + + /// Creates an ast::LocationAttribute + /// @param source the source information + /// @param location the location value expression + /// @returns the location attribute pointer + template + const ast::LocationAttribute* Location(const Source& source, EXPR&& location) { + return create(source, Expr(std::forward(location))); + } + + /// Creates an ast::ColorAttribute + /// @param index the index value expression + /// @returns the index attribute pointer + template + const ast::ColorAttribute* Color(EXPR&& index) { + return create(source_, Expr(std::forward(index))); + } + + /// Creates an ast::ColorAttribute + /// @param source the source information + /// @param index the index value expression + /// @returns the index attribute pointer + template + const ast::ColorAttribute* Color(const Source& source, EXPR&& index) { + return create(source, Expr(std::forward(index))); + } + + /// Creates an ast::LocationAttribute + /// @param location the location value expression + /// @returns the location attribute pointer + template + const ast::LocationAttribute* Location(EXPR&& location) { + return create(source_, Expr(std::forward(location))); + } + + /// Creates an ast::BlendSrcAttribute + /// @param source the source information + /// @param blend_src the blend_src value expression + /// @returns the blend_src attribute pointer + template + const ast::BlendSrcAttribute* BlendSrc(const Source& source, EXPR&& blend_src) { + return create(source, Expr(std::forward(blend_src))); + } + + /// Creates an ast::BlendSrcAttribute + /// @param blend_src the blend_src value expression + /// @returns the blend_src attribute pointer + template + const ast::BlendSrcAttribute* BlendSrc(EXPR&& blend_src) { + return create(source_, Expr(std::forward(blend_src))); + } + + /// Creates an ast::IdAttribute + /// @param source the source information + /// @param id the id value + /// @returns the override attribute pointer + const ast::IdAttribute* Id(const Source& source, OverrideId id) { + return create(source, Expr(core::AInt(id.value))); + } + + /// Creates an ast::IdAttribute with an override identifier + /// @param id the optional id value + /// @returns the override attribute pointer + const ast::IdAttribute* Id(OverrideId id) { + return create(Expr(core::AInt(id.value))); + } + + /// Creates an ast::IdAttribute + /// @param source the source information + /// @param id the id value expression + /// @returns the override attribute pointer + template + const ast::IdAttribute* Id(const Source& source, EXPR&& id) { + return create(source, Expr(std::forward(id))); + } + + /// Creates an ast::IdAttribute with an override identifier + /// @param id the optional id value expression + /// @returns the override attribute pointer + template + const ast::IdAttribute* Id(EXPR&& id) { + return create(Expr(std::forward(id))); + } + + /// Creates an ast::InputAttachmentIndexAttribute + /// @param index the index value expression + /// @returns the index attribute pointer + template + const ast::InputAttachmentIndexAttribute* InputAttachmentIndex(EXPR&& index) { + return create(source_, Expr(std::forward(index))); + } + + /// Creates an ast::InputAttachmentIndexAttribute + /// @param source the source information + /// @param index the index value expression + /// @returns the index attribute pointer + template + const ast::InputAttachmentIndexAttribute* InputAttachmentIndex(const Source& source, + EXPR&& index) { + return create(source, Expr(std::forward(index))); + } + + /// Creates an ast::StageAttribute + /// @param source the source information + /// @param stage the pipeline stage + /// @returns the stage attribute pointer + const ast::StageAttribute* Stage(const Source& source, ast::PipelineStage stage) { + return create(source, stage); + } + + /// Creates an ast::StageAttribute + /// @param stage the pipeline stage + /// @returns the stage attribute pointer + const ast::StageAttribute* Stage(ast::PipelineStage stage) { + return create(source_, stage); + } + + /// Creates an ast::WorkgroupAttribute + /// @param x the x dimension expression + /// @returns the workgroup attribute pointer + template + const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x) { + return WorkgroupSize(std::forward(x), nullptr, nullptr); + } + + /// Creates an ast::WorkgroupAttribute + /// @param source the source information + /// @param x the x dimension expression + /// @returns the workgroup attribute pointer + template + const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x) { + return WorkgroupSize(source, std::forward(x), nullptr, nullptr); + } + + /// Creates an ast::WorkgroupAttribute + /// @param source the source information + /// @param x the x dimension expression + /// @param y the y dimension expression + /// @returns the workgroup attribute pointer + template + const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x, EXPR_Y&& y) { + return WorkgroupSize(source, std::forward(x), std::forward(y), nullptr); + } + + /// Creates an ast::WorkgroupAttribute + /// @param x the x dimension expression + /// @param y the y dimension expression + /// @returns the workgroup attribute pointer + template > + const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) { + return WorkgroupSize(std::forward(x), std::forward(y), nullptr); + } + + /// Creates an ast::WorkgroupAttribute + /// @param source the source information + /// @param x the x dimension expression + /// @param y the y dimension expression + /// @param z the z dimension expression + /// @returns the workgroup attribute pointer + template + const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, + EXPR_X&& x, + EXPR_Y&& y, + EXPR_Z&& z) { + return create(source, Expr(std::forward(x)), + Expr(std::forward(y)), + Expr(std::forward(z))); + } + + /// Creates an ast::WorkgroupAttribute + /// @param x the x dimension expression + /// @param y the y dimension expression + /// @param z the z dimension expression + /// @returns the workgroup attribute pointer + template > + const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y, EXPR_Z&& z) { + return create(source_, Expr(std::forward(x)), + Expr(std::forward(y)), + Expr(std::forward(z))); + } + + /// Creates an ast::SubgroupSizeAttribute + /// @param source the source information + /// @param subgroup_size the subgroup size value expression + /// @returns the subgroup size attribute pointer + template + const ast::SubgroupSizeAttribute* SubgroupSize(const Source& source, EXPR&& subgroup_size) { + return create(source, std::forward(subgroup_size)); + } + + /// Creates an ast::SubgroupSizeAttribute + /// @param subgroup_size the subgroup size value expression + /// @returns the subgroup size attribute pointer + template + const ast::SubgroupSizeAttribute* SubgroupSize(EXPR&& subgroup_size) { + return SubgroupSize(source_, Expr(std::forward(subgroup_size))); + } + + /// Passthrough overload + /// @param name the diagnostic rule name + /// @returns @p name + const ast::DiagnosticRuleName* DiagnosticRuleName(const ast::DiagnosticRuleName* name) { + return name; + } + + /// Creates an ast::DiagnosticRuleName + /// @param name the diagnostic rule name + /// @returns the diagnostic rule name + template + const ast::DiagnosticRuleName* DiagnosticRuleName(NAME&& name) { + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is invalid for a diagnostic rule name to be templated"); + auto* name_ident = Ident(std::forward(name)); + return create(name_ident->source, name_ident); + } + + /// Creates an ast::DiagnosticRuleName + /// @param category the diagnostic rule category + /// @param name the diagnostic rule name + /// @returns the diagnostic rule name + template > + const ast::DiagnosticRuleName* DiagnosticRuleName(CATEGORY&& category, NAME&& name) { + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is invalid for a diagnostic rule name to be templated"); + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is invalid for a diagnostic rule category to be templated"); + auto* category_ident = Ident(std::forward(category)); + auto* name_ident = Ident(std::forward(name)); + Source source = category_ident->source; + source.range.end = name_ident->source.range.end; + return create(source, category_ident, name_ident); + } + + /// Creates an ast::DiagnosticRuleName + /// @param source the source information + /// @param name the diagnostic rule name + /// @returns the diagnostic rule name + template + const ast::DiagnosticRuleName* DiagnosticRuleName(const Source& source, NAME&& name) { + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is invalid for a diagnostic rule name to be templated"); + auto* name_ident = Ident(std::forward(name)); + return create(source, name_ident); + } + + /// Creates an ast::DiagnosticRuleName + /// @param source the source information + /// @param category the diagnostic rule category + /// @param name the diagnostic rule name + /// @returns the diagnostic rule name + template + const ast::DiagnosticRuleName* DiagnosticRuleName(const Source& source, + CATEGORY&& category, + NAME&& name) { + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is invalid for a diagnostic rule name to be templated"); + static_assert(!traits::IsType, ast::TemplatedIdentifier>, + "it is invalid for a diagnostic rule category to be templated"); + auto* category_ident = Ident(std::forward(category)); + auto* name_ident = Ident(std::forward(name)); + return create(source, category_ident, name_ident); + } + + /// Creates an ast::DiagnosticAttribute + /// @param source the source information + /// @param severity the diagnostic severity control + /// @param rule_args the arguments used to construct the rule name + /// @returns the diagnostic attribute pointer + template + const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source, + wgsl::DiagnosticSeverity severity, + RULE_ARGS&&... rule_args) { + return create( + source, ast::DiagnosticControl( + severity, DiagnosticRuleName(std::forward(rule_args)...))); + } + + /// Creates an ast::DiagnosticAttribute + /// @param severity the diagnostic severity control + /// @param rule_args the arguments used to construct the rule name + /// @returns the diagnostic attribute pointer + template + const ast::DiagnosticAttribute* DiagnosticAttribute(wgsl::DiagnosticSeverity severity, + RULE_ARGS&&... rule_args) { + return create( + source_, ast::DiagnosticControl( + severity, DiagnosticRuleName(std::forward(rule_args)...))); + } + + /// Add a diagnostic directive to the module. + /// @param source the source information + /// @param severity the diagnostic severity control + /// @param rule_args the arguments used to construct the rule name + /// @returns the diagnostic directive pointer + template + const ast::DiagnosticDirective* DiagnosticDirective(const Source& source, + wgsl::DiagnosticSeverity severity, + RULE_ARGS&&... rule_args) { + auto* rule = DiagnosticRuleName(std::forward(rule_args)...); + auto* directive = + create(source, ast::DiagnosticControl(severity, rule)); + AST().AddDiagnosticDirective(directive); + return directive; + } + + /// Add a diagnostic directive to the module. + /// @param severity the diagnostic severity control + /// @param rule_args the arguments used to construct the rule name + /// @returns the diagnostic directive pointer + template + const ast::DiagnosticDirective* DiagnosticDirective(wgsl::DiagnosticSeverity severity, + RULE_ARGS&&... rule_args) { + auto* rule = DiagnosticRuleName(std::forward(rule_args)...); + auto* directive = + create(source_, ast::DiagnosticControl(severity, rule)); + AST().AddDiagnosticDirective(directive); + return directive; + } + + /// Sets the current builder source to `src` + /// @param src the Source used for future create() calls + void SetSource(const Source& src) { + AssertNotMoved(); + source_ = src; + } + + /// Sets the current builder source to `loc` + /// @param loc the Source used for future create() calls + void SetSource(const Source::Location& loc) { + AssertNotMoved(); + source_ = Source(loc); + } + + /// Wraps the ast::Expression in a statement. This is used by tests that + /// construct a partial AST and require the Resolver to reach these + /// nodes. + /// @param expr the ast::Expression to be wrapped by an ast::Statement + /// @return the ast::Statement that wraps the ast::Expression + const ast::Statement* WrapInStatement(const ast::Expression* expr); + /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by + /// tests that construct a partial AST and require the Resolver to reach + /// these nodes. + /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement + /// @return the ast::VariableDeclStatement that wraps the ast::Variable + const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v); + /// Returns the statement argument. Used as a passthrough-overload by + /// WrapInFunction(). + /// @param stmt the ast::Statement + /// @return `stmt` + const ast::Statement* WrapInStatement(const ast::Statement* stmt); + /// Wraps the list of arguments in a simple function so that each is reachable + /// by the Resolver. + /// @param args a mix of ast::Expression, ast::Statement, ast::Variables. + /// @returns the function + template ::value && ...)>> + const ast::Function* WrapInFunction(ARGS&&... args) { + Vector stmts{ + WrapInStatement(std::forward(args))..., + }; + return WrapInFunction(std::move(stmts)); + } + /// @param stmts a list of ast::Statement that will be wrapped by a function, + /// so that each statement is reachable by the Resolver. + /// @returns the function + const ast::Function* WrapInFunction(VectorRef stmts); + + /// The builder types + TypesBuilder const ty{this}; + + protected: + /// Asserts that the builder has not been moved. + void AssertNotMoved() const; + + /// The last Node identifier + ast::NodeID last_ast_node_id_ = ast::NodeID{static_cast(0) - 1}; + + /// Allocator for AST nodes + ASTNodeAllocator ast_nodes_; + + /// The AST node module + ast::Module* ast_ = nullptr; + + /// The symbol table + SymbolTable symbols_{}; + + /// The diagnostic list + diag::List diagnostics_; + + /// The source to use when creating AST nodes without providing a Source as + /// the first argument. + Source source_; + + /// Set by MarkAsMoved(). Once set, no methods may be called on this builder. + bool moved_ = false; +}; + +//! @cond Doxygen_Suppress +// Various template specializations for Builder::TypesBuilder::CToAST. +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder*) { return ast::Type{}; } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder*) { return ast::Type{}; } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->i32(); } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->u32(); } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->f32(); } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->f16(); } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->bool_(); } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->i8(); } +}; +template <> +struct Builder::TypesBuilder::CToAST { + static ast::Type get(const Builder::TypesBuilder* t) { return t->u8(); } +}; +template +struct Builder::TypesBuilder::CToAST> { + static ast::Type get(const Builder::TypesBuilder* t) { return t->array(); } +}; +template +struct Builder::TypesBuilder::CToAST> { + static ast::Type get(const Builder::TypesBuilder* t) { return t->atomic(); } +}; +template +struct Builder::TypesBuilder::CToAST> { + static ast::Type get(const Builder::TypesBuilder* t) { return t->mat(C, R); } +}; +template +struct Builder::TypesBuilder::CToAST> { + static ast::Type get(const Builder::TypesBuilder* t) { return t->vec(); } +}; +template +struct Builder::TypesBuilder::CToAST> { + static ast::Type get(const Builder::TypesBuilder* t) { return t->ptr(); } +}; +//! @endcond + +// Primary template for metafunction that evaluates to true iff T can be wrapped in a statement. +template +struct CanWrapInStatement : std::false_type {}; + +// Specialization of CanWrapInStatement +template +struct CanWrapInStatement< + T, + std::void_t().WrapInStatement(std::declval()))>> + : std::true_type {}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BUILDER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.cc new file mode 100644 index 000000000..afa167b7c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.cc @@ -0,0 +1,50 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/builtin_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::BuiltinAttribute); + +namespace tint::ast { + +BuiltinAttribute::BuiltinAttribute(NodeID nid, + const Source& src, + const core::BuiltinValue b, + const core::BuiltinDepthMode d) + : Base(nid, src), builtin(b), depth_mode(d) {} + +BuiltinAttribute::~BuiltinAttribute() = default; + +std::string BuiltinAttribute::Name() const { + return "builtin"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.h new file mode 100644 index 000000000..00d913901 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/builtin_attribute.h @@ -0,0 +1,63 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_BUILTIN_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_BUILTIN_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/ast/attribute.h" + +namespace tint::ast { + +/// A builtin attribute +class BuiltinAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param builtin the builtin value + BuiltinAttribute(NodeID nid, + const Source& src, + const core::BuiltinValue builtin, + const core::BuiltinDepthMode depth_mode); + ~BuiltinAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The builtin value + const core::BuiltinValue builtin; + + /// The builtin depth mode + const core::BuiltinDepthMode depth_mode; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_BUILTIN_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.cc new file mode 100644 index 000000000..dcaff861a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.cc @@ -0,0 +1,51 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/call_expression.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::CallExpression); + +namespace tint::ast { + +CallExpression::CallExpression(NodeID nid, + const Source& src, + const IdentifierExpression* t, + VectorRef a) + : Base(nid, src), target(t), args(std::move(a)) { + TINT_ASSERT(target); + for (auto* arg : args) { + TINT_ASSERT(arg); + } +} + +CallExpression::~CallExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.h new file mode 100644 index 000000000..e75314ee5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_expression.h @@ -0,0 +1,70 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CALL_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_CALL_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/utils/containers/vector.h" + +// Forward declarations +namespace tint::ast { +class IdentifierExpression; +} // namespace tint::ast + +namespace tint::ast { + +/// A call expression - represents either a: +/// * sem::Function +/// * sem::BuiltinFn +/// * sem::ValueConstructor +/// * sem::ValueConversion +class CallExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the call expression source + /// @param target the target of the call + /// @param args the arguments + CallExpression(NodeID nid, + const Source& source, + const IdentifierExpression* target, + VectorRef args); + + /// Destructor + ~CallExpression() override; + + /// The target function or type + const IdentifierExpression* target; + + /// The arguments + const tint::Vector args; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CALL_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.cc new file mode 100644 index 000000000..bf1f8c846 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/call_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::CallStatement); + +namespace tint::ast { + +CallStatement::CallStatement(NodeID nid, const Source& src, const CallExpression* call) + : Base(nid, src), expr(call) { + TINT_ASSERT(expr); +} + +CallStatement::~CallStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.h new file mode 100644 index 000000000..1c8b9a5bf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/call_statement.h @@ -0,0 +1,54 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CALL_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_CALL_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// A call expression +class CallStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node for the statement + /// @param call the function + CallStatement(NodeID nid, const Source& src, const CallExpression* call); + + /// Destructor + ~CallStatement() override; + + /// The call expression + const CallExpression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CALL_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.cc new file mode 100644 index 000000000..eb0dab08b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.cc @@ -0,0 +1,43 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/case_selector.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::CaseSelector); + +namespace tint::ast { + +CaseSelector::CaseSelector(NodeID nid, const Source& src, const Expression* e) + : Base(nid, src), expr(e) {} + +CaseSelector::~CaseSelector() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.h new file mode 100644 index 000000000..22831e873 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_selector.h @@ -0,0 +1,59 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CASE_SELECTOR_H_ +#define SRC_TINT_LANG_WGSL_AST_CASE_SELECTOR_H_ + +#include + +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A case selector +class CaseSelector final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the selector expression, |nullptr| for a `default` selector + CaseSelector(NodeID nid, const Source& src, const Expression* expr = nullptr); + + /// Destructor + ~CaseSelector() override; + + /// @returns true if this is a default statement + bool IsDefault() const { return expr == nullptr; } + + /// The selector, nullptr for a default selector + const Expression* const expr = nullptr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CASE_SELECTOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.cc new file mode 100644 index 000000000..90b9fd71e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.cc @@ -0,0 +1,61 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/case_statement.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::CaseStatement); + +namespace tint::ast { + +CaseStatement::CaseStatement(NodeID nid, + const Source& src, + VectorRef s, + const BlockStatement* b) + : Base(nid, src), selectors(std::move(s)), body(b) { + TINT_ASSERT(body); + TINT_ASSERT(!selectors.IsEmpty()); + for (auto* selector : selectors) { + TINT_ASSERT(selector); + } +} + +CaseStatement::~CaseStatement() = default; + +bool CaseStatement::ContainsDefault() const { + for (const auto* sel : selectors) { + if (sel->IsDefault()) { + return true; + } + } + return false; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.h new file mode 100644 index 000000000..d3a2b9d7f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/case_statement.h @@ -0,0 +1,66 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CASE_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_CASE_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/case_selector.h" + +namespace tint::ast { + +/// A case statement +class CaseStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param selectors the case selectors + /// @param body the case body + CaseStatement(NodeID nid, + const Source& src, + VectorRef selectors, + const BlockStatement* body); + + /// Destructor + ~CaseStatement() override; + + /// @returns true if this item contains a default selector + bool ContainsDefault() const; + + /// The case selectors, empty if none set + const tint::Vector selectors; + + /// The case body + const BlockStatement* const body; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CASE_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.cc new file mode 100644 index 000000000..10cfaa62c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.cc @@ -0,0 +1,49 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/color_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::ColorAttribute); + +namespace tint::ast { + +ColorAttribute::ColorAttribute(NodeID nid, const Source& src, const Expression* exp) + : Base(nid, src), expr(exp) { + TINT_ASSERT(expr); +} + +ColorAttribute::~ColorAttribute() = default; + +std::string ColorAttribute::Name() const { + return "color"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.h new file mode 100644 index 000000000..f4987ef6a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/color_attribute.h @@ -0,0 +1,61 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_COLOR_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_COLOR_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" + +// Forward declarations +namespace tint::ast { +class Expression; +} + +namespace tint::ast { + +/// A color attribute (enabled with the frame-buffer fetch extension) +class ColorAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the frame-buffer index value + ColorAttribute(NodeID nid, const Source& src, const Expression* expr); + ~ColorAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The index value expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_COLOR_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.cc new file mode 100644 index 000000000..e86f42bf3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.cc @@ -0,0 +1,48 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/compound_assignment_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::CompoundAssignmentStatement); + +namespace tint::ast { + +CompoundAssignmentStatement::CompoundAssignmentStatement(NodeID nid, + const Source& src, + const Expression* l, + const Expression* r, + core::BinaryOp o) + : Base(nid, src), lhs(l), rhs(r), op(o) { + TINT_ASSERT(lhs); + TINT_ASSERT(rhs); +} + +CompoundAssignmentStatement::~CompoundAssignmentStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.h new file mode 100644 index 000000000..9fccee952 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/compound_assignment_statement.h @@ -0,0 +1,67 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_COMPOUND_ASSIGNMENT_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_COMPOUND_ASSIGNMENT_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/binary_expression.h" +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// A compound assignment statement +class CompoundAssignmentStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the compound assignment statement source + /// @param lhs the left side of the expression + /// @param rhs the right side of the expression + /// @param op the binary operator + CompoundAssignmentStatement(NodeID nid, + const Source& source, + const Expression* lhs, + const Expression* rhs, + core::BinaryOp op); + + /// Destructor + ~CompoundAssignmentStatement() override; + + /// left side expression + const Expression* const lhs; + + /// right side expression + const Expression* const rhs; + + /// the binary operator + const core::BinaryOp op; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_COMPOUND_ASSIGNMENT_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/const.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/const.cc new file mode 100644 index 000000000..aa482fc3b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/const.cc @@ -0,0 +1,54 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/const.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Const); + +namespace tint::ast { + +Const::Const(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + const Expression* init, + VectorRef attrs) + : Base(nid, src, n, ty, init, std::move(attrs)) { + TINT_ASSERT(init != nullptr); +} + +Const::~Const() = default; + +const char* Const::Kind() const { + return "const"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/const.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/const.h new file mode 100644 index 000000000..87574f70c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/const.h @@ -0,0 +1,70 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CONST_H_ +#define SRC_TINT_LANG_WGSL_AST_CONST_H_ + +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// A "const" declaration is a name for a module-scoped or function-scoped creation-time value. +/// const must have a initializer expression. +/// +/// Examples: +/// +/// ``` +/// const n = 123; // Abstract-integer typed constant +/// const pi = 3.14159265359; // Abstract-float typed constant +/// const max_f32 : f32 = 0x1.fffffep+127; // f32 typed constant +/// ``` +/// @see https://www.w3.org/TR/WGSL/#creation-time-consts +class Const final : public Castable { + public: + /// Create a 'const' creation-time value variable. + /// @param source the variable source + /// @param name the variable name + /// @param type the declared variable type + /// @param initializer the initializer expression. Must not be nullptr. + /// @param attributes the variable attributes + Const(NodeID nid, + const Source& source, + const Identifier* name, + Type type, + const Expression* initializer, + VectorRef attributes); + + /// Destructor + ~Const() override; + + /// @returns "const" + const char* Kind() const override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CONST_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.cc new file mode 100644 index 000000000..97a66bd3a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.cc @@ -0,0 +1,43 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/const_assert.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::ConstAssert); + +namespace tint::ast { + +ConstAssert::ConstAssert(NodeID nid, const Source& src, const Expression* cond) + : Base(nid, src), condition(cond) { + TINT_ASSERT(cond); +} + +ConstAssert::~ConstAssert() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.h new file mode 100644 index 000000000..abd0fc62e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/const_assert.h @@ -0,0 +1,54 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CONST_ASSERT_H_ +#define SRC_TINT_LANG_WGSL_AST_CONST_ASSERT_H_ + +#include "src/tint/lang/wgsl/ast/statement.h" +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// A `const_assert` statement +class ConstAssert final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the variable statement source + /// @param condition the assertion condition + ConstAssert(NodeID nid, const Source& source, const Expression* condition); + + /// Destructor + ~ConstAssert() override; + + /// The assertion condition + const Expression* const condition; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CONST_ASSERT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.cc new file mode 100644 index 000000000..e8bead9e1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.cc @@ -0,0 +1,40 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/continue_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::ContinueStatement); + +namespace tint::ast { + +ContinueStatement::ContinueStatement(NodeID nid, const Source& src) : Base(nid, src) {} + +ContinueStatement::~ContinueStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.h new file mode 100644 index 000000000..9b65e7f40 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/continue_statement.h @@ -0,0 +1,49 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_CONTINUE_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_CONTINUE_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// An continue statement +class ContinueStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + ContinueStatement(NodeID nid, const Source& src); + + /// Destructor + ~ContinueStatement() override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_CONTINUE_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.cc new file mode 100644 index 000000000..05affed81 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.cc @@ -0,0 +1,48 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/diagnostic_attribute.h" + +#include +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticAttribute); + +namespace tint::ast { + +DiagnosticAttribute::DiagnosticAttribute(NodeID nid, const Source& src, DiagnosticControl&& dc) + : Base(nid, src), control(std::move(dc)) {} + +DiagnosticAttribute::~DiagnosticAttribute() = default; + +std::string DiagnosticAttribute::Name() const { + return "diagnostic"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.h new file mode 100644 index 000000000..259210ce2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/diagnostic_control.h" + +namespace tint::ast { + +/// A diagnostic attribute +class DiagnosticAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param dc the diagnostic control + DiagnosticAttribute(NodeID nid, const Source& src, DiagnosticControl&& dc); + ~DiagnosticAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The diagnostic control. + const DiagnosticControl control; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.cc new file mode 100644 index 000000000..772551f73 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.cc @@ -0,0 +1,47 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/diagnostic_control.h" + +#include + +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/enums.h" + +namespace tint::ast { + +DiagnosticControl::DiagnosticControl() = default; + +DiagnosticControl::DiagnosticControl(wgsl::DiagnosticSeverity sev, const DiagnosticRuleName* rule) + : severity(sev), rule_name(rule) { + TINT_ASSERT(rule != nullptr); +} + +DiagnosticControl::DiagnosticControl(DiagnosticControl&&) = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.h new file mode 100644 index 000000000..9441c51ba --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_control.h @@ -0,0 +1,67 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_CONTROL_H_ +#define SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_CONTROL_H_ + +#include +#include + +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/utils/diagnostic/diagnostic.h" + +// Forward declarations +namespace tint::ast { +class DiagnosticRuleName; +} // namespace tint::ast + +namespace tint::ast { + +/// A diagnostic control used for diagnostic directives and attributes. +struct DiagnosticControl { + public: + /// Default constructor. + DiagnosticControl(); + + /// Constructor + /// @param sev the diagnostic severity + /// @param rule the diagnostic rule name + DiagnosticControl(wgsl::DiagnosticSeverity sev, const DiagnosticRuleName* rule); + + /// Move constructor + DiagnosticControl(DiagnosticControl&&); + + /// The diagnostic severity control. + wgsl::DiagnosticSeverity severity = wgsl::DiagnosticSeverity::kUndefined; + + /// The diagnostic rule name. + const DiagnosticRuleName* rule_name = nullptr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_CONTROL_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.cc new file mode 100644 index 000000000..d65255b63 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.cc @@ -0,0 +1,41 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/diagnostic_directive.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticDirective); + +namespace tint::ast { + +DiagnosticDirective::DiagnosticDirective(NodeID nid, const Source& src, DiagnosticControl&& dc) + : Base(nid, src), control(std::move(dc)) {} + +DiagnosticDirective::~DiagnosticDirective() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.h new file mode 100644 index 000000000..099fa7d03 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_directive.h @@ -0,0 +1,62 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_DIRECTIVE_H_ +#define SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_DIRECTIVE_H_ + +#include +#include +#include + +#include "src/tint/lang/wgsl/ast/diagnostic_control.h" +#include "src/tint/lang/wgsl/ast/node.h" + +namespace tint::ast { + +/// A "diagnostic" directive. Example: +/// ``` +/// // Turn off diagnostics for derivative uniformity violations. +/// diagnostic(off, derivative_uniformity); +/// ``` +class DiagnosticDirective final : public Castable { + public: + /// Create a extension + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param dc the diagnostic control + DiagnosticDirective(NodeID nid, const Source& src, DiagnosticControl&& dc); + + /// Destructor + ~DiagnosticDirective() override; + + /// The diagnostic control. + const DiagnosticControl control; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_DIRECTIVE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.cc new file mode 100644 index 000000000..2c65c1cf2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.cc @@ -0,0 +1,73 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/diagnostic_rule_name.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticRuleName); + +namespace tint::ast { + +DiagnosticRuleName::DiagnosticRuleName(NodeID nid, const Source& src, const Identifier* n) + : Base(nid, src), name(n) { + TINT_ASSERT(name != nullptr); + if (name) { + // It is invalid for a diagnostic rule name to be templated + TINT_ASSERT(!name->Is()); + } +} + +DiagnosticRuleName::DiagnosticRuleName(NodeID nid, + const Source& src, + const Identifier* c, + const Identifier* n) + : Base(nid, src), category(c), name(n) { + TINT_ASSERT(name != nullptr); + if (name) { + // It is invalid for a diagnostic rule name to be templated + TINT_ASSERT(!name->Is()); + } + if (category) { + // It is invalid for a diagnostic rule category to be templated + TINT_ASSERT(!category->Is()); + } +} + +DiagnosticRuleName::~DiagnosticRuleName() = default; + +std::string DiagnosticRuleName::String() const { + if (category) { + return category->symbol.Name() + "." + name->symbol.Name(); + } else { + return name->symbol.Name(); + } +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.h new file mode 100644 index 000000000..829c6fd80 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/diagnostic_rule_name.h @@ -0,0 +1,75 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_RULE_NAME_H_ +#define SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_RULE_NAME_H_ + +#include + +#include "src/tint/lang/wgsl/ast/node.h" + +// Forward declarations +namespace tint::ast { +class Identifier; +} // namespace tint::ast + +namespace tint::ast { + +/// A diagnostic rule name used for diagnostic directives and attributes. +class DiagnosticRuleName final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param name the rule name + DiagnosticRuleName(NodeID nid, const Source& src, const Identifier* name); + + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param category the rule category. + /// @param name the rule name + DiagnosticRuleName(NodeID nid, + const Source& src, + const Identifier* category, + const Identifier* name); + + ~DiagnosticRuleName() override; + + /// @return the full name of this diagnostic rule, either as `name` or `category.name`. + std::string String() const; + + /// The diagnostic rule category (category.name) + Identifier const* const category = nullptr; + + /// The diagnostic rule name. + Identifier const* const name; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_DIAGNOSTIC_RULE_NAME_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.cc new file mode 100644 index 000000000..ff201b2c8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.cc @@ -0,0 +1,40 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/discard_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::DiscardStatement); + +namespace tint::ast { + +DiscardStatement::DiscardStatement(NodeID nid, const Source& src) : Base(nid, src) {} + +DiscardStatement::~DiscardStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.h new file mode 100644 index 000000000..221861ae2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/discard_statement.h @@ -0,0 +1,49 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_DISCARD_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_DISCARD_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// A discard statement +class DiscardStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + DiscardStatement(NodeID nid, const Source& src); + + /// Destructor + ~DiscardStatement() override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_DISCARD_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/enable.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/enable.cc new file mode 100644 index 000000000..636e02d21 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/enable.cc @@ -0,0 +1,50 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/enable.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Enable); + +namespace tint::ast { + +Enable::Enable(NodeID nid, const Source& src, VectorRef exts) + : Base(nid, src), extensions(std::move(exts)) {} + +Enable::~Enable() = default; + +bool Enable::HasExtension(wgsl::Extension ext) const { + for (auto* e : extensions) { + if (e->name == ext) { + return true; + } + } + return false; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/enable.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/enable.h new file mode 100644 index 000000000..17b765461 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/enable.h @@ -0,0 +1,65 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_ENABLE_H_ +#define SRC_TINT_LANG_WGSL_AST_ENABLE_H_ + +#include +#include +#include + +#include "src/tint/lang/wgsl/ast/extension.h" + +namespace tint::ast { + +/// An "enable" directive. Example: +/// ``` +/// // Enable an extension named "f16" +/// enable f16; +/// ``` +class Enable final : public Castable { + public: + /// Create a extension + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param exts the extensions being enabled by this directive + Enable(NodeID nid, const Source& src, VectorRef exts); + + /// Destructor + ~Enable() override; + + /// @param ext the extension to search for + /// @returns true if this Enable lists the given extension + bool HasExtension(wgsl::Extension ext) const; + + /// The extensions being enabled by this directive + const tint::Vector extensions; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_ENABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/expression.cc new file mode 100644 index 000000000..7561a7d6c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/expression.cc @@ -0,0 +1,38 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Expression); + +namespace tint::ast { + +Expression::Expression(NodeID nid, const Source& src) : Base(nid, src) {} + +Expression::~Expression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/expression.h new file mode 100644 index 000000000..0588d6670 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/expression.h @@ -0,0 +1,52 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_EXPRESSION_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/node.h" + +namespace tint::ast { + +/// Base expression class +class Expression : public Castable { + public: + ~Expression() override; + + protected: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + Expression(NodeID nid, const Source& src); +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/extension.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/extension.cc new file mode 100644 index 000000000..c31dd5067 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/extension.cc @@ -0,0 +1,46 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/extension.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +//! @cond Doxygen_Suppress +// Doxygen gets confused with tint::ast::Extension and tint::wgsl::Extension + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Extension); + +namespace tint::ast { + +Extension::Extension(NodeID nid, const Source& src, wgsl::Extension ext) + : Base(nid, src), name(ext) {} + +Extension::~Extension() = default; + +} // namespace tint::ast + +//! @endcond diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/extension.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/extension.h new file mode 100644 index 000000000..7d9b600ad --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/extension.h @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_EXTENSION_H_ +#define SRC_TINT_LANG_WGSL_AST_EXTENSION_H_ + +#include "src/tint/lang/wgsl/ast/node.h" +#include "src/tint/lang/wgsl/enums.h" + +namespace tint::ast { + +/// An extension used in an "enable" directive. Example: +/// ``` +/// enable f16; +/// ``` +class Extension final : public Castable { + public: + /// Create a extension + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param ext the extension + Extension(NodeID nid, const Source& src, wgsl::Extension ext); + + /// Destructor + ~Extension() override; + + /// The extension name + const wgsl::Extension name; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_EXTENSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.cc new file mode 100644 index 000000000..fac00e372 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.cc @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/float_literal_expression.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::FloatLiteralExpression); + +namespace tint::ast { + +FloatLiteralExpression::FloatLiteralExpression(NodeID nid, + const Source& src, + double val, + Suffix suf) + : Base(nid, src), value(val), suffix(suf) {} + +FloatLiteralExpression::~FloatLiteralExpression() = default; + +std::string_view ToString(FloatLiteralExpression::Suffix suffix) { + switch (suffix) { + default: + return ""; + case FloatLiteralExpression::Suffix::kF: + return "f"; + case FloatLiteralExpression::Suffix::kH: + return "h"; + } +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.h new file mode 100644 index 000000000..e27c84895 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/float_literal_expression.h @@ -0,0 +1,81 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_FLOAT_LITERAL_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_FLOAT_LITERAL_EXPRESSION_H_ + +#include + +#include "src/tint/lang/wgsl/ast/literal_expression.h" + +namespace tint::ast { + +/// A float literal +class FloatLiteralExpression final : public Castable { + public: + /// Literal suffix + enum class Suffix { + /// No suffix + kNone, + /// 'f' suffix (f32) + kF, + /// 'h' suffix (f16) + kH, + }; + + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param val the literal value + /// @param suf the literal suffix + FloatLiteralExpression(NodeID nid, const Source& src, double val, Suffix suf); + ~FloatLiteralExpression() override; + + /// The literal value + const double value; + + /// The literal suffix + const Suffix suffix; +}; + +/// @param suffix the enum value +/// @returns the string for the given enum value +std::string_view ToString(FloatLiteralExpression::Suffix suffix); + +/// Writes the float literal suffix to the stream. +/// @param out the stream to write to +/// @param suffix the suffix to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, FloatLiteralExpression::Suffix suffix) { + return out << ToString(suffix); +} + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_FLOAT_LITERAL_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.cc new file mode 100644 index 000000000..ff7e71805 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.cc @@ -0,0 +1,60 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::ForLoopStatement); + +namespace tint::ast { + +ForLoopStatement::ForLoopStatement(NodeID nid, + const Source& src, + const Statement* init, + const Expression* cond, + const Statement* cont, + const BlockStatement* b, + VectorRef attrs) + : Base(nid, src), + initializer(init), + condition(cond), + continuing(cont), + body(b), + attributes(std::move(attrs)) { + TINT_ASSERT(body); + + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +ForLoopStatement::~ForLoopStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.h new file mode 100644 index 000000000..13d8a1365 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/for_loop_statement.h @@ -0,0 +1,77 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_FOR_LOOP_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_FOR_LOOP_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/block_statement.h" + +namespace tint::ast { + +class Expression; + +/// A for loop statement +class ForLoopStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the for loop statement source + /// @param initializer the optional loop initializer statement + /// @param condition the optional loop condition expression + /// @param continuing the optional continuing statement + /// @param body the loop body + /// @param attributes the while statement attributes + ForLoopStatement(NodeID nid, + const Source& source, + const Statement* initializer, + const Expression* condition, + const Statement* continuing, + const BlockStatement* body, + VectorRef attributes); + + /// Destructor + ~ForLoopStatement() override; + + /// The initializer statement + const Statement* const initializer; + + /// The condition expression + const Expression* const condition; + + /// The continuing statement + const Statement* const continuing; + + /// The loop body block + const BlockStatement* const body; + + /// The attribute list + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_FOR_LOOP_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/function.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/function.cc new file mode 100644 index 000000000..ef33dd275 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/function.cc @@ -0,0 +1,105 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/function.h" + +#include "src/tint/lang/wgsl/ast/builder.h" +#include "src/tint/lang/wgsl/ast/stage_attribute.h" +#include "src/tint/lang/wgsl/ast/type.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Function); + +namespace tint::ast { + +Function::Function(NodeID nid, + const Source& src, + const Identifier* n, + VectorRef parameters, + Type return_ty, + const BlockStatement* b, + VectorRef attrs, + VectorRef return_type_attrs) + : Base(nid, src), + name(n), + params(std::move(parameters)), + return_type(return_ty), + body(b), + attributes(std::move(attrs)), + return_type_attributes(std::move(return_type_attrs)) { + TINT_ASSERT(name); + if (name) { + TINT_ASSERT(!name->Is()); + } + for (auto* param : params) { + TINT_ASSERT(tint::Is(param)); + } + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } + for (auto* attr : return_type_attributes) { + TINT_ASSERT(attr); + } +} + +Function::~Function() = default; + +PipelineStage Function::PipelineStage() const { + if (auto* stage = GetAttribute(attributes)) { + return stage->stage; + } + return PipelineStage::kNone; +} + +const Function* FunctionList::Find(Symbol sym) const { + for (auto* func : *this) { + if (func->name->symbol == sym) { + return func; + } + } + return nullptr; +} + +const Function* FunctionList::Find(Symbol sym, PipelineStage stage) const { + for (auto* func : *this) { + if (func->name->symbol == sym && func->PipelineStage() == stage) { + return func; + } + } + return nullptr; +} + +bool FunctionList::HasStage(ast::PipelineStage stage) const { + for (auto* func : *this) { + if (func->PipelineStage() == stage) { + return true; + } + } + return false; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/function.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/function.h new file mode 100644 index 000000000..d3bd3e678 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/function.h @@ -0,0 +1,129 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_FUNCTION_H_ +#define SRC_TINT_LANG_WGSL_AST_FUNCTION_H_ + +#include +#include +#include +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/binding_attribute.h" +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/builtin_attribute.h" +#include "src/tint/lang/wgsl/ast/group_attribute.h" +#include "src/tint/lang/wgsl/ast/location_attribute.h" +#include "src/tint/lang/wgsl/ast/parameter.h" +#include "src/tint/lang/wgsl/ast/pipeline_stage.h" +#include "src/tint/utils/symbol/symbol.h" + +// Forward declarations +namespace tint::ast { +class Identifier; +class IdentifierExpression; +} // namespace tint::ast + +namespace tint::ast { + +/// A Function statement. +class Function final : public Castable { + public: + /// Create a function + /// @param nid the unique node identifier + /// @param source the variable source + /// @param name the function name + /// @param params the function parameters + /// @param return_type the return type + /// @param body the function body + /// @param attributes the function attributes + /// @param return_type_attributes the return type attributes + Function(NodeID nid, + const Source& source, + const Identifier* name, + VectorRef params, + Type return_type, + const BlockStatement* body, + VectorRef attributes, + VectorRef return_type_attributes); + + /// Destructor + ~Function() override; + + /// @returns the functions pipeline stage or None if not set + ast::PipelineStage PipelineStage() const; + + /// @returns true if this function is an entry point + bool IsEntryPoint() const { return PipelineStage() != ast::PipelineStage::kNone; } + + /// The function name + const Identifier* const name; + + /// The function params + const tint::Vector params; + + /// The function return type + const Type return_type; + + /// The function body + const BlockStatement* const body; + + /// The attributes attached to this function + const tint::Vector attributes; + + /// The attributes attached to the function return type. + const tint::Vector return_type_attributes; +}; + +/// A list of functions +class FunctionList : public tint::Vector { + public: + /// Appends f to the end of the list + /// @param f the function to append to this list + void Add(const Function* f) { this->Push(f); } + + /// Returns the function with the given name + /// @param sym the function symbol to search for + /// @returns the associated function or nullptr if none exists + const Function* Find(Symbol sym) const; + + /// Returns the function with the given name + /// @param sym the function symbol to search for + /// @param stage the pipeline stage + /// @returns the associated function or nullptr if none exists + const Function* Find(Symbol sym, ast::PipelineStage stage) const; + + /// @param stage the pipeline stage + /// @returns true if the Builder contains an entrypoint function with + /// the given stage + bool HasStage(ast::PipelineStage stage) const; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_FUNCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.cc new file mode 100644 index 000000000..97bd82836 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.cc @@ -0,0 +1,47 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/group_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::GroupAttribute); + +namespace tint::ast { + +GroupAttribute::GroupAttribute(NodeID nid, const Source& src, const Expression* exp) + : Base(nid, src), expr(exp) {} + +GroupAttribute::~GroupAttribute() = default; + +std::string GroupAttribute::Name() const { + return "group"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.h new file mode 100644 index 000000000..4c73975c1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/group_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_GROUP_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_GROUP_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A group attribute +class GroupAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the group expression + GroupAttribute(NodeID nid, const Source& src, const Expression* expr); + ~GroupAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The group expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_GROUP_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.cc new file mode 100644 index 000000000..f07207021 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.cc @@ -0,0 +1,47 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/id_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::IdAttribute); + +namespace tint::ast { + +IdAttribute::IdAttribute(NodeID nid, const Source& src, const Expression* exp) + : Base(nid, src), expr(exp) {} + +IdAttribute::~IdAttribute() = default; + +std::string IdAttribute::Name() const { + return "id"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.h new file mode 100644 index 000000000..8ec5f16fb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/id_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_ID_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_ID_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// An id attribute for pipeline-overridable constants +class IdAttribute final : public Castable { + public: + /// Create an id attribute. + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the numeric id expression + IdAttribute(NodeID nid, const Source& src, const Expression* expr); + ~IdAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The id expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_ID_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.cc new file mode 100644 index 000000000..04b132977 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.cc @@ -0,0 +1,42 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/identifier.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Identifier); + +namespace tint::ast { + +Identifier::Identifier(NodeID nid, const Source& src, Symbol sym) : Base(nid, src), symbol(sym) { + TINT_ASSERT(symbol.IsValid()); +} + +Identifier::~Identifier() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.h new file mode 100644 index 000000000..97ece21df --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier.h @@ -0,0 +1,54 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_IDENTIFIER_H_ +#define SRC_TINT_LANG_WGSL_AST_IDENTIFIER_H_ + +#include "src/tint/lang/wgsl/ast/node.h" +#include "src/tint/utils/symbol/symbol.h" + +namespace tint::ast { + +/// An identifier +class Identifier : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param sym the symbol for the identifier + Identifier(NodeID nid, const Source& src, Symbol sym); + + /// Destructor + ~Identifier() override; + + /// The symbol for the identifier + const Symbol symbol; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_IDENTIFIER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.cc new file mode 100644 index 000000000..038c83b48 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/identifier_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::IdentifierExpression); + +namespace tint::ast { + +IdentifierExpression::IdentifierExpression(NodeID nid, const Source& src, const Identifier* ident) + : Base(nid, src), identifier(ident) { + TINT_ASSERT(identifier != nullptr); +} + +IdentifierExpression::~IdentifierExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.h new file mode 100644 index 000000000..c3119725b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/identifier_expression.h @@ -0,0 +1,58 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_IDENTIFIER_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_IDENTIFIER_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" + +// Forward declarations +namespace tint::ast { +class Identifier; +} + +namespace tint::ast { + +/// An identifier expression +class IdentifierExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param identifier the identifier + IdentifierExpression(NodeID nid, const Source& src, const Identifier* identifier); + + /// Destructor + ~IdentifierExpression() override; + + /// The identifier for the expression + Identifier const* const identifier; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_IDENTIFIER_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.cc new file mode 100644 index 000000000..665dcb836 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.cc @@ -0,0 +1,59 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/if_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::IfStatement); + +namespace tint::ast { + +IfStatement::IfStatement(NodeID nid, + const Source& src, + const Expression* cond, + const BlockStatement* b, + const Statement* else_stmt, + VectorRef attrs) + : Base(nid, src), + condition(cond), + body(b), + else_statement(else_stmt), + attributes(std::move(attrs)) { + TINT_ASSERT(condition); + TINT_ASSERT(body); + if (else_statement) { + TINT_ASSERT((else_statement->IsAnyOf())); + } + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +IfStatement::~IfStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.h new file mode 100644 index 000000000..a16834ce1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/if_statement.h @@ -0,0 +1,73 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_IF_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_IF_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// An if statement +class IfStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param condition the if condition + /// @param body the if body + /// @param else_stmt the else statement, or nullptr + /// @param attributes the if statement attributes + IfStatement(NodeID nid, + const Source& src, + const Expression* condition, + const BlockStatement* body, + const Statement* else_stmt, + VectorRef attributes); + + /// Destructor + ~IfStatement() override; + + /// The if condition or nullptr if none set + const Expression* const condition; + + /// The if body + const BlockStatement* const body; + + /// The optional else statement, or nullptr + const Statement* const else_statement; + + /// The attribute list + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_IF_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.cc new file mode 100644 index 000000000..9ec0ca999 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.cc @@ -0,0 +1,44 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::IncrementDecrementStatement); + +namespace tint::ast { + +IncrementDecrementStatement::IncrementDecrementStatement(NodeID nid, + const Source& src, + const Expression* l, + bool inc) + : Base(nid, src), lhs(l), increment(inc) {} + +IncrementDecrementStatement::~IncrementDecrementStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.h new file mode 100644 index 000000000..030753a30 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/increment_decrement_statement.h @@ -0,0 +1,58 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_INCREMENT_DECREMENT_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_INCREMENT_DECREMENT_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// An increment or decrement statement +class IncrementDecrementStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param lhs the LHS expression + /// @param inc `true` for increment, `false` for decrement + IncrementDecrementStatement(NodeID nid, const Source& src, const Expression* lhs, bool inc); + + /// Destructor + ~IncrementDecrementStatement() override; + + /// The LHS expression. + const Expression* const lhs; + + /// `true` for increment, `false` for decrement. + bool increment; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_INCREMENT_DECREMENT_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.cc new file mode 100644 index 000000000..127e4673e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.cc @@ -0,0 +1,46 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::IndexAccessorExpression); + +namespace tint::ast { + +IndexAccessorExpression::IndexAccessorExpression(NodeID nid, + const Source& src, + const Expression* obj, + const Expression* idx) + : Base(nid, src, obj), index(idx) { + TINT_ASSERT(idx); +} + +IndexAccessorExpression::~IndexAccessorExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.h new file mode 100644 index 000000000..9a275341c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/index_accessor_expression.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_INDEX_ACCESSOR_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_INDEX_ACCESSOR_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/accessor_expression.h" + +namespace tint::ast { + +/// An index accessor expression +class IndexAccessorExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the index accessor source + /// @param obj the object + /// @param idx the index expression + IndexAccessorExpression(NodeID nid, + const Source& source, + const Expression* obj, + const Expression* idx); + + /// Destructor + ~IndexAccessorExpression() override; + + /// the index expression + const Expression* const index; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_INDEX_ACCESSOR_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc new file mode 100644 index 000000000..7ad49ae03 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc @@ -0,0 +1,49 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::InputAttachmentIndexAttribute); + +namespace tint::ast { + +InputAttachmentIndexAttribute::InputAttachmentIndexAttribute(NodeID nid, + const Source& src, + const Expression* exp) + : Base(nid, src), expr(exp) {} + +InputAttachmentIndexAttribute::~InputAttachmentIndexAttribute() = default; + +std::string InputAttachmentIndexAttribute::Name() const { + return "input_attachment_index"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h new file mode 100644 index 000000000..66651d6d2 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h @@ -0,0 +1,62 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_INPUT_ATTACHMENT_INDEX_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_INPUT_ATTACHMENT_INDEX_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" + +// Forward declarations +namespace tint::ast { +class Expression; +} + +namespace tint::ast { + +/// An input attachment attribute (enabled with the input attachments extension) +class InputAttachmentIndexAttribute final + : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the input attachment index value + InputAttachmentIndexAttribute(NodeID nid, const Source& src, const Expression* expr); + ~InputAttachmentIndexAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The index value expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_INPUT_ATTACHMENT_INDEX_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.cc new file mode 100644 index 000000000..b047fb702 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.cc @@ -0,0 +1,52 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/int_literal_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::IntLiteralExpression); + +namespace tint::ast { + +IntLiteralExpression::IntLiteralExpression(NodeID nid, const Source& src, int64_t val, Suffix suf) + : Base(nid, src), value(val), suffix(suf) {} + +IntLiteralExpression::~IntLiteralExpression() = default; + +std::string_view ToString(IntLiteralExpression::Suffix suffix) { + switch (suffix) { + default: + return ""; + case IntLiteralExpression::Suffix::kI: + return "i"; + case IntLiteralExpression::Suffix::kU: + return "u"; + } +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.h new file mode 100644 index 000000000..f1e1df65d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/int_literal_expression.h @@ -0,0 +1,80 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_INT_LITERAL_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_INT_LITERAL_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/literal_expression.h" + +namespace tint::ast { + +/// An integer literal. The literal may have an 'i', 'u' or no suffix. +class IntLiteralExpression final : public Castable { + public: + /// Literal suffix + enum class Suffix { + /// No suffix + kNone, + /// 'i' suffix (i32) + kI, + /// 'u' suffix (u32) + kU, + }; + + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param val the literal value + /// @param suf the literal suffix + IntLiteralExpression(NodeID nid, const Source& src, int64_t val, Suffix suf); + + ~IntLiteralExpression() override; + + /// The literal value + const int64_t value; + + /// The literal suffix + const Suffix suffix; +}; + +/// @param suffix the enum value +/// @returns the string for the given enum value +std::string_view ToString(IntLiteralExpression::Suffix suffix); + +/// Writes the integer literal suffix to the stream. +/// @param out the stream to write to +/// @param suffix the suffix to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, IntLiteralExpression::Suffix suffix) { + return out << ToString(suffix); +} + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_INT_LITERAL_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.cc new file mode 100644 index 000000000..8ddac48f5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.cc @@ -0,0 +1,50 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" + +#include + +#include "src/tint/lang/core/interpolation.h" +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::InterpolateAttribute); + +namespace tint::ast { + +InterpolateAttribute::InterpolateAttribute(NodeID nid, + const Source& src, + core::Interpolation interp) + : Base(nid, src), interpolation(interp) {} + +InterpolateAttribute::~InterpolateAttribute() = default; + +std::string InterpolateAttribute::Name() const { + return "interpolate"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.h new file mode 100644 index 000000000..d72d4a9e1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/interpolate_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_INTERPOLATE_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_INTERPOLATE_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/core/interpolation.h" +#include "src/tint/lang/wgsl/ast/attribute.h" + +namespace tint::ast { + +/// An interpolate attribute +class InterpolateAttribute final : public Castable { + public: + /// Create an interpolate attribute. + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param interpolation the interpolate attribute values + InterpolateAttribute(NodeID nid, const Source& src, core::Interpolation interpolation); + ~InterpolateAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The interpolation attribute values + const core::Interpolation interpolation; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_INTERPOLATE_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.cc new file mode 100644 index 000000000..fa824ba87 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.cc @@ -0,0 +1,44 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/invariant_attribute.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::InvariantAttribute); + +namespace tint::ast { + +InvariantAttribute::InvariantAttribute(NodeID nid, const Source& src) : Base(nid, src) {} + +InvariantAttribute::~InvariantAttribute() = default; + +std::string InvariantAttribute::Name() const { + return "invariant"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.h new file mode 100644 index 000000000..5fbf30829 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/invariant_attribute.h @@ -0,0 +1,52 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_INVARIANT_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_INVARIANT_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" + +namespace tint::ast { + +/// The invariant attribute +class InvariantAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + InvariantAttribute(NodeID nid, const Source& src); + ~InvariantAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_INVARIANT_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/let.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/let.cc new file mode 100644 index 000000000..3b9324fe4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/let.cc @@ -0,0 +1,54 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/let.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Let); + +namespace tint::ast { + +Let::Let(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + const Expression* init, + VectorRef attrs) + : Base(nid, src, n, ty, init, std::move(attrs)) { + TINT_ASSERT(init != nullptr); +} + +Let::~Let() = default; + +const char* Let::Kind() const { + return "let"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/let.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/let.h new file mode 100644 index 000000000..9f49df811 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/let.h @@ -0,0 +1,68 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_LET_H_ +#define SRC_TINT_LANG_WGSL_AST_LET_H_ + +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// A "let" declaration is a name for a function-scoped runtime typed value. +/// +/// Examples: +/// +/// ``` +/// let twice_depth : i32 = width + width; // Must have initializer +/// ``` +/// @see https://www.w3.org/TR/WGSL/#let-decls +class Let final : public Castable { + public: + /// Create a 'let' variable + /// @param nid the unique node identifier + /// @param source the variable source + /// @param name the variable name + /// @param type the declared variable type + /// @param initializer the initializer expression + /// @param attributes the variable attributes + Let(NodeID nid, + const Source& source, + const Identifier* name, + Type type, + const Expression* initializer, + VectorRef attributes); + + /// Destructor + ~Let() override; + + /// @returns "let" + const char* Kind() const override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_LET_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.cc new file mode 100644 index 000000000..910d00ece --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.cc @@ -0,0 +1,38 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/literal_expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::LiteralExpression); + +namespace tint::ast { + +LiteralExpression::LiteralExpression(NodeID nid, const Source& src) : Base(nid, src) {} + +LiteralExpression::~LiteralExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.h new file mode 100644 index 000000000..307ce318e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/literal_expression.h @@ -0,0 +1,51 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_LITERAL_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_LITERAL_EXPRESSION_H_ + +#include + +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// Base class for a literal value expressions +class LiteralExpression : public Castable { + public: + ~LiteralExpression() override; + + protected: + /// Constructor + /// @param nid the unique node identifier + /// @param src the input source + LiteralExpression(NodeID nid, const Source& src); +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_LITERAL_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.cc new file mode 100644 index 000000000..b006515db --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.cc @@ -0,0 +1,47 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/location_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::LocationAttribute); + +namespace tint::ast { + +LocationAttribute::LocationAttribute(NodeID nid, const Source& src, const Expression* exp) + : Base(nid, src), expr(exp) {} + +LocationAttribute::~LocationAttribute() = default; + +std::string LocationAttribute::Name() const { + return "location"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.h new file mode 100644 index 000000000..1198c4b21 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/location_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_LOCATION_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_LOCATION_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A location attribute +class LocationAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the location expression + LocationAttribute(NodeID nid, const Source& src, const Expression* expr); + ~LocationAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The location expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_LOCATION_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.cc new file mode 100644 index 000000000..862fab7b6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.cc @@ -0,0 +1,52 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/loop_statement.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::LoopStatement); + +namespace tint::ast { + +LoopStatement::LoopStatement(NodeID nid, + const Source& src, + const BlockStatement* b, + const BlockStatement* cont, + VectorRef attrs) + : Base(nid, src), body(b), continuing(cont), attributes(std::move(attrs)) { + TINT_ASSERT(body); + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +LoopStatement::~LoopStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.h new file mode 100644 index 000000000..48d2502b3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/loop_statement.h @@ -0,0 +1,64 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_LOOP_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_LOOP_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/block_statement.h" + +namespace tint::ast { + +/// A loop statement +class LoopStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the loop statement source + /// @param body the body statements + /// @param continuing the continuing statements + /// @param attributes the while statement attributes + LoopStatement(NodeID nid, + const Source& source, + const BlockStatement* body, + const BlockStatement* continuing, + VectorRef attributes); + /// Destructor + ~LoopStatement() override; + + /// The loop body + const BlockStatement* const body; + + /// The continuing statements + const BlockStatement* const continuing; + + /// The attribute list + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_LOOP_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.cc new file mode 100644 index 000000000..0b9d84a16 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.cc @@ -0,0 +1,51 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/member_accessor_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::MemberAccessorExpression); + +namespace tint::ast { + +MemberAccessorExpression::MemberAccessorExpression(NodeID nid, + const Source& src, + const Expression* obj, + const Identifier* mem) + : Base(nid, src, obj), member(mem) { + TINT_ASSERT(member); + + // It is currently invalid for a structure to hold a templated member + if (member) { + TINT_ASSERT(!member->Is()); + } +} + +MemberAccessorExpression::~MemberAccessorExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.h new file mode 100644 index 000000000..58180a9f5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/member_accessor_expression.h @@ -0,0 +1,59 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_MEMBER_ACCESSOR_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_MEMBER_ACCESSOR_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/accessor_expression.h" +#include "src/tint/lang/wgsl/ast/identifier_expression.h" + +namespace tint::ast { + +/// A member accessor expression +class MemberAccessorExpression final + : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the member accessor expression source + /// @param object the object + /// @param member the member + MemberAccessorExpression(NodeID nid, + const Source& source, + const Expression* object, + const Identifier* member); + + /// Destructor + ~MemberAccessorExpression() override; + + /// The member expression + const Identifier* const member; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_MEMBER_ACCESSOR_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/module.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/module.cc new file mode 100644 index 000000000..dbd55b8a3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/module.cc @@ -0,0 +1,132 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/module.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" +#include "src/tint/lang/wgsl/ast/type_decl.h" +#include "src/tint/utils/rtti/switch.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Module); + +namespace tint::ast { + +Module::Module(NodeID nid, const Source& src) : Base(nid, src) {} + +Module::Module(NodeID nid, const Source& src, VectorRef global_decls) + : Base(nid, src), global_declarations_(std::move(global_decls)) { + for (auto* decl : global_declarations_) { + if (decl == nullptr) { + continue; + } + BinGlobalDeclaration(decl); + } +} + +Module::~Module() = default; + +const TypeDecl* Module::LookupType(Symbol name) const { + for (auto* ty : TypeDecls()) { + if (ty->name->symbol == name) { + return ty; + } + } + return nullptr; +} + +void Module::AddGlobalDeclaration(const tint::ast::Node* decl) { + BinGlobalDeclaration(decl); + global_declarations_.Push(decl); +} + +void Module::BinGlobalDeclaration(const tint::ast::Node* decl) { + Switch( + decl, // + [&](const TypeDecl* type) { type_decls_.Push(type); }, + [&](const Function* func) { functions_.Push(func); }, + [&](const Variable* var) { global_variables_.Push(var); }, + [&](const DiagnosticDirective* diagnostic) { diagnostic_directives_.Push(diagnostic); }, + [&](const Enable* enable) { enables_.Push(enable); }, + [&](const ast::Requires* req) { requires_.Push(req); }, + [&](const ConstAssert* assertion) { const_asserts_.Push(assertion); }, // + TINT_ICE_ON_NO_MATCH); +} + +void Module::AddDiagnosticDirective(const DiagnosticDirective* directive) { + TINT_ASSERT(directive); + global_declarations_.Push(directive); + diagnostic_directives_.Push(directive); +} + +void Module::AddEnable(const Enable* enable) { + TINT_ASSERT(enable); + global_declarations_.Push(enable); + enables_.Push(enable); +} + +void Module::AddRequires(const ast::Requires* req) { + TINT_ASSERT(req); + global_declarations_.Push(req); + requires_.Push(req); +} + +void Module::AddGlobalVariable(const Variable* var) { + TINT_ASSERT(var); + global_variables_.Push(var); + global_declarations_.Push(var); +} + +void Module::AddConstAssert(const ConstAssert* assertion) { + TINT_ASSERT(assertion); + const_asserts_.Push(assertion); + global_declarations_.Push(assertion); +} + +void Module::AddTypeDecl(const TypeDecl* type) { + TINT_ASSERT(type); + type_decls_.Push(type); + global_declarations_.Push(type); +} + +void Module::AddFunction(const Function* func) { + TINT_ASSERT(func); + functions_.Push(func); + global_declarations_.Push(func); +} + +bool Module::HasOverrides() const { + for (auto* var : global_variables_) { + if (var->As()) { + return true; + } + } + return false; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/module.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/module.h new file mode 100644 index 000000000..e04fd49c5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/module.h @@ -0,0 +1,173 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_MODULE_H_ +#define SRC_TINT_LANG_WGSL_AST_MODULE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/const_assert.h" +#include "src/tint/lang/wgsl/ast/diagnostic_directive.h" +#include "src/tint/lang/wgsl/ast/enable.h" +#include "src/tint/lang/wgsl/ast/function.h" +#include "src/tint/lang/wgsl/ast/requires.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint::ast { + +class TypeDecl; + +/// Module holds the top-level AST types, functions and global variables used by +/// a Program. +class Module final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + Module(NodeID nid, const Source& src); + + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param global_decls the list of global types, functions, and variables, in + /// the order they were declared in the source program + Module(NodeID nid, const Source& src, VectorRef global_decls); + + /// Destructor + ~Module() override; + + /// @returns the declaration-ordered global declarations for the module + const auto& GlobalDeclarations() const { return global_declarations_; } + + /// Add a global variable to the module + /// @param var the variable to add + void AddGlobalVariable(const Variable* var); + + /// @returns true if the module has the global declaration `decl` + /// @param decl the declaration to check + bool HasGlobalDeclaration(Node* decl) const { + for (auto* d : global_declarations_) { + if (d == decl) { + return true; + } + } + return false; + } + + /// Adds a global declaration to the module. + /// @param decl the declaration to add + void AddGlobalDeclaration(const tint::ast::Node* decl); + + /// @returns the global variables for the module + const auto& GlobalVariables() const { return global_variables_; } + + /// @returns the global variables for the module + auto& GlobalVariables() { return global_variables_; } + + /// @returns the global variable declarations of kind 'T' for the module + template + requires(traits::IsTypeOrDerived) + auto Globals() const { + tint::Vector out; + out.Reserve(global_variables_.Length()); + for (auto* global : global_variables_) { + if (auto* var = global->As()) { + out.Push(var); + } + } + return out; + } + + /// Add a diagnostic directive to the module + /// @param diagnostic the diagnostic directive to add + void AddDiagnosticDirective(const DiagnosticDirective* diagnostic); + + /// Add a enable directive to the module + /// @param ext the enable directive to add + void AddEnable(const Enable* ext); + + /// Add a requires directive to the module + /// @param req the requires directive to add + void AddRequires(const Requires* req); + + /// @returns the diagnostic directives for the module + const auto& DiagnosticDirectives() const { return diagnostic_directives_; } + + /// @returns the extension set for the module + const auto& Enables() const { return enables_; } + + /// @returns the requires directives for the module + const auto& Requires() const { return requires_; } + + /// Add a global const assertion to the module + /// @param assertion the const assert to add + void AddConstAssert(const ConstAssert* assertion); + + /// @returns the list of global const assertions + const auto& ConstAsserts() const { return const_asserts_; } + + /// Adds a type declaration to the module + /// @param decl the type declaration to add + void AddTypeDecl(const TypeDecl* decl); + + /// @returns the TypeDecl registered as a TypeDecl() + /// @param name the name of the type to search for + const TypeDecl* LookupType(Symbol name) const; + + /// @returns the declared types in the module + const auto& TypeDecls() const { return type_decls_; } + + /// Add a function to the module + /// @param func the function to add + void AddFunction(const Function* func); + + /// @returns the functions declared in the module + const FunctionList& Functions() const { return functions_; } + + /// @returns true if the module has any 'override' declarations + bool HasOverrides() const; + + private: + /// Adds `decl` to either: + /// * #global_declarations_ + /// * #type_decls_ + /// * #functions_ + void BinGlobalDeclaration(const tint::ast::Node* decl); + + tint::Vector global_declarations_; + tint::Vector type_decls_; + FunctionList functions_; + tint::Vector global_variables_; + tint::Vector diagnostic_directives_; + tint::Vector enables_; + tint::Vector requires_; + tint::Vector const_asserts_; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_MODULE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.cc new file mode 100644 index 000000000..6b6450669 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.cc @@ -0,0 +1,44 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/must_use_attribute.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::MustUseAttribute); + +namespace tint::ast { + +MustUseAttribute::MustUseAttribute(NodeID nid, const Source& src) : Base(nid, src) {} + +MustUseAttribute::~MustUseAttribute() = default; + +std::string MustUseAttribute::Name() const { + return "must_use"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.h new file mode 100644 index 000000000..cfcf530bb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/must_use_attribute.h @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_MUST_USE_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_MUST_USE_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" + +namespace tint::ast { + +/// The must_use attribute +class MustUseAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + MustUseAttribute(NodeID nid, const Source& src); + ~MustUseAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_MUST_USE_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/node.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/node.cc new file mode 100644 index 000000000..c6dd9a8a9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/node.cc @@ -0,0 +1,38 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/node.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Node); + +namespace tint::ast { + +Node::Node(NodeID nid, const Source& src) : node_id(nid), source(src) {} + +Node::~Node() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/node.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/node.h new file mode 100644 index 000000000..281654edf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/node.h @@ -0,0 +1,68 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_NODE_H_ +#define SRC_TINT_LANG_WGSL_AST_NODE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/node_id.h" +#include "src/tint/utils/diagnostic/source.h" +#include "src/tint/utils/rtti/castable.h" + +// Forward declarations +namespace tint::ast { +class CloneContext; +} + +namespace tint::ast { + +/// AST base class node +class Node : public Castable { + public: + ~Node() override; + + /// The node identifier, unique for the program. + const NodeID node_id; + + /// The node source data + const Source source; + + protected: + /// Create a new node + /// @param nid the unique node identifier + /// @param src the input source for the node + Node(NodeID nid, const Source& src); + + private: + Node(const Node&) = delete; + Node(Node&&) = delete; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_NODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/node_id.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/node_id.h new file mode 100644 index 000000000..36096c359 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/node_id.h @@ -0,0 +1,55 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_NODE_ID_H_ +#define SRC_TINT_LANG_WGSL_AST_NODE_ID_H_ + +#include +#include + +namespace tint::ast { + +/// NodeID is a unique node identifier for a given Program. +/// NodeIDs are sequentially allocated, starting at 0. +struct NodeID { + /// Equality operator + /// @param other the other NodeID + /// @returns true if the NodeIDs are the same + bool operator==(NodeID other) const { return value == other.value; } + + /// Less-than comparison operator + /// @param other the other NodeID + /// @returns true if the other comes before this node + bool operator<(NodeID other) const { return value < other.value; } + + /// The numerical value for the node identifier + uint32_t value = 0; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_NODE_ID_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/override.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/override.cc new file mode 100644 index 000000000..acb773c32 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/override.cc @@ -0,0 +1,52 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/override.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Override); + +namespace tint::ast { + +Override::Override(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + const Expression* init, + VectorRef attrs) + : Base(nid, src, n, ty, init, std::move(attrs)) {} + +Override::~Override() = default; + +const char* Override::Kind() const { + return "override"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/override.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/override.h new file mode 100644 index 000000000..981b98fe9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/override.h @@ -0,0 +1,71 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_OVERRIDE_H_ +#define SRC_TINT_LANG_WGSL_AST_OVERRIDE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// An "override" declaration - a name for a pipeline-overridable constant. +/// Examples: +/// +/// ``` +/// override radius : i32 = 2; // Can be overridden by name. +/// @id(5) override width : i32 = 2; // Can be overridden by ID. +/// override scale : f32; // No default - must be overridden. +/// ``` +/// @see https://www.w3.org/TR/WGSL/#override-decls +class Override final : public Castable { + public: + /// Create an 'override' pipeline-overridable constant. + /// @param nid the unique node identifier + /// @param source the variable source + /// @param name the variable name + /// @param type the declared variable type + /// @param initializer the initializer expression + /// @param attributes the variable attributes + Override(NodeID nid, + const Source& source, + const Identifier* name, + Type type, + const Expression* initializer, + VectorRef attributes); + + /// Destructor + ~Override() override; + + /// @returns "override" + const char* Kind() const override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_OVERRIDE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.cc new file mode 100644 index 000000000..735a25cac --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.cc @@ -0,0 +1,51 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/parameter.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Parameter); + +namespace tint::ast { + +Parameter::Parameter(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + VectorRef attrs) + : Base(nid, src, n, ty, nullptr, std::move(attrs)) {} + +Parameter::~Parameter() = default; + +const char* Parameter::Kind() const { + return "parameter"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.h new file mode 100644 index 000000000..92c41336d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/parameter.h @@ -0,0 +1,70 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_PARAMETER_H_ +#define SRC_TINT_LANG_WGSL_AST_PARAMETER_H_ + +#include + +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// A formal parameter to a function - a name for a typed value to be passed into a function. +/// Example: +/// +/// ``` +/// fn twice(a: i32) -> i32 { // "a:i32" is the formal parameter +/// return a + a; +/// } +/// ``` +/// +/// @see https://www.w3.org/TR/WGSL/#creation-time-consts +class Parameter final : public Castable { + public: + /// Create a 'parameter' creation-time value variable. + /// @param nid the unique node identifier + /// @param source the variable source + /// @param name the variable name + /// @param type the declared variable type + /// @param attributes the variable attributes + Parameter(NodeID nid, + const Source& source, + const Identifier* name, + Type type, + VectorRef attributes); + + /// Destructor + ~Parameter() override; + + /// @returns "parameter" + const char* Kind() const override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_PARAMETER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.cc new file mode 100644 index 000000000..38b76b807 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.cc @@ -0,0 +1,40 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/phony_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::PhonyExpression); + +namespace tint::ast { + +PhonyExpression::PhonyExpression(NodeID nid, const Source& src) : Base(nid, src) {} + +PhonyExpression::~PhonyExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.h new file mode 100644 index 000000000..7e0962ce9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/phony_expression.h @@ -0,0 +1,50 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_PHONY_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_PHONY_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// Represents the `_` of a phony assignment `_ = ` +/// @see https://www.w3.org/TR/WGSL/#phony-assignment-section +class PhonyExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + PhonyExpression(NodeID nid, const Source& src); + + /// Destructor + ~PhonyExpression() override; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_PHONY_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.cc new file mode 100644 index 000000000..6f591df15 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.cc @@ -0,0 +1,46 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/pipeline_stage.h" + +namespace tint::ast { + +std::string_view ToString(PipelineStage stage) { + switch (stage) { + case PipelineStage::kNone: + return "none"; + case PipelineStage::kVertex: + return "vertex"; + case PipelineStage::kFragment: + return "fragment"; + case PipelineStage::kCompute: + return "compute"; + } + return ""; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.h new file mode 100644 index 000000000..683213c29 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/pipeline_stage.h @@ -0,0 +1,54 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_PIPELINE_STAGE_H_ +#define SRC_TINT_LANG_WGSL_AST_PIPELINE_STAGE_H_ + +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::ast { + +/// The pipeline stage +enum class PipelineStage : uint8_t { kVertex, kFragment, kCompute, kNone }; + +/// @param stage the enum value +/// @returns the string for the given enum value +std::string_view ToString(PipelineStage stage); + +/// @param out the stream to write to +/// @param stage the PipelineStage +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, PipelineStage stage) { + return out << ToString(stage); +} + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_PIPELINE_STAGE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/requires.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/requires.cc new file mode 100644 index 000000000..2af83d16b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/requires.cc @@ -0,0 +1,41 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/requires.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Requires); + +namespace tint::ast { + +Requires::Requires(NodeID nid, const Source& src, LanguageFeatures feats) + : Base(nid, src), features(std::move(feats)) {} + +Requires::~Requires() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/requires.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/requires.h new file mode 100644 index 000000000..02cb91b02 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/requires.h @@ -0,0 +1,66 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_REQUIRES_H_ +#define SRC_TINT_LANG_WGSL_AST_REQUIRES_H_ + +#include +#include +#include + +#include "src/tint/lang/wgsl/ast/node.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/utils/containers/unique_vector.h" + +namespace tint::ast { + +/// A "requires" directive. Example: +/// ``` +/// // Require a language feature named "foo" +/// requires foo; +/// ``` +class Requires final : public Castable { + public: + /// A unique list of WGSL language features + using LanguageFeatures = UniqueVector; + + /// Create a requires directive + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param feats the language features being required by this directive + Requires(NodeID nid, const Source& src, LanguageFeatures feats); + + /// Destructor + ~Requires() override; + + /// The features being required by this directive. + const LanguageFeatures features; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_REQUIRES_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.cc new file mode 100644 index 000000000..97613c75f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/return_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::ReturnStatement); + +namespace tint::ast { + +ReturnStatement::ReturnStatement(NodeID nid, const Source& src) : Base(nid, src), value(nullptr) {} + +ReturnStatement::ReturnStatement(NodeID nid, const Source& src, const Expression* val) + : Base(nid, src), value(val) {} + +ReturnStatement::~ReturnStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.h new file mode 100644 index 000000000..2b1dee49a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/return_statement.h @@ -0,0 +1,59 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_RETURN_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_RETURN_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/lang/wgsl/ast/statement.h" + +namespace tint::ast { + +/// A return statement +class ReturnStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + ReturnStatement(NodeID nid, const Source& src); + + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param value the return value + ReturnStatement(NodeID nid, const Source& src, const Expression* value); + + /// Destructor + ~ReturnStatement() override; + + /// The value returned. May be null. + const Expression* const value; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_RETURN_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.cc new file mode 100644 index 000000000..356e73ebf --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.cc @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/stage_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::StageAttribute); + +namespace tint::ast { + +StageAttribute::StageAttribute(NodeID nid, const Source& src, PipelineStage s) + : Base(nid, src), stage(s) {} + +StageAttribute::~StageAttribute() = default; + +std::string StageAttribute::Name() const { + switch (stage) { + case PipelineStage::kVertex: + return "vertex"; + case PipelineStage::kFragment: + return "fragment"; + case PipelineStage::kCompute: + return "compute"; + case PipelineStage::kNone: + break; + } + return "stage"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.h new file mode 100644 index 000000000..52e043c51 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/stage_attribute.h @@ -0,0 +1,57 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_STAGE_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_STAGE_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/pipeline_stage.h" + +namespace tint::ast { + +/// A workgroup attribute +class StageAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param stage the pipeline stage + /// @param source the source of this attribute + StageAttribute(NodeID nid, const Source& source, PipelineStage stage); + ~StageAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The pipeline stage + const PipelineStage stage; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_STAGE_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/statement.cc new file mode 100644 index 000000000..08408c3ab --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/statement.cc @@ -0,0 +1,89 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/statement.h" + +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Statement); + +namespace tint::ast { + +Statement::Statement(NodeID nid, const Source& src) : Base(nid, src) {} + +Statement::~Statement() = default; + +const char* Statement::Name() const { + if (Is()) { + return "assignment statement"; + } + if (Is()) { + return "block statement"; + } + if (Is()) { + return "break statement"; + } + if (Is()) { + return "case statement"; + } + if (Is()) { + return "function call"; + } + if (Is()) { + return "continue statement"; + } + if (Is()) { + return "discard statement"; + } + if (Is()) { + return "if statement"; + } + if (Is()) { + return "loop statement"; + } + if (Is()) { + return "return statement"; + } + if (Is()) { + return "switch statement"; + } + if (Is()) { + return "variable declaration"; + } + return "statement"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/statement.h new file mode 100644 index 000000000..933abbc67 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/statement.h @@ -0,0 +1,54 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/ast/node.h" + +namespace tint::ast { + +/// Base statement class +class Statement : public Castable { + public: + ~Statement() override; + + /// @returns the human readable name for the statement type. + const char* Name() const; + + protected: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of the expression + Statement(NodeID nid, const Source& src); +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct.cc new file mode 100644 index 000000000..570611962 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct.cc @@ -0,0 +1,54 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/struct.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Struct); + +namespace tint::ast { + +Struct::Struct(NodeID nid, + const Source& src, + const Identifier* n, + VectorRef m, + VectorRef attrs) + : Base(nid, src, n), members(std::move(m)), attributes(std::move(attrs)) { + for (auto* mem : members) { + TINT_ASSERT(mem); + } + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +Struct::~Struct() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct.h new file mode 100644 index 000000000..d20cb7248 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct.h @@ -0,0 +1,68 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_STRUCT_H_ +#define SRC_TINT_LANG_WGSL_AST_STRUCT_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/struct_member.h" +#include "src/tint/lang/wgsl/ast/type_decl.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint::ast { + +/// A struct statement. +class Struct final : public Castable { + public: + /// Create a new struct statement + /// @param nid the unique node identifier + /// @param src the source of this node for the import statement + /// @param name The name of the structure + /// @param members The struct members + /// @param attributes The struct attributes + Struct(NodeID nid, + const Source& src, + const Identifier* name, + VectorRef members, + VectorRef attributes); + + /// Destructor + ~Struct() override; + + /// The members + const tint::Vector members; + + /// The struct attributes + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_STRUCT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.cc new file mode 100644 index 000000000..81d5416c7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.cc @@ -0,0 +1,55 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/struct_member.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::StructMember); + +namespace tint::ast { + +StructMember::StructMember(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + VectorRef attrs) + + : Base(nid, src), name(n), type(ty), attributes(std::move(attrs)) { + TINT_ASSERT(name); + if (name) { + TINT_ASSERT(!name->Is()); + } + TINT_ASSERT(type); + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +StructMember::~StructMember() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.h new file mode 100644 index 000000000..c40c48e26 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member.h @@ -0,0 +1,73 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_H_ +#define SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/type.h" + +// Forward declarations +namespace tint::ast { +class Identifier; +} // namespace tint::ast + +namespace tint::ast { + +/// A struct member statement. +class StructMember final : public Castable { + public: + /// Create a new struct member statement + /// @param nid the unique node identifier + /// @param src the source of this node for the struct member statement + /// @param name The struct member name + /// @param type The struct member type + /// @param attributes The struct member attributes + StructMember(NodeID nid, + const Source& src, + const Identifier* name, + Type type, + VectorRef attributes); + + /// Destructor + ~StructMember() override; + + /// The member name + const Identifier* const name; + + /// The type + const Type type; + + /// The attributes + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.cc new file mode 100644 index 000000000..d50f8298b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.cc @@ -0,0 +1,49 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::StructMemberAlignAttribute); + +namespace tint::ast { + +StructMemberAlignAttribute::StructMemberAlignAttribute(NodeID nid, + const Source& src, + const Expression* a) + : Base(nid, src), expr(a) {} + +StructMemberAlignAttribute::~StructMemberAlignAttribute() = default; + +std::string StructMemberAlignAttribute::Name() const { + return "align"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.h new file mode 100644 index 000000000..c309f852c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_align_attribute.h @@ -0,0 +1,58 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_ALIGN_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_ALIGN_ATTRIBUTE_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A struct member align attribute +class StructMemberAlignAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param align the align expression + StructMemberAlignAttribute(NodeID nid, const Source& src, const Expression* align); + ~StructMemberAlignAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The align expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_ALIGN_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.cc new file mode 100644 index 000000000..2c4ec1c2c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.cc @@ -0,0 +1,49 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::StructMemberSizeAttribute); + +namespace tint::ast { + +StructMemberSizeAttribute::StructMemberSizeAttribute(NodeID nid, + const Source& src, + const Expression* exp) + : Base(nid, src), expr(exp) {} + +StructMemberSizeAttribute::~StructMemberSizeAttribute() = default; + +std::string StructMemberSizeAttribute::Name() const { + return "size"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.h new file mode 100644 index 000000000..9203e36e0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/struct_member_size_attribute.h @@ -0,0 +1,58 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_SIZE_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_SIZE_ATTRIBUTE_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A struct member size attribute +class StructMemberSizeAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param expr the size expression + StructMemberSizeAttribute(NodeID nid, const Source& src, const Expression* expr); + ~StructMemberSizeAttribute() override; + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The size expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_SIZE_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.cc new file mode 100644 index 000000000..47ab8a20f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.cc @@ -0,0 +1,49 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::SubgroupSizeAttribute); + +namespace tint::ast { + +SubgroupSizeAttribute::SubgroupSizeAttribute(NodeID nid, + const Source& src, + const Expression* subgroup_size_) + : Base(nid, src), subgroup_size(subgroup_size_) {} + +SubgroupSizeAttribute::~SubgroupSizeAttribute() = default; + +std::string SubgroupSizeAttribute::Name() const { + return "subgroup_size"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.h new file mode 100644 index 000000000..e841192c1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/subgroup_size_attribute.h @@ -0,0 +1,65 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_SUBGROUP_SIZE_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_SUBGROUP_SIZE_ATTRIBUTE_H_ + +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" + +// Forward declarations +namespace tint::ast { +class Expression; +} // namespace tint::ast + +namespace tint::ast { + +/// A subgroup_size attribute +class SubgroupSizeAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param subgroup_size_ the subgroup_size expression + SubgroupSizeAttribute(NodeID nid, const Source& src, const Expression* subgroup_size_); + + ~SubgroupSizeAttribute() override; + + /// @returns the subgroup_size value + const Expression* Value() const { return subgroup_size; } + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The subgroup_size expression. + const Expression* const subgroup_size; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_SUBGROUP_SIZE_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.cc new file mode 100644 index 000000000..56082ed84 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.cc @@ -0,0 +1,63 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/switch_statement.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::SwitchStatement); + +namespace tint::ast { + +SwitchStatement::SwitchStatement(NodeID nid, + const Source& src, + const Expression* cond, + VectorRef b, + VectorRef stmt_attrs, + VectorRef body_attrs) + : Base(nid, src), + condition(cond), + body(std::move(b)), + attributes(std::move(stmt_attrs)), + body_attributes(std::move(body_attrs)) { + TINT_ASSERT(condition); + for (auto* stmt : body) { + TINT_ASSERT(stmt); + } + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } + for (auto* attr : body_attributes) { + TINT_ASSERT(attr); + } +} + +SwitchStatement::~SwitchStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.h new file mode 100644 index 000000000..a73234bc4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/switch_statement.h @@ -0,0 +1,72 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_SWITCH_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_SWITCH_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/case_statement.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A switch statement +class SwitchStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param condition the switch condition + /// @param body the switch body + /// @param stmt_attributes the switch statement attributes + /// @param body_attributes the switch body attributes + SwitchStatement(NodeID nid, + const Source& src, + const Expression* condition, + VectorRef body, + VectorRef stmt_attributes, + VectorRef body_attributes); + + /// Destructor + ~SwitchStatement() override; + + /// The switch condition or nullptr if none set + const Expression* const condition; + + /// The Switch body + const tint::Vector body; + SwitchStatement(const SwitchStatement&) = delete; + + /// The attribute list for the statement + const tint::Vector attributes; + + /// The attribute list for the body + const tint::Vector body_attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_SWITCH_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.cc new file mode 100644 index 000000000..e927445e8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.cc @@ -0,0 +1,51 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/templated_identifier.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::TemplatedIdentifier); + +namespace tint::ast { + +TemplatedIdentifier::TemplatedIdentifier(NodeID nid, + const Source& src, + const Symbol& sym, + VectorRef args) + : Base(nid, src, sym), arguments(std::move(args)) { + TINT_ASSERT(!arguments.IsEmpty()); // Should have been an Identifier if this fires. + for (auto* arg : arguments) { + TINT_ASSERT(arg); + } +} + +TemplatedIdentifier::~TemplatedIdentifier() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.h new file mode 100644 index 000000000..328907d58 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/templated_identifier.h @@ -0,0 +1,64 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_TEMPLATED_IDENTIFIER_H_ +#define SRC_TINT_LANG_WGSL_AST_TEMPLATED_IDENTIFIER_H_ + +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/utils/containers/vector.h" + +// Forward declarations +namespace tint::ast { +class Attribute; +class Expression; +} // namespace tint::ast + +namespace tint::ast { + +/// A templated identifier expression +class TemplatedIdentifier final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param sym the symbol for the identifier + /// @param args the template arguments + TemplatedIdentifier(NodeID nid, + const Source& src, + const Symbol& sym, + VectorRef args); + + /// Destructor + ~TemplatedIdentifier() override; + + /// The templated arguments + const tint::Vector arguments; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_TEMPLATED_IDENTIFIER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/traverse_expressions.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/traverse_expressions.h new file mode 100644 index 000000000..b697b713e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/traverse_expressions.h @@ -0,0 +1,177 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_TRAVERSE_EXPRESSIONS_H_ +#define SRC_TINT_LANG_WGSL_AST_TRAVERSE_EXPRESSIONS_H_ + +#include + +#include "src/tint/lang/wgsl/ast/binary_expression.h" +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/literal_expression.h" +#include "src/tint/lang/wgsl/ast/member_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/phony_expression.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::ast { + +/// The action to perform after calling the TraverseExpressions() callback +/// function. +enum class TraverseAction { + /// Stop traversal immediately. + Stop, + /// Descend into this expression. + Descend, + /// Do not descend into this expression. + Skip, +}; + +/// The order TraverseExpressions() will traverse expressions +enum class TraverseOrder { + /// Expressions will be traversed from left to right + LeftToRight, + /// Expressions will be traversed from right to left + RightToLeft, +}; + +/// TraverseExpressions performs a depth-first traversal of the expression nodes +/// from `root`, calling `callback` for each of the visited expressions that +/// match the predicate parameter type, in pre-ordering (root first). +/// @param root the root expression node +/// @param callback the callback function. Must be of the signature: +/// `TraverseAction(const T* expr)` or `TraverseAction(const T* expr, size_t depth)` where T +/// is an Expression type. +/// @return true on success, false on error +template +bool TraverseExpressions(const Expression* root, CALLBACK&& callback) { + using EXPR_TYPE = std::remove_pointer_t>; + constexpr static bool kHasDepthArg = traits::SignatureOfT::parameter_count == 2; + + struct Pending { + const Expression* expr; + size_t depth; + }; + + tint::Vector to_visit{{root, 0}}; + + auto push_single = [&](const Expression* expr, size_t depth) { to_visit.Push({expr, depth}); }; + auto push_pair = [&](const Expression* left, const Expression* right, size_t depth) { + if constexpr (ORDER == TraverseOrder::LeftToRight) { + to_visit.Push({right, depth}); + to_visit.Push({left, depth}); + } else { + to_visit.Push({left, depth}); + to_visit.Push({right, depth}); + } + }; + auto push_list = [&](VectorRef exprs, size_t depth) { + if constexpr (ORDER == TraverseOrder::LeftToRight) { + for (auto* expr : tint::Reverse(exprs)) { + to_visit.Push({expr, depth}); + } + } else { + for (auto* expr : exprs) { + to_visit.Push({expr, depth}); + } + } + }; + + while (!to_visit.IsEmpty()) { + auto p = to_visit.Pop(); + const Expression* expr = p.expr; + + if (auto* filtered = expr->template As()) { + TraverseAction result; + if constexpr (kHasDepthArg) { + result = callback(filtered, p.depth); + } else { + result = callback(filtered); + } + + switch (result) { + case TraverseAction::Stop: + return true; + case TraverseAction::Skip: + continue; + case TraverseAction::Descend: + break; + } + } + + bool ok = Switch( + expr, + [&](const IdentifierExpression* ident) { + if (auto* tmpl = ident->identifier->As()) { + push_list(tmpl->arguments, p.depth + 1); + } + return true; + }, + [&](const IndexAccessorExpression* idx) { + push_pair(idx->object, idx->index, p.depth + 1); + return true; + }, + [&](const BinaryExpression* bin_op) { + push_pair(bin_op->lhs, bin_op->rhs, p.depth + 1); + return true; + }, + [&](const CallExpression* call) { + if constexpr (ORDER == TraverseOrder::LeftToRight) { + push_list(call->args, p.depth + 1); + push_single(call->target, p.depth + 1); + } else { + push_single(call->target, p.depth + 1); + push_list(call->args, p.depth + 1); + } + return true; + }, + [&](const MemberAccessorExpression* member) { + push_single(member->object, p.depth + 1); + return true; + }, + [&](const UnaryOpExpression* unary) { + push_single(unary->expr, p.depth + 1); + return true; + }, + [&](const LiteralExpression*) { return true; }, + [&](const PhonyExpression*) { return true; }, // + TINT_ICE_ON_NO_MATCH); + if (!ok) { + return false; + } + } + return true; +} + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_TRAVERSE_EXPRESSIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/type.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/type.h new file mode 100644 index 000000000..e2f9bc505 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/type.h @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_TYPE_H_ +#define SRC_TINT_LANG_WGSL_AST_TYPE_H_ + +// Forward declarations +namespace tint::ast { +class IdentifierExpression; +} // namespace tint::ast + +namespace tint::ast { + +/// Type is a thin wrapper around an IdentifierExpression, to help statically disambiguate known +/// type expressions from other expressions. +struct Type { + /// The type expression + const IdentifierExpression* expr = nullptr; + + /// Indirection operator for accessing the type's expression + /// @return #expr + const IdentifierExpression* operator->() const { return expr; } + + /// Implicit conversion operator to the type's expression + /// @return #expr + operator const IdentifierExpression*() const { return expr; } +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_TYPE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.cc new file mode 100644 index 000000000..2800834ed --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.cc @@ -0,0 +1,45 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/type_decl.h" + +#include "src/tint/lang/wgsl/ast/templated_identifier.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::TypeDecl); + +namespace tint::ast { + +TypeDecl::TypeDecl(NodeID nid, const Source& src, const Identifier* n) : Base(nid, src), name(n) { + TINT_ASSERT(name); + if (name) { + TINT_ASSERT(!name->Is()); + } +} + +TypeDecl::~TypeDecl() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.h new file mode 100644 index 000000000..24feee47d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/type_decl.h @@ -0,0 +1,58 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_TYPE_DECL_H_ +#define SRC_TINT_LANG_WGSL_AST_TYPE_DECL_H_ + +#include "src/tint/lang/wgsl/ast/node.h" + +// Forward declarations +namespace tint::ast { +class Identifier; +} // namespace tint::ast + +namespace tint::ast { + +/// The base class for type declarations. +class TypeDecl : public Castable { + public: + /// Create a new struct statement + /// @param nid the unique node identifier + /// @param src the source of this node for the import statement + /// @param name The name of the type + TypeDecl(NodeID nid, const Source& src, const Identifier* name); + + /// Destructor + ~TypeDecl() override; + + /// The name of the type declaration + const Identifier* const name; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_TYPE_DECL_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.cc new file mode 100644 index 000000000..5130e0311 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.cc @@ -0,0 +1,46 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::UnaryOpExpression); + +namespace tint::ast { + +UnaryOpExpression::UnaryOpExpression(NodeID nid, + const Source& src, + core::UnaryOp o, + const Expression* e) + : Base(nid, src), op(o), expr(e) { + TINT_ASSERT(expr); +} + +UnaryOpExpression::~UnaryOpExpression() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.h new file mode 100644 index 000000000..6bc060fb0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/unary_op_expression.h @@ -0,0 +1,58 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_UNARY_OP_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_AST_UNARY_OP_EXPRESSION_H_ + +#include "src/tint/lang/core/unary_op.h" +#include "src/tint/lang/wgsl/ast/expression.h" + +namespace tint::ast { + +/// A unary op expression +class UnaryOpExpression final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the unary op expression source + /// @param op the op + /// @param expr the expr + UnaryOpExpression(NodeID nid, const Source& source, core::UnaryOp op, const Expression* expr); + + /// Destructor + ~UnaryOpExpression() override; + + /// The op + const core::UnaryOp op; + + /// The expression + const Expression* const expr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_UNARY_OP_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/var.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/var.cc new file mode 100644 index 000000000..7dc053587 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/var.cc @@ -0,0 +1,54 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/var.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Var); + +namespace tint::ast { + +Var::Var(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + const Expression* address_space, + const Expression* access, + const Expression* init, + VectorRef attrs) + : Base(nid, src, n, ty, init, std::move(attrs)), + declared_address_space(address_space), + declared_access(access) {} + +Var::~Var() = default; + +const char* Var::Kind() const { + return "var"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/var.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/var.h new file mode 100644 index 000000000..f4715860c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/var.h @@ -0,0 +1,93 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_VAR_H_ +#define SRC_TINT_LANG_WGSL_AST_VAR_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// A "var" declaration is a name for typed storage. +/// +/// Examples: +/// +/// ``` +/// // Declared outside a function, i.e. at module scope, requires +/// // a address space. +/// var width : i32; // no initializer +/// var height : i32 = 3; // with initializer +/// +/// // A variable declared inside a function doesn't take a address space, +/// // and maps to SPIR-V Function storage. +/// var computed_depth : i32; +/// var area : i32 = compute_area(width, height); +/// ``` +/// +/// @see https://www.w3.org/TR/WGSL/#var-decls +class Var final : public Castable { + public: + /// Create a 'var' variable + /// @param nid the unique node identifier + /// @param source the variable source + /// @param name the variable name + /// @param type the declared variable type + /// @param declared_address_space the declared address space + /// @param declared_access the declared access control + /// @param initializer the initializer expression + /// @param attributes the variable attributes + Var(NodeID nid, + const Source& source, + const Identifier* name, + Type type, + const Expression* declared_address_space, + const Expression* declared_access, + const Expression* initializer, + VectorRef attributes); + + /// Destructor + ~Var() override; + + /// @returns "var" + const char* Kind() const override; + + /// The declared address space + const Expression* const declared_address_space = nullptr; + + /// The declared access control + const Expression* const declared_access = nullptr; +}; + +/// A list of `var` declarations +using VarList = std::vector; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_VAR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/variable.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable.cc new file mode 100644 index 000000000..255794f16 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable.cc @@ -0,0 +1,52 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/variable.h" +#include "src/tint/lang/wgsl/ast/binding_attribute.h" +#include "src/tint/lang/wgsl/ast/group_attribute.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::Variable); + +namespace tint::ast { + +Variable::Variable(NodeID nid, + const Source& src, + const Identifier* n, + Type ty, + const Expression* init, + VectorRef attrs) + : Base(nid, src), name(n), type(ty), initializer(init), attributes(std::move(attrs)) { + TINT_ASSERT(name); + if (name) { + TINT_ASSERT(!name->Is()); + } +} + +Variable::~Variable() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/variable.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable.h new file mode 100644 index 000000000..f454d14ee --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable.h @@ -0,0 +1,108 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_VARIABLE_H_ +#define SRC_TINT_LANG_WGSL_AST_VARIABLE_H_ + +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/binding_attribute.h" +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/lang/wgsl/ast/group_attribute.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/node.h" +#include "src/tint/lang/wgsl/ast/type.h" + +// Forward declarations +namespace tint::ast { +class Identifier; +class LocationAttribute; +} // namespace tint::ast + +namespace tint::ast { + +/// Variable is the base class for Var, Let, Const, Override and Parameter. +/// +/// An instance of this class represents one of five constructs in WGSL: "var" declaration, "let" +/// declaration, "override" declaration, "const" declaration, or formal parameter to a function. +/// +/// @see https://www.w3.org/TR/WGSL/#value-decls +class Variable : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param src the variable source + /// @param name The struct member name + /// @param type the declared variable type + /// @param initializer the initializer expression + /// @param attributes the variable attributes + Variable(NodeID nid, + const Source& src, + const Identifier* name, + Type type, + const Expression* initializer, + VectorRef attributes); + + /// Destructor + ~Variable() override; + + /// @returns true if the variable has both group and binding attributes + bool HasBindingPoint() const { + return HasAttribute(attributes) && + HasAttribute(attributes); + } + + /// @returns true if the variable has an input_attachment_index attribute + bool HasInputAttachmentIndex() const { + return HasAttribute(attributes); + } + + /// @returns the kind of the variable, which can be used in diagnostics + /// e.g. "var", "let", "const", etc + virtual const char* Kind() const = 0; + + /// The variable name + const Identifier* const name; + + /// The declared variable type. This is null if the type is inferred, e.g.: + /// let f = 1.0; + /// var i = 1; + const Type type; + + /// The initializer expression or nullptr if none set + const Expression* const initializer; + + /// The attributes attached to this variable + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_VARIABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.cc new file mode 100644 index 000000000..da6b4404c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::VariableDeclStatement); + +namespace tint::ast { + +VariableDeclStatement::VariableDeclStatement(NodeID nid, const Source& src, const Variable* var) + : Base(nid, src), variable(var) { + TINT_ASSERT(variable); +} + +VariableDeclStatement::~VariableDeclStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.h new file mode 100644 index 000000000..3012b02ec --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/variable_decl_statement.h @@ -0,0 +1,54 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_VARIABLE_DECL_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_VARIABLE_DECL_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/statement.h" +#include "src/tint/lang/wgsl/ast/variable.h" + +namespace tint::ast { + +/// A variable declaration statement +class VariableDeclStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the variable statement source + /// @param variable the variable + VariableDeclStatement(NodeID nid, const Source& source, const Variable* variable); + + /// Destructor + ~VariableDeclStatement() override; + + /// The variable + const Variable* const variable; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_VARIABLE_DECL_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.cc new file mode 100644 index 000000000..2ac67f9a1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.cc @@ -0,0 +1,54 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/while_statement.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::WhileStatement); + +namespace tint::ast { + +WhileStatement::WhileStatement(NodeID nid, + const Source& src, + const Expression* cond, + const BlockStatement* b, + VectorRef attrs) + : Base(nid, src), condition(cond), body(b), attributes(std::move(attrs)) { + TINT_ASSERT(cond); + TINT_ASSERT(body); + + for (auto* attr : attributes) { + TINT_ASSERT(attr); + } +} + +WhileStatement::~WhileStatement() = default; + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.h new file mode 100644 index 000000000..308a22f28 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/while_statement.h @@ -0,0 +1,67 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_WHILE_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_AST_WHILE_STATEMENT_H_ + +#include "src/tint/lang/wgsl/ast/block_statement.h" + +namespace tint::ast { + +class Expression; + +/// A while loop statement +class WhileStatement final : public Castable { + public: + /// Constructor + /// @param nid the unique node identifier + /// @param source the for loop statement source + /// @param condition the optional loop condition expression + /// @param body the loop body + /// @param attributes the while statement attributes + WhileStatement(NodeID nid, + const Source& source, + const Expression* condition, + const BlockStatement* body, + VectorRef attributes); + + /// Destructor + ~WhileStatement() override; + + /// The condition expression + const Expression* const condition; + + /// The loop body block + const BlockStatement* const body; + + /// The attribute list + const tint::Vector attributes; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_WHILE_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.cc b/3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.cc new file mode 100644 index 000000000..f30af3f3f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.cc @@ -0,0 +1,51 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" + +#include + +#include "src/tint/lang/wgsl/ast/builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ast::WorkgroupAttribute); + +namespace tint::ast { + +WorkgroupAttribute::WorkgroupAttribute(NodeID nid, + const Source& src, + const Expression* x_, + const Expression* y_, + const Expression* z_) + : Base(nid, src), x(x_), y(y_), z(z_) {} + +WorkgroupAttribute::~WorkgroupAttribute() = default; + +std::string WorkgroupAttribute::Name() const { + return "workgroup_size"; +} + +} // namespace tint::ast diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.h b/3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.h new file mode 100644 index 000000000..535e8df4a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ast/workgroup_attribute.h @@ -0,0 +1,76 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_AST_WORKGROUP_ATTRIBUTE_H_ +#define SRC_TINT_LANG_WGSL_AST_WORKGROUP_ATTRIBUTE_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/attribute.h" + +// Forward declarations +namespace tint::ast { +class Expression; +} // namespace tint::ast + +namespace tint::ast { + +/// A workgroup attribute +class WorkgroupAttribute final : public Castable { + public: + /// constructor + /// @param nid the unique node identifier + /// @param src the source of this node + /// @param x the workgroup x dimension expression + /// @param y the optional workgroup y dimension expression + /// @param z the optional workgroup z dimension expression + WorkgroupAttribute(NodeID nid, + const Source& src, + const Expression* x, + const Expression* y = nullptr, + const Expression* z = nullptr); + + ~WorkgroupAttribute() override; + + /// @returns the workgroup dimensions + std::array Values() const { return {x, y, z}; } + + /// @returns the WGSL name for the attribute + std::string Name() const override; + + /// The workgroup x dimension. + const Expression* const x; + /// The optional workgroup y dimension. May be null. + const Expression* const y = nullptr; + /// The optional workgroup z dimension. May be null. + const Expression* const z = nullptr; +}; + +} // namespace tint::ast + +#endif // SRC_TINT_LANG_WGSL_AST_WORKGROUP_ATTRIBUTE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/enums.cc b/3rdparty/dawn/src/tint/lang/wgsl/enums.cc new file mode 100644 index 000000000..9ce47b9e0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/enums.cc @@ -0,0 +1,1255 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/wgsl/enums.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include "src/tint/lang/wgsl/enums.h" + +#include + +#include "src/tint/utils/rtti/traits.h" + +namespace tint::wgsl { + +/// ParseExtension parses a Extension from a string. +/// @param str the string to parse +/// @returns the parsed enum, or Extension::kUndefined if the string could not be parsed. +Extension ParseExtension(std::string_view str) { + if (str == "chromium_disable_uniformity_analysis") { + return Extension::kChromiumDisableUniformityAnalysis; + } + if (str == "chromium_experimental_barycentric_coord") { + return Extension::kChromiumExperimentalBarycentricCoord; + } + if (str == "chromium_experimental_framebuffer_fetch") { + return Extension::kChromiumExperimentalFramebufferFetch; + } + if (str == "chromium_experimental_pixel_local") { + return Extension::kChromiumExperimentalPixelLocal; + } + if (str == "chromium_experimental_resource_table") { + return Extension::kChromiumExperimentalResourceTable; + } + if (str == "chromium_experimental_subgroup_matrix") { + return Extension::kChromiumExperimentalSubgroupMatrix; + } + if (str == "chromium_experimental_subgroup_size_control") { + return Extension::kChromiumExperimentalSubgroupSizeControl; + } + if (str == "chromium_internal_graphite") { + return Extension::kChromiumInternalGraphite; + } + if (str == "chromium_internal_input_attachments") { + return Extension::kChromiumInternalInputAttachments; + } + if (str == "clip_distances") { + return Extension::kClipDistances; + } + if (str == "dual_source_blending") { + return Extension::kDualSourceBlending; + } + if (str == "f16") { + return Extension::kF16; + } + if (str == "primitive_index") { + return Extension::kPrimitiveIndex; + } + if (str == "subgroups") { + return Extension::kSubgroups; + } + return Extension::kUndefined; +} +std::string_view ToString(Extension value) { + switch (value) { + case Extension::kUndefined: + return "undefined"; + case Extension::kChromiumDisableUniformityAnalysis: + return "chromium_disable_uniformity_analysis"; + case Extension::kChromiumExperimentalBarycentricCoord: + return "chromium_experimental_barycentric_coord"; + case Extension::kChromiumExperimentalFramebufferFetch: + return "chromium_experimental_framebuffer_fetch"; + case Extension::kChromiumExperimentalPixelLocal: + return "chromium_experimental_pixel_local"; + case Extension::kChromiumExperimentalResourceTable: + return "chromium_experimental_resource_table"; + case Extension::kChromiumExperimentalSubgroupMatrix: + return "chromium_experimental_subgroup_matrix"; + case Extension::kChromiumExperimentalSubgroupSizeControl: + return "chromium_experimental_subgroup_size_control"; + case Extension::kChromiumInternalGraphite: + return "chromium_internal_graphite"; + case Extension::kChromiumInternalInputAttachments: + return "chromium_internal_input_attachments"; + case Extension::kClipDistances: + return "clip_distances"; + case Extension::kDualSourceBlending: + return "dual_source_blending"; + case Extension::kF16: + return "f16"; + case Extension::kPrimitiveIndex: + return "primitive_index"; + case Extension::kSubgroups: + return "subgroups"; + } + return ""; +} + +/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string. +/// @param str the string to parse +/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed. +CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str) { + if (str == "derivative_uniformity") { + return CoreDiagnosticRule::kDerivativeUniformity; + } + if (str == "subgroup_uniformity") { + return CoreDiagnosticRule::kSubgroupUniformity; + } + return CoreDiagnosticRule::kUndefined; +} +std::string_view ToString(CoreDiagnosticRule value) { + switch (value) { + case CoreDiagnosticRule::kUndefined: + return "undefined"; + case CoreDiagnosticRule::kDerivativeUniformity: + return "derivative_uniformity"; + case CoreDiagnosticRule::kSubgroupUniformity: + return "subgroup_uniformity"; + } + return ""; +} + +/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string. +/// @param str the string to parse +/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be parsed. +ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str) { + if (str == "subgroup_matrix_uniformity") { + return ChromiumDiagnosticRule::kSubgroupMatrixUniformity; + } + if (str == "unreachable_code") { + return ChromiumDiagnosticRule::kUnreachableCode; + } + return ChromiumDiagnosticRule::kUndefined; +} +std::string_view ToString(ChromiumDiagnosticRule value) { + switch (value) { + case ChromiumDiagnosticRule::kUndefined: + return "undefined"; + case ChromiumDiagnosticRule::kSubgroupMatrixUniformity: + return "subgroup_matrix_uniformity"; + case ChromiumDiagnosticRule::kUnreachableCode: + return "unreachable_code"; + } + return ""; +} + +/// ParseLanguageFeature parses a LanguageFeature from a string. +/// @param str the string to parse +/// @returns the parsed enum, or LanguageFeature::kUndefined if the string could not be parsed. +LanguageFeature ParseLanguageFeature(std::string_view str) { + if (str == "buffer_view") { + return LanguageFeature::kBufferView; + } + if (str == "chromium_print") { + return LanguageFeature::kChromiumPrint; + } + if (str == "chromium_testing_experimental") { + return LanguageFeature::kChromiumTestingExperimental; + } + if (str == "chromium_testing_shipped") { + return LanguageFeature::kChromiumTestingShipped; + } + if (str == "chromium_testing_shipped_with_killswitch") { + return LanguageFeature::kChromiumTestingShippedWithKillswitch; + } + if (str == "chromium_testing_unimplemented") { + return LanguageFeature::kChromiumTestingUnimplemented; + } + if (str == "chromium_testing_unsafe_experimental") { + return LanguageFeature::kChromiumTestingUnsafeExperimental; + } + if (str == "fragment_depth") { + return LanguageFeature::kFragmentDepth; + } + if (str == "immediate_address_space") { + return LanguageFeature::kImmediateAddressSpace; + } + if (str == "packed_4x8_integer_dot_product") { + return LanguageFeature::kPacked4X8IntegerDotProduct; + } + if (str == "pointer_composite_access") { + return LanguageFeature::kPointerCompositeAccess; + } + if (str == "readonly_and_readwrite_storage_textures") { + return LanguageFeature::kReadonlyAndReadwriteStorageTextures; + } + if (str == "sized_binding_array") { + return LanguageFeature::kSizedBindingArray; + } + if (str == "subgroup_id") { + return LanguageFeature::kSubgroupId; + } + if (str == "subgroup_uniformity") { + return LanguageFeature::kSubgroupUniformity; + } + if (str == "texel_buffers") { + return LanguageFeature::kTexelBuffers; + } + if (str == "texture_and_sampler_let") { + return LanguageFeature::kTextureAndSamplerLet; + } + if (str == "uniform_buffer_standard_layout") { + return LanguageFeature::kUniformBufferStandardLayout; + } + if (str == "unrestricted_pointer_parameters") { + return LanguageFeature::kUnrestrictedPointerParameters; + } + return LanguageFeature::kUndefined; +} +std::string_view ToString(LanguageFeature value) { + switch (value) { + case LanguageFeature::kUndefined: + return "undefined"; + case LanguageFeature::kBufferView: + return "buffer_view"; + case LanguageFeature::kChromiumPrint: + return "chromium_print"; + case LanguageFeature::kChromiumTestingExperimental: + return "chromium_testing_experimental"; + case LanguageFeature::kChromiumTestingShipped: + return "chromium_testing_shipped"; + case LanguageFeature::kChromiumTestingShippedWithKillswitch: + return "chromium_testing_shipped_with_killswitch"; + case LanguageFeature::kChromiumTestingUnimplemented: + return "chromium_testing_unimplemented"; + case LanguageFeature::kChromiumTestingUnsafeExperimental: + return "chromium_testing_unsafe_experimental"; + case LanguageFeature::kFragmentDepth: + return "fragment_depth"; + case LanguageFeature::kImmediateAddressSpace: + return "immediate_address_space"; + case LanguageFeature::kPacked4X8IntegerDotProduct: + return "packed_4x8_integer_dot_product"; + case LanguageFeature::kPointerCompositeAccess: + return "pointer_composite_access"; + case LanguageFeature::kReadonlyAndReadwriteStorageTextures: + return "readonly_and_readwrite_storage_textures"; + case LanguageFeature::kSizedBindingArray: + return "sized_binding_array"; + case LanguageFeature::kSubgroupId: + return "subgroup_id"; + case LanguageFeature::kSubgroupUniformity: + return "subgroup_uniformity"; + case LanguageFeature::kTexelBuffers: + return "texel_buffers"; + case LanguageFeature::kTextureAndSamplerLet: + return "texture_and_sampler_let"; + case LanguageFeature::kUniformBufferStandardLayout: + return "uniform_buffer_standard_layout"; + case LanguageFeature::kUnrestrictedPointerParameters: + return "unrestricted_pointer_parameters"; + } + return ""; +} + +diag::Severity ToSeverity(DiagnosticSeverity sc) { + switch (sc) { + case DiagnosticSeverity::kError: + return diag::Severity::Error; + case DiagnosticSeverity::kWarning: + return diag::Severity::Warning; + case DiagnosticSeverity::kInfo: + return diag::Severity::Note; + default: + return diag::Severity::Error; + } +} + +/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string. +/// @param str the string to parse +/// @returns the parsed enum, or DiagnosticSeverity::kUndefined if the string could not be parsed. +DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str) { + if (str == "error") { + return DiagnosticSeverity::kError; + } + if (str == "info") { + return DiagnosticSeverity::kInfo; + } + if (str == "off") { + return DiagnosticSeverity::kOff; + } + if (str == "warning") { + return DiagnosticSeverity::kWarning; + } + return DiagnosticSeverity::kUndefined; +} +std::string_view ToString(DiagnosticSeverity value) { + switch (value) { + case DiagnosticSeverity::kUndefined: + return "undefined"; + case DiagnosticSeverity::kError: + return "error"; + case DiagnosticSeverity::kInfo: + return "info"; + case DiagnosticSeverity::kOff: + return "off"; + case DiagnosticSeverity::kWarning: + return "warning"; + } + return ""; +} + + +BuiltinFn ParseBuiltinFn(std::string_view name) { + if (name == "abs") { + return BuiltinFn::kAbs; + } + if (name == "acos") { + return BuiltinFn::kAcos; + } + if (name == "acosh") { + return BuiltinFn::kAcosh; + } + if (name == "all") { + return BuiltinFn::kAll; + } + if (name == "any") { + return BuiltinFn::kAny; + } + if (name == "arrayLength") { + return BuiltinFn::kArrayLength; + } + if (name == "asin") { + return BuiltinFn::kAsin; + } + if (name == "asinh") { + return BuiltinFn::kAsinh; + } + if (name == "atan") { + return BuiltinFn::kAtan; + } + if (name == "atan2") { + return BuiltinFn::kAtan2; + } + if (name == "atanh") { + return BuiltinFn::kAtanh; + } + if (name == "bitcast") { + return BuiltinFn::kBitcast; + } + if (name == "ceil") { + return BuiltinFn::kCeil; + } + if (name == "clamp") { + return BuiltinFn::kClamp; + } + if (name == "cos") { + return BuiltinFn::kCos; + } + if (name == "cosh") { + return BuiltinFn::kCosh; + } + if (name == "countLeadingZeros") { + return BuiltinFn::kCountLeadingZeros; + } + if (name == "countOneBits") { + return BuiltinFn::kCountOneBits; + } + if (name == "countTrailingZeros") { + return BuiltinFn::kCountTrailingZeros; + } + if (name == "cross") { + return BuiltinFn::kCross; + } + if (name == "degrees") { + return BuiltinFn::kDegrees; + } + if (name == "determinant") { + return BuiltinFn::kDeterminant; + } + if (name == "distance") { + return BuiltinFn::kDistance; + } + if (name == "dot") { + return BuiltinFn::kDot; + } + if (name == "dot4I8Packed") { + return BuiltinFn::kDot4I8Packed; + } + if (name == "dot4U8Packed") { + return BuiltinFn::kDot4U8Packed; + } + if (name == "dpdx") { + return BuiltinFn::kDpdx; + } + if (name == "dpdxCoarse") { + return BuiltinFn::kDpdxCoarse; + } + if (name == "dpdxFine") { + return BuiltinFn::kDpdxFine; + } + if (name == "dpdy") { + return BuiltinFn::kDpdy; + } + if (name == "dpdyCoarse") { + return BuiltinFn::kDpdyCoarse; + } + if (name == "dpdyFine") { + return BuiltinFn::kDpdyFine; + } + if (name == "exp") { + return BuiltinFn::kExp; + } + if (name == "exp2") { + return BuiltinFn::kExp2; + } + if (name == "extractBits") { + return BuiltinFn::kExtractBits; + } + if (name == "faceForward") { + return BuiltinFn::kFaceForward; + } + if (name == "firstLeadingBit") { + return BuiltinFn::kFirstLeadingBit; + } + if (name == "firstTrailingBit") { + return BuiltinFn::kFirstTrailingBit; + } + if (name == "floor") { + return BuiltinFn::kFloor; + } + if (name == "fma") { + return BuiltinFn::kFma; + } + if (name == "fract") { + return BuiltinFn::kFract; + } + if (name == "frexp") { + return BuiltinFn::kFrexp; + } + if (name == "fwidth") { + return BuiltinFn::kFwidth; + } + if (name == "fwidthCoarse") { + return BuiltinFn::kFwidthCoarse; + } + if (name == "fwidthFine") { + return BuiltinFn::kFwidthFine; + } + if (name == "insertBits") { + return BuiltinFn::kInsertBits; + } + if (name == "inverseSqrt") { + return BuiltinFn::kInverseSqrt; + } + if (name == "ldexp") { + return BuiltinFn::kLdexp; + } + if (name == "length") { + return BuiltinFn::kLength; + } + if (name == "log") { + return BuiltinFn::kLog; + } + if (name == "log2") { + return BuiltinFn::kLog2; + } + if (name == "max") { + return BuiltinFn::kMax; + } + if (name == "min") { + return BuiltinFn::kMin; + } + if (name == "mix") { + return BuiltinFn::kMix; + } + if (name == "modf") { + return BuiltinFn::kModf; + } + if (name == "normalize") { + return BuiltinFn::kNormalize; + } + if (name == "pack2x16float") { + return BuiltinFn::kPack2X16Float; + } + if (name == "pack2x16snorm") { + return BuiltinFn::kPack2X16Snorm; + } + if (name == "pack2x16unorm") { + return BuiltinFn::kPack2X16Unorm; + } + if (name == "pack4x8snorm") { + return BuiltinFn::kPack4X8Snorm; + } + if (name == "pack4x8unorm") { + return BuiltinFn::kPack4X8Unorm; + } + if (name == "pack4xI8") { + return BuiltinFn::kPack4XI8; + } + if (name == "pack4xU8") { + return BuiltinFn::kPack4XU8; + } + if (name == "pack4xI8Clamp") { + return BuiltinFn::kPack4XI8Clamp; + } + if (name == "pack4xU8Clamp") { + return BuiltinFn::kPack4XU8Clamp; + } + if (name == "pow") { + return BuiltinFn::kPow; + } + if (name == "quantizeToF16") { + return BuiltinFn::kQuantizeToF16; + } + if (name == "radians") { + return BuiltinFn::kRadians; + } + if (name == "reflect") { + return BuiltinFn::kReflect; + } + if (name == "refract") { + return BuiltinFn::kRefract; + } + if (name == "reverseBits") { + return BuiltinFn::kReverseBits; + } + if (name == "round") { + return BuiltinFn::kRound; + } + if (name == "saturate") { + return BuiltinFn::kSaturate; + } + if (name == "select") { + return BuiltinFn::kSelect; + } + if (name == "sign") { + return BuiltinFn::kSign; + } + if (name == "sin") { + return BuiltinFn::kSin; + } + if (name == "sinh") { + return BuiltinFn::kSinh; + } + if (name == "smoothstep") { + return BuiltinFn::kSmoothstep; + } + if (name == "sqrt") { + return BuiltinFn::kSqrt; + } + if (name == "step") { + return BuiltinFn::kStep; + } + if (name == "storageBarrier") { + return BuiltinFn::kStorageBarrier; + } + if (name == "tan") { + return BuiltinFn::kTan; + } + if (name == "tanh") { + return BuiltinFn::kTanh; + } + if (name == "transpose") { + return BuiltinFn::kTranspose; + } + if (name == "trunc") { + return BuiltinFn::kTrunc; + } + if (name == "unpack2x16float") { + return BuiltinFn::kUnpack2X16Float; + } + if (name == "unpack2x16snorm") { + return BuiltinFn::kUnpack2X16Snorm; + } + if (name == "unpack2x16unorm") { + return BuiltinFn::kUnpack2X16Unorm; + } + if (name == "unpack4x8snorm") { + return BuiltinFn::kUnpack4X8Snorm; + } + if (name == "unpack4x8unorm") { + return BuiltinFn::kUnpack4X8Unorm; + } + if (name == "unpack4xI8") { + return BuiltinFn::kUnpack4XI8; + } + if (name == "unpack4xU8") { + return BuiltinFn::kUnpack4XU8; + } + if (name == "workgroupBarrier") { + return BuiltinFn::kWorkgroupBarrier; + } + if (name == "workgroupUniformLoad") { + return BuiltinFn::kWorkgroupUniformLoad; + } + if (name == "textureBarrier") { + return BuiltinFn::kTextureBarrier; + } + if (name == "textureDimensions") { + return BuiltinFn::kTextureDimensions; + } + if (name == "textureGather") { + return BuiltinFn::kTextureGather; + } + if (name == "textureGatherCompare") { + return BuiltinFn::kTextureGatherCompare; + } + if (name == "textureNumLayers") { + return BuiltinFn::kTextureNumLayers; + } + if (name == "textureNumLevels") { + return BuiltinFn::kTextureNumLevels; + } + if (name == "textureNumSamples") { + return BuiltinFn::kTextureNumSamples; + } + if (name == "textureSample") { + return BuiltinFn::kTextureSample; + } + if (name == "textureSampleBias") { + return BuiltinFn::kTextureSampleBias; + } + if (name == "textureSampleCompare") { + return BuiltinFn::kTextureSampleCompare; + } + if (name == "textureSampleCompareLevel") { + return BuiltinFn::kTextureSampleCompareLevel; + } + if (name == "textureSampleGrad") { + return BuiltinFn::kTextureSampleGrad; + } + if (name == "textureSampleLevel") { + return BuiltinFn::kTextureSampleLevel; + } + if (name == "textureSampleBaseClampToEdge") { + return BuiltinFn::kTextureSampleBaseClampToEdge; + } + if (name == "textureStore") { + return BuiltinFn::kTextureStore; + } + if (name == "textureLoad") { + return BuiltinFn::kTextureLoad; + } + if (name == "inputAttachmentLoad") { + return BuiltinFn::kInputAttachmentLoad; + } + if (name == "atomicLoad") { + return BuiltinFn::kAtomicLoad; + } + if (name == "atomicStore") { + return BuiltinFn::kAtomicStore; + } + if (name == "atomicAdd") { + return BuiltinFn::kAtomicAdd; + } + if (name == "atomicSub") { + return BuiltinFn::kAtomicSub; + } + if (name == "atomicMax") { + return BuiltinFn::kAtomicMax; + } + if (name == "atomicMin") { + return BuiltinFn::kAtomicMin; + } + if (name == "atomicAnd") { + return BuiltinFn::kAtomicAnd; + } + if (name == "atomicOr") { + return BuiltinFn::kAtomicOr; + } + if (name == "atomicXor") { + return BuiltinFn::kAtomicXor; + } + if (name == "atomicExchange") { + return BuiltinFn::kAtomicExchange; + } + if (name == "atomicCompareExchangeWeak") { + return BuiltinFn::kAtomicCompareExchangeWeak; + } + if (name == "subgroupBallot") { + return BuiltinFn::kSubgroupBallot; + } + if (name == "subgroupElect") { + return BuiltinFn::kSubgroupElect; + } + if (name == "subgroupBroadcast") { + return BuiltinFn::kSubgroupBroadcast; + } + if (name == "subgroupBroadcastFirst") { + return BuiltinFn::kSubgroupBroadcastFirst; + } + if (name == "subgroupShuffle") { + return BuiltinFn::kSubgroupShuffle; + } + if (name == "subgroupShuffleXor") { + return BuiltinFn::kSubgroupShuffleXor; + } + if (name == "subgroupShuffleUp") { + return BuiltinFn::kSubgroupShuffleUp; + } + if (name == "subgroupShuffleDown") { + return BuiltinFn::kSubgroupShuffleDown; + } + if (name == "subgroupAdd") { + return BuiltinFn::kSubgroupAdd; + } + if (name == "subgroupInclusiveAdd") { + return BuiltinFn::kSubgroupInclusiveAdd; + } + if (name == "subgroupExclusiveAdd") { + return BuiltinFn::kSubgroupExclusiveAdd; + } + if (name == "subgroupMul") { + return BuiltinFn::kSubgroupMul; + } + if (name == "subgroupInclusiveMul") { + return BuiltinFn::kSubgroupInclusiveMul; + } + if (name == "subgroupExclusiveMul") { + return BuiltinFn::kSubgroupExclusiveMul; + } + if (name == "subgroupAnd") { + return BuiltinFn::kSubgroupAnd; + } + if (name == "subgroupOr") { + return BuiltinFn::kSubgroupOr; + } + if (name == "subgroupXor") { + return BuiltinFn::kSubgroupXor; + } + if (name == "subgroupMin") { + return BuiltinFn::kSubgroupMin; + } + if (name == "subgroupMax") { + return BuiltinFn::kSubgroupMax; + } + if (name == "subgroupAll") { + return BuiltinFn::kSubgroupAll; + } + if (name == "subgroupAny") { + return BuiltinFn::kSubgroupAny; + } + if (name == "quadBroadcast") { + return BuiltinFn::kQuadBroadcast; + } + if (name == "quadSwapX") { + return BuiltinFn::kQuadSwapX; + } + if (name == "quadSwapY") { + return BuiltinFn::kQuadSwapY; + } + if (name == "quadSwapDiagonal") { + return BuiltinFn::kQuadSwapDiagonal; + } + if (name == "subgroupMatrixLoad") { + return BuiltinFn::kSubgroupMatrixLoad; + } + if (name == "subgroupMatrixStore") { + return BuiltinFn::kSubgroupMatrixStore; + } + if (name == "subgroupMatrixMultiply") { + return BuiltinFn::kSubgroupMatrixMultiply; + } + if (name == "subgroupMatrixMultiplyAccumulate") { + return BuiltinFn::kSubgroupMatrixMultiplyAccumulate; + } + if (name == "subgroupMatrixScalarAdd") { + return BuiltinFn::kSubgroupMatrixScalarAdd; + } + if (name == "subgroupMatrixScalarSubtract") { + return BuiltinFn::kSubgroupMatrixScalarSubtract; + } + if (name == "subgroupMatrixScalarMultiply") { + return BuiltinFn::kSubgroupMatrixScalarMultiply; + } + if (name == "bufferView") { + return BuiltinFn::kBufferView; + } + if (name == "bufferLength") { + return BuiltinFn::kBufferLength; + } + if (name == "print") { + return BuiltinFn::kPrint; + } + if (name == "__tint_materialize") { + return BuiltinFn::kTintMaterialize; + } + if (name == "hasResource") { + return BuiltinFn::kHasResource; + } + if (name == "getResource") { + return BuiltinFn::kGetResource; + } + return BuiltinFn::kNone; +} + +const char* str(BuiltinFn i) { + switch (i) { + case BuiltinFn::kNone: + return ""; + case BuiltinFn::kAbs: + return "abs"; + case BuiltinFn::kAcos: + return "acos"; + case BuiltinFn::kAcosh: + return "acosh"; + case BuiltinFn::kAll: + return "all"; + case BuiltinFn::kAny: + return "any"; + case BuiltinFn::kArrayLength: + return "arrayLength"; + case BuiltinFn::kAsin: + return "asin"; + case BuiltinFn::kAsinh: + return "asinh"; + case BuiltinFn::kAtan: + return "atan"; + case BuiltinFn::kAtan2: + return "atan2"; + case BuiltinFn::kAtanh: + return "atanh"; + case BuiltinFn::kBitcast: + return "bitcast"; + case BuiltinFn::kCeil: + return "ceil"; + case BuiltinFn::kClamp: + return "clamp"; + case BuiltinFn::kCos: + return "cos"; + case BuiltinFn::kCosh: + return "cosh"; + case BuiltinFn::kCountLeadingZeros: + return "countLeadingZeros"; + case BuiltinFn::kCountOneBits: + return "countOneBits"; + case BuiltinFn::kCountTrailingZeros: + return "countTrailingZeros"; + case BuiltinFn::kCross: + return "cross"; + case BuiltinFn::kDegrees: + return "degrees"; + case BuiltinFn::kDeterminant: + return "determinant"; + case BuiltinFn::kDistance: + return "distance"; + case BuiltinFn::kDot: + return "dot"; + case BuiltinFn::kDot4I8Packed: + return "dot4I8Packed"; + case BuiltinFn::kDot4U8Packed: + return "dot4U8Packed"; + case BuiltinFn::kDpdx: + return "dpdx"; + case BuiltinFn::kDpdxCoarse: + return "dpdxCoarse"; + case BuiltinFn::kDpdxFine: + return "dpdxFine"; + case BuiltinFn::kDpdy: + return "dpdy"; + case BuiltinFn::kDpdyCoarse: + return "dpdyCoarse"; + case BuiltinFn::kDpdyFine: + return "dpdyFine"; + case BuiltinFn::kExp: + return "exp"; + case BuiltinFn::kExp2: + return "exp2"; + case BuiltinFn::kExtractBits: + return "extractBits"; + case BuiltinFn::kFaceForward: + return "faceForward"; + case BuiltinFn::kFirstLeadingBit: + return "firstLeadingBit"; + case BuiltinFn::kFirstTrailingBit: + return "firstTrailingBit"; + case BuiltinFn::kFloor: + return "floor"; + case BuiltinFn::kFma: + return "fma"; + case BuiltinFn::kFract: + return "fract"; + case BuiltinFn::kFrexp: + return "frexp"; + case BuiltinFn::kFwidth: + return "fwidth"; + case BuiltinFn::kFwidthCoarse: + return "fwidthCoarse"; + case BuiltinFn::kFwidthFine: + return "fwidthFine"; + case BuiltinFn::kInsertBits: + return "insertBits"; + case BuiltinFn::kInverseSqrt: + return "inverseSqrt"; + case BuiltinFn::kLdexp: + return "ldexp"; + case BuiltinFn::kLength: + return "length"; + case BuiltinFn::kLog: + return "log"; + case BuiltinFn::kLog2: + return "log2"; + case BuiltinFn::kMax: + return "max"; + case BuiltinFn::kMin: + return "min"; + case BuiltinFn::kMix: + return "mix"; + case BuiltinFn::kModf: + return "modf"; + case BuiltinFn::kNormalize: + return "normalize"; + case BuiltinFn::kPack2X16Float: + return "pack2x16float"; + case BuiltinFn::kPack2X16Snorm: + return "pack2x16snorm"; + case BuiltinFn::kPack2X16Unorm: + return "pack2x16unorm"; + case BuiltinFn::kPack4X8Snorm: + return "pack4x8snorm"; + case BuiltinFn::kPack4X8Unorm: + return "pack4x8unorm"; + case BuiltinFn::kPack4XI8: + return "pack4xI8"; + case BuiltinFn::kPack4XU8: + return "pack4xU8"; + case BuiltinFn::kPack4XI8Clamp: + return "pack4xI8Clamp"; + case BuiltinFn::kPack4XU8Clamp: + return "pack4xU8Clamp"; + case BuiltinFn::kPow: + return "pow"; + case BuiltinFn::kQuantizeToF16: + return "quantizeToF16"; + case BuiltinFn::kRadians: + return "radians"; + case BuiltinFn::kReflect: + return "reflect"; + case BuiltinFn::kRefract: + return "refract"; + case BuiltinFn::kReverseBits: + return "reverseBits"; + case BuiltinFn::kRound: + return "round"; + case BuiltinFn::kSaturate: + return "saturate"; + case BuiltinFn::kSelect: + return "select"; + case BuiltinFn::kSign: + return "sign"; + case BuiltinFn::kSin: + return "sin"; + case BuiltinFn::kSinh: + return "sinh"; + case BuiltinFn::kSmoothstep: + return "smoothstep"; + case BuiltinFn::kSqrt: + return "sqrt"; + case BuiltinFn::kStep: + return "step"; + case BuiltinFn::kStorageBarrier: + return "storageBarrier"; + case BuiltinFn::kTan: + return "tan"; + case BuiltinFn::kTanh: + return "tanh"; + case BuiltinFn::kTranspose: + return "transpose"; + case BuiltinFn::kTrunc: + return "trunc"; + case BuiltinFn::kUnpack2X16Float: + return "unpack2x16float"; + case BuiltinFn::kUnpack2X16Snorm: + return "unpack2x16snorm"; + case BuiltinFn::kUnpack2X16Unorm: + return "unpack2x16unorm"; + case BuiltinFn::kUnpack4X8Snorm: + return "unpack4x8snorm"; + case BuiltinFn::kUnpack4X8Unorm: + return "unpack4x8unorm"; + case BuiltinFn::kUnpack4XI8: + return "unpack4xI8"; + case BuiltinFn::kUnpack4XU8: + return "unpack4xU8"; + case BuiltinFn::kWorkgroupBarrier: + return "workgroupBarrier"; + case BuiltinFn::kWorkgroupUniformLoad: + return "workgroupUniformLoad"; + case BuiltinFn::kTextureBarrier: + return "textureBarrier"; + case BuiltinFn::kTextureDimensions: + return "textureDimensions"; + case BuiltinFn::kTextureGather: + return "textureGather"; + case BuiltinFn::kTextureGatherCompare: + return "textureGatherCompare"; + case BuiltinFn::kTextureNumLayers: + return "textureNumLayers"; + case BuiltinFn::kTextureNumLevels: + return "textureNumLevels"; + case BuiltinFn::kTextureNumSamples: + return "textureNumSamples"; + case BuiltinFn::kTextureSample: + return "textureSample"; + case BuiltinFn::kTextureSampleBias: + return "textureSampleBias"; + case BuiltinFn::kTextureSampleCompare: + return "textureSampleCompare"; + case BuiltinFn::kTextureSampleCompareLevel: + return "textureSampleCompareLevel"; + case BuiltinFn::kTextureSampleGrad: + return "textureSampleGrad"; + case BuiltinFn::kTextureSampleLevel: + return "textureSampleLevel"; + case BuiltinFn::kTextureSampleBaseClampToEdge: + return "textureSampleBaseClampToEdge"; + case BuiltinFn::kTextureStore: + return "textureStore"; + case BuiltinFn::kTextureLoad: + return "textureLoad"; + case BuiltinFn::kInputAttachmentLoad: + return "inputAttachmentLoad"; + case BuiltinFn::kAtomicLoad: + return "atomicLoad"; + case BuiltinFn::kAtomicStore: + return "atomicStore"; + case BuiltinFn::kAtomicAdd: + return "atomicAdd"; + case BuiltinFn::kAtomicSub: + return "atomicSub"; + case BuiltinFn::kAtomicMax: + return "atomicMax"; + case BuiltinFn::kAtomicMin: + return "atomicMin"; + case BuiltinFn::kAtomicAnd: + return "atomicAnd"; + case BuiltinFn::kAtomicOr: + return "atomicOr"; + case BuiltinFn::kAtomicXor: + return "atomicXor"; + case BuiltinFn::kAtomicExchange: + return "atomicExchange"; + case BuiltinFn::kAtomicCompareExchangeWeak: + return "atomicCompareExchangeWeak"; + case BuiltinFn::kSubgroupBallot: + return "subgroupBallot"; + case BuiltinFn::kSubgroupElect: + return "subgroupElect"; + case BuiltinFn::kSubgroupBroadcast: + return "subgroupBroadcast"; + case BuiltinFn::kSubgroupBroadcastFirst: + return "subgroupBroadcastFirst"; + case BuiltinFn::kSubgroupShuffle: + return "subgroupShuffle"; + case BuiltinFn::kSubgroupShuffleXor: + return "subgroupShuffleXor"; + case BuiltinFn::kSubgroupShuffleUp: + return "subgroupShuffleUp"; + case BuiltinFn::kSubgroupShuffleDown: + return "subgroupShuffleDown"; + case BuiltinFn::kSubgroupAdd: + return "subgroupAdd"; + case BuiltinFn::kSubgroupInclusiveAdd: + return "subgroupInclusiveAdd"; + case BuiltinFn::kSubgroupExclusiveAdd: + return "subgroupExclusiveAdd"; + case BuiltinFn::kSubgroupMul: + return "subgroupMul"; + case BuiltinFn::kSubgroupInclusiveMul: + return "subgroupInclusiveMul"; + case BuiltinFn::kSubgroupExclusiveMul: + return "subgroupExclusiveMul"; + case BuiltinFn::kSubgroupAnd: + return "subgroupAnd"; + case BuiltinFn::kSubgroupOr: + return "subgroupOr"; + case BuiltinFn::kSubgroupXor: + return "subgroupXor"; + case BuiltinFn::kSubgroupMin: + return "subgroupMin"; + case BuiltinFn::kSubgroupMax: + return "subgroupMax"; + case BuiltinFn::kSubgroupAll: + return "subgroupAll"; + case BuiltinFn::kSubgroupAny: + return "subgroupAny"; + case BuiltinFn::kQuadBroadcast: + return "quadBroadcast"; + case BuiltinFn::kQuadSwapX: + return "quadSwapX"; + case BuiltinFn::kQuadSwapY: + return "quadSwapY"; + case BuiltinFn::kQuadSwapDiagonal: + return "quadSwapDiagonal"; + case BuiltinFn::kSubgroupMatrixLoad: + return "subgroupMatrixLoad"; + case BuiltinFn::kSubgroupMatrixStore: + return "subgroupMatrixStore"; + case BuiltinFn::kSubgroupMatrixMultiply: + return "subgroupMatrixMultiply"; + case BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + return "subgroupMatrixMultiplyAccumulate"; + case BuiltinFn::kSubgroupMatrixScalarAdd: + return "subgroupMatrixScalarAdd"; + case BuiltinFn::kSubgroupMatrixScalarSubtract: + return "subgroupMatrixScalarSubtract"; + case BuiltinFn::kSubgroupMatrixScalarMultiply: + return "subgroupMatrixScalarMultiply"; + case BuiltinFn::kBufferView: + return "bufferView"; + case BuiltinFn::kBufferLength: + return "bufferLength"; + case BuiltinFn::kPrint: + return "print"; + case BuiltinFn::kTintMaterialize: + return "__tint_materialize"; + case BuiltinFn::kHasResource: + return "hasResource"; + case BuiltinFn::kGetResource: + return "getResource"; + } + return ""; +} + +bool IsDerivative(BuiltinFn f) { + return f == BuiltinFn::kDpdx || f == BuiltinFn::kDpdy || + f == BuiltinFn::kFwidth || f == BuiltinFn::kDpdxCoarse || f == BuiltinFn::kDpdyCoarse || + f == BuiltinFn::kFwidthCoarse || + f == BuiltinFn::kDpdxFine || f == BuiltinFn::kDpdyFine || + f == BuiltinFn::kFwidthFine; +} + +bool IsTexture(BuiltinFn f) { + return f == BuiltinFn::kTextureDimensions || // + f == BuiltinFn::kTextureNumLayers || // + f == BuiltinFn::kTextureNumLevels || // + f == BuiltinFn::kTextureNumSamples || // + f == BuiltinFn::kTextureGather || // + f == BuiltinFn::kTextureGatherCompare || // + f == BuiltinFn::kTextureLoad || // + f == BuiltinFn::kTextureSample || // + f == BuiltinFn::kTextureSampleBaseClampToEdge || // + f == BuiltinFn::kTextureSampleBias || // + f == BuiltinFn::kTextureSampleCompare || // + f == BuiltinFn::kTextureSampleCompareLevel || // + f == BuiltinFn::kTextureSampleGrad || // + f == BuiltinFn::kTextureSampleLevel || // + f == BuiltinFn::kTextureStore || f == BuiltinFn::kInputAttachmentLoad; +} + +bool IsBarrier(BuiltinFn f) { + return f == BuiltinFn::kWorkgroupBarrier || f == BuiltinFn::kStorageBarrier || + f == BuiltinFn::kTextureBarrier; +} + +bool IsAtomic(BuiltinFn f) { + return f == BuiltinFn::kAtomicLoad || f == BuiltinFn::kAtomicStore || + f == BuiltinFn::kAtomicAdd || f == BuiltinFn::kAtomicSub || + f == BuiltinFn::kAtomicMax || f == BuiltinFn::kAtomicMin || + f == BuiltinFn::kAtomicAnd || f == BuiltinFn::kAtomicOr || + f == BuiltinFn::kAtomicXor || f == BuiltinFn::kAtomicExchange || + f == BuiltinFn::kAtomicCompareExchangeWeak; +} + +bool IsPacked4x8IntegerDotProductBuiltin(BuiltinFn f) { + return f == BuiltinFn::kDot4I8Packed || f == BuiltinFn::kDot4U8Packed || + f == BuiltinFn::kPack4XI8 || f == BuiltinFn::kPack4XU8 || + f == BuiltinFn::kPack4XI8Clamp || f == BuiltinFn::kPack4XU8Clamp || + f == BuiltinFn::kUnpack4XI8 || f == BuiltinFn::kUnpack4XU8; +} + +bool IsSubgroup(BuiltinFn f) { + switch (f) { + case BuiltinFn::kSubgroupBallot: + case BuiltinFn::kSubgroupElect: + case BuiltinFn::kSubgroupBroadcast: + case BuiltinFn::kSubgroupBroadcastFirst: + case BuiltinFn::kSubgroupShuffle: + case BuiltinFn::kSubgroupShuffleXor: + case BuiltinFn::kSubgroupShuffleUp: + case BuiltinFn::kSubgroupShuffleDown: + case BuiltinFn::kSubgroupAdd: + case BuiltinFn::kSubgroupInclusiveAdd: + case BuiltinFn::kSubgroupExclusiveAdd: + case BuiltinFn::kSubgroupMul: + case BuiltinFn::kSubgroupInclusiveMul: + case BuiltinFn::kSubgroupExclusiveMul: + case BuiltinFn::kSubgroupAnd: + case BuiltinFn::kSubgroupOr: + case BuiltinFn::kSubgroupXor: + case BuiltinFn::kSubgroupMin: + case BuiltinFn::kSubgroupMax: + case BuiltinFn::kSubgroupAll: + case BuiltinFn::kSubgroupAny: + case BuiltinFn::kQuadBroadcast: + case BuiltinFn::kQuadSwapX: + case BuiltinFn::kQuadSwapY: + case BuiltinFn::kQuadSwapDiagonal: + return true; + default: + return false; + } +} + +bool IsSubgroupMatrix(BuiltinFn f) { + switch (f) { + case BuiltinFn::kSubgroupMatrixLoad: + case BuiltinFn::kSubgroupMatrixStore: + case BuiltinFn::kSubgroupMatrixMultiply: + case BuiltinFn::kSubgroupMatrixMultiplyAccumulate: + case BuiltinFn::kSubgroupMatrixScalarAdd: + case BuiltinFn::kSubgroupMatrixScalarSubtract: + case BuiltinFn::kSubgroupMatrixScalarMultiply: + return true; + default: + return false; + } +} + +bool IsResourceTable(BuiltinFn f) { + switch (f) { + case BuiltinFn::kGetResource: + case BuiltinFn::kHasResource: + return true; + default: + return false; + } +} + +} // namespace tint::wgsl + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/wgsl/enums.h b/3rdparty/dawn/src/tint/lang/wgsl/enums.h new file mode 100644 index 000000000..a3de573eb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/enums.h @@ -0,0 +1,899 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/wgsl/enums.h.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SRC_TINT_LANG_WGSL_ENUMS_H_ +#define SRC_TINT_LANG_WGSL_ENUMS_H_ + +// clang-format off + +#include +#include +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint::wgsl { + +/// WGSL core diagnostic rules. +enum class CoreDiagnosticRule : uint8_t { + kUndefined, + kDerivativeUniformity, + kSubgroupUniformity, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(CoreDiagnosticRule value); + +/// @param out the stream to write to +/// @param value the CoreDiagnosticRule +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, CoreDiagnosticRule value) { + return out << ToString(value); +} + +/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string. +/// @param str the string to parse +/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed. +CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str); + +constexpr std::string_view kCoreDiagnosticRuleStrings[] = { + "derivative_uniformity", + "subgroup_uniformity", +}; + +/// Chromium-specific diagnostic rules. +enum class ChromiumDiagnosticRule : uint8_t { + kUndefined, + kSubgroupMatrixUniformity, + kUnreachableCode, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(ChromiumDiagnosticRule value); + +/// @param out the stream to write to +/// @param value the ChromiumDiagnosticRule +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, ChromiumDiagnosticRule value) { + return out << ToString(value); +} + +/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string. +/// @param str the string to parse +/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be parsed. +ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str); + +constexpr std::string_view kChromiumDiagnosticRuleStrings[] = { + "subgroup_matrix_uniformity", + "unreachable_code", +}; + +/// An enumerator of WGSL extensions +/// @see src/tint/lang/wgsl/wgsl.def for extension descriptions +enum class Extension : uint8_t { + kUndefined, + kChromiumDisableUniformityAnalysis, + kChromiumExperimentalBarycentricCoord, + kChromiumExperimentalFramebufferFetch, + kChromiumExperimentalPixelLocal, + kChromiumExperimentalResourceTable, + kChromiumExperimentalSubgroupMatrix, + kChromiumExperimentalSubgroupSizeControl, + kChromiumInternalGraphite, + kChromiumInternalInputAttachments, + kClipDistances, + kDualSourceBlending, + kF16, + kPrimitiveIndex, + kSubgroups, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(Extension value); + +/// @param out the stream to write to +/// @param value the Extension +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Extension value) { + return out << ToString(value); +} + +/// ParseExtension parses a Extension from a string. +/// @param str the string to parse +/// @returns the parsed enum, or Extension::kUndefined if the string could not be parsed. +Extension ParseExtension(std::string_view str); + +constexpr std::string_view kExtensionStrings[] = { + "chromium_disable_uniformity_analysis", + "chromium_experimental_barycentric_coord", + "chromium_experimental_framebuffer_fetch", + "chromium_experimental_pixel_local", + "chromium_experimental_resource_table", + "chromium_experimental_subgroup_matrix", + "chromium_experimental_subgroup_size_control", + "chromium_internal_graphite", + "chromium_internal_input_attachments", + "clip_distances", + "dual_source_blending", + "f16", + "primitive_index", + "subgroups", +}; + +/// All extensions +static constexpr Extension kAllExtensions[] = { + Extension::kChromiumDisableUniformityAnalysis, + Extension::kChromiumExperimentalBarycentricCoord, + Extension::kChromiumExperimentalFramebufferFetch, + Extension::kChromiumExperimentalPixelLocal, + Extension::kChromiumExperimentalResourceTable, + Extension::kChromiumExperimentalSubgroupMatrix, + Extension::kChromiumExperimentalSubgroupSizeControl, + Extension::kChromiumInternalGraphite, + Extension::kChromiumInternalInputAttachments, + Extension::kClipDistances, + Extension::kDualSourceBlending, + Extension::kF16, + Extension::kPrimitiveIndex, + Extension::kSubgroups, +}; + +/// An enumerator of WGSL language features +/// @see src/tint/lang/wgsl/wgsl.def for language feature descriptions +enum class LanguageFeature : uint8_t { + kUndefined, + kBufferView, + kChromiumPrint, + kChromiumTestingExperimental, + kChromiumTestingShipped, + kChromiumTestingShippedWithKillswitch, + kChromiumTestingUnimplemented, + kChromiumTestingUnsafeExperimental, + kFragmentDepth, + kImmediateAddressSpace, + kPacked4X8IntegerDotProduct, + kPointerCompositeAccess, + kReadonlyAndReadwriteStorageTextures, + kSizedBindingArray, + kSubgroupId, + kSubgroupUniformity, + kTexelBuffers, + kTextureAndSamplerLet, + kUniformBufferStandardLayout, + kUnrestrictedPointerParameters, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(LanguageFeature value); + +/// ParseLanguageFeature parses a LanguageFeature from a string. +/// @param str the string to parse +/// @returns the parsed enum, or LanguageFeature::kUndefined if the string could not be parsed. +LanguageFeature ParseLanguageFeature(std::string_view str); + +constexpr std::string_view kLanguageFeatureStrings[] = { + "buffer_view", + "chromium_print", + "chromium_testing_experimental", + "chromium_testing_shipped", + "chromium_testing_shipped_with_killswitch", + "chromium_testing_unimplemented", + "chromium_testing_unsafe_experimental", + "fragment_depth", + "immediate_address_space", + "packed_4x8_integer_dot_product", + "pointer_composite_access", + "readonly_and_readwrite_storage_textures", + "sized_binding_array", + "subgroup_id", + "subgroup_uniformity", + "texel_buffers", + "texture_and_sampler_let", + "uniform_buffer_standard_layout", + "unrestricted_pointer_parameters", +}; + +/// All features +static constexpr LanguageFeature kAllLanguageFeatures[] = { + LanguageFeature::kBufferView, + LanguageFeature::kChromiumPrint, + LanguageFeature::kChromiumTestingExperimental, + LanguageFeature::kChromiumTestingShipped, + LanguageFeature::kChromiumTestingShippedWithKillswitch, + LanguageFeature::kChromiumTestingUnimplemented, + LanguageFeature::kChromiumTestingUnsafeExperimental, + LanguageFeature::kFragmentDepth, + LanguageFeature::kImmediateAddressSpace, + LanguageFeature::kPacked4X8IntegerDotProduct, + LanguageFeature::kPointerCompositeAccess, + LanguageFeature::kReadonlyAndReadwriteStorageTextures, + LanguageFeature::kSizedBindingArray, + LanguageFeature::kSubgroupId, + LanguageFeature::kSubgroupUniformity, + LanguageFeature::kTexelBuffers, + LanguageFeature::kTextureAndSamplerLet, + LanguageFeature::kUniformBufferStandardLayout, + LanguageFeature::kUnrestrictedPointerParameters, +}; + +/// A unique vector of extensions +using Extensions = UniqueVector; + +/// All diagnostic rules understood by Tint. +using DiagnosticRule = std::variant; + +/// The diagnostic severity control. +enum class DiagnosticSeverity : uint8_t { + kUndefined, + kError, + kInfo, + kOff, + kWarning, +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString(DiagnosticSeverity value); + +/// @param out the stream to write to +/// @param value the DiagnosticSeverity +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, DiagnosticSeverity value) { + return out << ToString(value); +} + +/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string. +/// @param str the string to parse +/// @returns the parsed enum, or DiagnosticSeverity::kUndefined if the string could not be parsed. +DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str); + +constexpr std::string_view kDiagnosticSeverityStrings[] = { + "error", + "info", + "off", + "warning", +}; + +/// Convert a DiagnosticSeverity to the corresponding diag::Severity. +diag::Severity ToSeverity(DiagnosticSeverity sc); + +/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity. +using DiagnosticRuleSeverities = Hashmap; + + +/// Enumerator of all builtin functions +enum class BuiltinFn : uint8_t { + kAbs, + kAcos, + kAcosh, + kAll, + kAny, + kArrayLength, + kAsin, + kAsinh, + kAtan, + kAtan2, + kAtanh, + kBitcast, + kCeil, + kClamp, + kCos, + kCosh, + kCountLeadingZeros, + kCountOneBits, + kCountTrailingZeros, + kCross, + kDegrees, + kDeterminant, + kDistance, + kDot, + kDot4I8Packed, + kDot4U8Packed, + kDpdx, + kDpdxCoarse, + kDpdxFine, + kDpdy, + kDpdyCoarse, + kDpdyFine, + kExp, + kExp2, + kExtractBits, + kFaceForward, + kFirstLeadingBit, + kFirstTrailingBit, + kFloor, + kFma, + kFract, + kFrexp, + kFwidth, + kFwidthCoarse, + kFwidthFine, + kInsertBits, + kInverseSqrt, + kLdexp, + kLength, + kLog, + kLog2, + kMax, + kMin, + kMix, + kModf, + kNormalize, + kPack2X16Float, + kPack2X16Snorm, + kPack2X16Unorm, + kPack4X8Snorm, + kPack4X8Unorm, + kPack4XI8, + kPack4XU8, + kPack4XI8Clamp, + kPack4XU8Clamp, + kPow, + kQuantizeToF16, + kRadians, + kReflect, + kRefract, + kReverseBits, + kRound, + kSaturate, + kSelect, + kSign, + kSin, + kSinh, + kSmoothstep, + kSqrt, + kStep, + kStorageBarrier, + kTan, + kTanh, + kTranspose, + kTrunc, + kUnpack2X16Float, + kUnpack2X16Snorm, + kUnpack2X16Unorm, + kUnpack4X8Snorm, + kUnpack4X8Unorm, + kUnpack4XI8, + kUnpack4XU8, + kWorkgroupBarrier, + kWorkgroupUniformLoad, + kTextureBarrier, + kTextureDimensions, + kTextureGather, + kTextureGatherCompare, + kTextureNumLayers, + kTextureNumLevels, + kTextureNumSamples, + kTextureSample, + kTextureSampleBias, + kTextureSampleCompare, + kTextureSampleCompareLevel, + kTextureSampleGrad, + kTextureSampleLevel, + kTextureSampleBaseClampToEdge, + kTextureStore, + kTextureLoad, + kInputAttachmentLoad, + kAtomicLoad, + kAtomicStore, + kAtomicAdd, + kAtomicSub, + kAtomicMax, + kAtomicMin, + kAtomicAnd, + kAtomicOr, + kAtomicXor, + kAtomicExchange, + kAtomicCompareExchangeWeak, + kSubgroupBallot, + kSubgroupElect, + kSubgroupBroadcast, + kSubgroupBroadcastFirst, + kSubgroupShuffle, + kSubgroupShuffleXor, + kSubgroupShuffleUp, + kSubgroupShuffleDown, + kSubgroupAdd, + kSubgroupInclusiveAdd, + kSubgroupExclusiveAdd, + kSubgroupMul, + kSubgroupInclusiveMul, + kSubgroupExclusiveMul, + kSubgroupAnd, + kSubgroupOr, + kSubgroupXor, + kSubgroupMin, + kSubgroupMax, + kSubgroupAll, + kSubgroupAny, + kQuadBroadcast, + kQuadSwapX, + kQuadSwapY, + kQuadSwapDiagonal, + kSubgroupMatrixLoad, + kSubgroupMatrixStore, + kSubgroupMatrixMultiply, + kSubgroupMatrixMultiplyAccumulate, + kSubgroupMatrixScalarAdd, + kSubgroupMatrixScalarSubtract, + kSubgroupMatrixScalarMultiply, + kBufferView, + kBufferLength, + kPrint, + kTintMaterialize, + kHasResource, + kGetResource, + kNone, +}; + +/// Matches the BuiltinFn by name +/// @param name the builtin name to parse +/// @returns the parsed BuiltinFn, or BuiltinFn::kNone if `name` did not +/// match any builtin function. +BuiltinFn ParseBuiltinFn(std::string_view name); + +/// @returns the name of the builtin function type. The spelling, including +/// case, matches the name in the WGSL spec. +const char* str(BuiltinFn i); + +/// Emits the name of the builtin function type. The spelling, including case, +/// matches the name in the WGSL spec. +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, BuiltinFn i) { + return o << str(i); +} + +/// All builtin functions +constexpr BuiltinFn kBuiltinFns[] = { + BuiltinFn::kAbs, + BuiltinFn::kAcos, + BuiltinFn::kAcosh, + BuiltinFn::kAll, + BuiltinFn::kAny, + BuiltinFn::kArrayLength, + BuiltinFn::kAsin, + BuiltinFn::kAsinh, + BuiltinFn::kAtan, + BuiltinFn::kAtan2, + BuiltinFn::kAtanh, + BuiltinFn::kBitcast, + BuiltinFn::kCeil, + BuiltinFn::kClamp, + BuiltinFn::kCos, + BuiltinFn::kCosh, + BuiltinFn::kCountLeadingZeros, + BuiltinFn::kCountOneBits, + BuiltinFn::kCountTrailingZeros, + BuiltinFn::kCross, + BuiltinFn::kDegrees, + BuiltinFn::kDeterminant, + BuiltinFn::kDistance, + BuiltinFn::kDot, + BuiltinFn::kDot4I8Packed, + BuiltinFn::kDot4U8Packed, + BuiltinFn::kDpdx, + BuiltinFn::kDpdxCoarse, + BuiltinFn::kDpdxFine, + BuiltinFn::kDpdy, + BuiltinFn::kDpdyCoarse, + BuiltinFn::kDpdyFine, + BuiltinFn::kExp, + BuiltinFn::kExp2, + BuiltinFn::kExtractBits, + BuiltinFn::kFaceForward, + BuiltinFn::kFirstLeadingBit, + BuiltinFn::kFirstTrailingBit, + BuiltinFn::kFloor, + BuiltinFn::kFma, + BuiltinFn::kFract, + BuiltinFn::kFrexp, + BuiltinFn::kFwidth, + BuiltinFn::kFwidthCoarse, + BuiltinFn::kFwidthFine, + BuiltinFn::kInsertBits, + BuiltinFn::kInverseSqrt, + BuiltinFn::kLdexp, + BuiltinFn::kLength, + BuiltinFn::kLog, + BuiltinFn::kLog2, + BuiltinFn::kMax, + BuiltinFn::kMin, + BuiltinFn::kMix, + BuiltinFn::kModf, + BuiltinFn::kNormalize, + BuiltinFn::kPack2X16Float, + BuiltinFn::kPack2X16Snorm, + BuiltinFn::kPack2X16Unorm, + BuiltinFn::kPack4X8Snorm, + BuiltinFn::kPack4X8Unorm, + BuiltinFn::kPack4XI8, + BuiltinFn::kPack4XU8, + BuiltinFn::kPack4XI8Clamp, + BuiltinFn::kPack4XU8Clamp, + BuiltinFn::kPow, + BuiltinFn::kQuantizeToF16, + BuiltinFn::kRadians, + BuiltinFn::kReflect, + BuiltinFn::kRefract, + BuiltinFn::kReverseBits, + BuiltinFn::kRound, + BuiltinFn::kSaturate, + BuiltinFn::kSelect, + BuiltinFn::kSign, + BuiltinFn::kSin, + BuiltinFn::kSinh, + BuiltinFn::kSmoothstep, + BuiltinFn::kSqrt, + BuiltinFn::kStep, + BuiltinFn::kStorageBarrier, + BuiltinFn::kTan, + BuiltinFn::kTanh, + BuiltinFn::kTranspose, + BuiltinFn::kTrunc, + BuiltinFn::kUnpack2X16Float, + BuiltinFn::kUnpack2X16Snorm, + BuiltinFn::kUnpack2X16Unorm, + BuiltinFn::kUnpack4X8Snorm, + BuiltinFn::kUnpack4X8Unorm, + BuiltinFn::kUnpack4XI8, + BuiltinFn::kUnpack4XU8, + BuiltinFn::kWorkgroupBarrier, + BuiltinFn::kWorkgroupUniformLoad, + BuiltinFn::kTextureBarrier, + BuiltinFn::kTextureDimensions, + BuiltinFn::kTextureGather, + BuiltinFn::kTextureGatherCompare, + BuiltinFn::kTextureNumLayers, + BuiltinFn::kTextureNumLevels, + BuiltinFn::kTextureNumSamples, + BuiltinFn::kTextureSample, + BuiltinFn::kTextureSampleBias, + BuiltinFn::kTextureSampleCompare, + BuiltinFn::kTextureSampleCompareLevel, + BuiltinFn::kTextureSampleGrad, + BuiltinFn::kTextureSampleLevel, + BuiltinFn::kTextureSampleBaseClampToEdge, + BuiltinFn::kTextureStore, + BuiltinFn::kTextureLoad, + BuiltinFn::kInputAttachmentLoad, + BuiltinFn::kAtomicLoad, + BuiltinFn::kAtomicStore, + BuiltinFn::kAtomicAdd, + BuiltinFn::kAtomicSub, + BuiltinFn::kAtomicMax, + BuiltinFn::kAtomicMin, + BuiltinFn::kAtomicAnd, + BuiltinFn::kAtomicOr, + BuiltinFn::kAtomicXor, + BuiltinFn::kAtomicExchange, + BuiltinFn::kAtomicCompareExchangeWeak, + BuiltinFn::kSubgroupBallot, + BuiltinFn::kSubgroupElect, + BuiltinFn::kSubgroupBroadcast, + BuiltinFn::kSubgroupBroadcastFirst, + BuiltinFn::kSubgroupShuffle, + BuiltinFn::kSubgroupShuffleXor, + BuiltinFn::kSubgroupShuffleUp, + BuiltinFn::kSubgroupShuffleDown, + BuiltinFn::kSubgroupAdd, + BuiltinFn::kSubgroupInclusiveAdd, + BuiltinFn::kSubgroupExclusiveAdd, + BuiltinFn::kSubgroupMul, + BuiltinFn::kSubgroupInclusiveMul, + BuiltinFn::kSubgroupExclusiveMul, + BuiltinFn::kSubgroupAnd, + BuiltinFn::kSubgroupOr, + BuiltinFn::kSubgroupXor, + BuiltinFn::kSubgroupMin, + BuiltinFn::kSubgroupMax, + BuiltinFn::kSubgroupAll, + BuiltinFn::kSubgroupAny, + BuiltinFn::kQuadBroadcast, + BuiltinFn::kQuadSwapX, + BuiltinFn::kQuadSwapY, + BuiltinFn::kQuadSwapDiagonal, + BuiltinFn::kSubgroupMatrixLoad, + BuiltinFn::kSubgroupMatrixStore, + BuiltinFn::kSubgroupMatrixMultiply, + BuiltinFn::kSubgroupMatrixMultiplyAccumulate, + BuiltinFn::kSubgroupMatrixScalarAdd, + BuiltinFn::kSubgroupMatrixScalarSubtract, + BuiltinFn::kSubgroupMatrixScalarMultiply, + BuiltinFn::kBufferView, + BuiltinFn::kBufferLength, + BuiltinFn::kPrint, + BuiltinFn::kTintMaterialize, + BuiltinFn::kHasResource, + BuiltinFn::kGetResource, +}; + +/// All builtin function names +constexpr const char* kBuiltinFnStrings[] = { + "abs", + "acos", + "acosh", + "all", + "any", + "arrayLength", + "asin", + "asinh", + "atan", + "atan2", + "atanh", + "bitcast", + "ceil", + "clamp", + "cos", + "cosh", + "countLeadingZeros", + "countOneBits", + "countTrailingZeros", + "cross", + "degrees", + "determinant", + "distance", + "dot", + "dot4I8Packed", + "dot4U8Packed", + "dpdx", + "dpdxCoarse", + "dpdxFine", + "dpdy", + "dpdyCoarse", + "dpdyFine", + "exp", + "exp2", + "extractBits", + "faceForward", + "firstLeadingBit", + "firstTrailingBit", + "floor", + "fma", + "fract", + "frexp", + "fwidth", + "fwidthCoarse", + "fwidthFine", + "insertBits", + "inverseSqrt", + "ldexp", + "length", + "log", + "log2", + "max", + "min", + "mix", + "modf", + "normalize", + "pack2x16float", + "pack2x16snorm", + "pack2x16unorm", + "pack4x8snorm", + "pack4x8unorm", + "pack4xI8", + "pack4xU8", + "pack4xI8Clamp", + "pack4xU8Clamp", + "pow", + "quantizeToF16", + "radians", + "reflect", + "refract", + "reverseBits", + "round", + "saturate", + "select", + "sign", + "sin", + "sinh", + "smoothstep", + "sqrt", + "step", + "storageBarrier", + "tan", + "tanh", + "transpose", + "trunc", + "unpack2x16float", + "unpack2x16snorm", + "unpack2x16unorm", + "unpack4x8snorm", + "unpack4x8unorm", + "unpack4xI8", + "unpack4xU8", + "workgroupBarrier", + "workgroupUniformLoad", + "textureBarrier", + "textureDimensions", + "textureGather", + "textureGatherCompare", + "textureNumLayers", + "textureNumLevels", + "textureNumSamples", + "textureSample", + "textureSampleBias", + "textureSampleCompare", + "textureSampleCompareLevel", + "textureSampleGrad", + "textureSampleLevel", + "textureSampleBaseClampToEdge", + "textureStore", + "textureLoad", + "inputAttachmentLoad", + "atomicLoad", + "atomicStore", + "atomicAdd", + "atomicSub", + "atomicMax", + "atomicMin", + "atomicAnd", + "atomicOr", + "atomicXor", + "atomicExchange", + "atomicCompareExchangeWeak", + "subgroupBallot", + "subgroupElect", + "subgroupBroadcast", + "subgroupBroadcastFirst", + "subgroupShuffle", + "subgroupShuffleXor", + "subgroupShuffleUp", + "subgroupShuffleDown", + "subgroupAdd", + "subgroupInclusiveAdd", + "subgroupExclusiveAdd", + "subgroupMul", + "subgroupInclusiveMul", + "subgroupExclusiveMul", + "subgroupAnd", + "subgroupOr", + "subgroupXor", + "subgroupMin", + "subgroupMax", + "subgroupAll", + "subgroupAny", + "quadBroadcast", + "quadSwapX", + "quadSwapY", + "quadSwapDiagonal", + "subgroupMatrixLoad", + "subgroupMatrixStore", + "subgroupMatrixMultiply", + "subgroupMatrixMultiplyAccumulate", + "subgroupMatrixScalarAdd", + "subgroupMatrixScalarSubtract", + "subgroupMatrixScalarMultiply", + "bufferView", + "bufferLength", + "print", + "__tint_materialize", + "hasResource", + "getResource", +}; + +/// Determines if the given `f` is a coarse derivative. +/// @param f the builtin type +/// @returns true if the given derivative is coarse. +bool IsCoarseDerivative(BuiltinFn f); + +/// Determines if the given `f` is a fine derivative. +/// @param f the builtin type +/// @returns true if the given derivative is fine. +bool IsFineDerivative(BuiltinFn f); + +/// Determine if the given `f` is a derivative builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a derivative builtin +bool IsDerivative(BuiltinFn f); + +/// Determines if the given `f` is a texture operation builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a texture operation builtin +bool IsTexture(BuiltinFn f); + +/// Determines if the given `f` is an image query builtin. +/// @param f the builtin type +/// @returns true if the given `f` is an image query builtin +bool IsImageQuery(BuiltinFn f); + +/// Determines if the given `f` is a data packing builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a data packing builtin +bool IsDataPacking(BuiltinFn f); + +/// Determines if the given `f` is a data unpacking builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a data unpacking builtin +bool IsDataUnpacking(BuiltinFn f); + +/// Determines if the given `f` is a barrier builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a barrier builtin +bool IsBarrier(BuiltinFn f); + +/// Determines if the given `f` is an atomic builtin. +/// @param f the builtin type +/// @returns true if the given `f` is an atomic builtin +bool IsAtomic(BuiltinFn f); + +/// Determines if the given `f` is a builtin defined in the language extension +/// `packed_4x8_integer_dot_product`. +/// @param f the builtin type +/// @returns true if the given `f` is a builtin defined in the language extension +/// `packed_4x8_integer_dot_product`. +bool IsPacked4x8IntegerDotProductBuiltin(BuiltinFn f); + +/// Determines if the given `f` is a subgroup builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a subgroup builtin +bool IsSubgroup(BuiltinFn f); + +/// Determines if the given `f` is a subgroup matrix builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a subgroup matrix builtin +bool IsSubgroupMatrix(BuiltinFn f); + +/// Determines if the given `f` is a quadSwap* builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a quadSwap* builtin +bool IsQuadSwap(BuiltinFn f); + +/// Determines if the given `f` is a resource table builtin. +/// @param f the builtin type +/// @returns true if the given `f` is a resource table builtin +bool IsResourceTable(BuiltinFn f); + +} // namespace tint::wgsl + +// clang-format on + +#endif // SRC_TINT_LANG_WGSL_ENUMS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/feature_status.cc b/3rdparty/dawn/src/tint/lang/wgsl/feature_status.cc new file mode 100644 index 000000000..19f54410f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/feature_status.cc @@ -0,0 +1,85 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/feature_status.h" + +#include "src/tint/lang/wgsl/enums.h" + +namespace tint::wgsl { + +FeatureStatus GetLanguageFeatureStatus(LanguageFeature f) { + switch (f) { + //////////////////////////////////////////////////////////////////// + // Experimental features + /////////////////////////////////////////////////////////////////// + case LanguageFeature::kSizedBindingArray: + case LanguageFeature::kTexelBuffers: + case LanguageFeature::kFragmentDepth: + case LanguageFeature::kImmediateAddressSpace: + case LanguageFeature::kTextureAndSamplerLet: + case LanguageFeature::kBufferView: + return FeatureStatus::kUnsafeExperimental; + + //////////////////////////////////////////////////////////////////// + // Chromium developer features + /////////////////////////////////////////////////////////////////// + case LanguageFeature::kChromiumPrint: + return FeatureStatus::kUnsafeExperimental; + + //////////////////////////////////////////////////////////////////// + // Enabled features + //////////////////////////////////////////////////////////////////// + case LanguageFeature::kPacked4X8IntegerDotProduct: + case LanguageFeature::kPointerCompositeAccess: + case LanguageFeature::kUnrestrictedPointerParameters: + case LanguageFeature::kReadonlyAndReadwriteStorageTextures: + case LanguageFeature::kUniformBufferStandardLayout: + case LanguageFeature::kSubgroupId: + case LanguageFeature::kSubgroupUniformity: + return FeatureStatus::kShippedWithKillswitch; + + //////////////////////////////////////////////////////////////////// + // Testing / special cases + //////////////////////////////////////////////////////////////////// + case LanguageFeature::kChromiumTestingUnimplemented: + return FeatureStatus::kUnimplemented; + case LanguageFeature::kChromiumTestingUnsafeExperimental: + return FeatureStatus::kUnsafeExperimental; + case LanguageFeature::kChromiumTestingExperimental: + return FeatureStatus::kExperimental; + case LanguageFeature::kChromiumTestingShippedWithKillswitch: + return FeatureStatus::kShippedWithKillswitch; + case LanguageFeature::kChromiumTestingShipped: + return FeatureStatus::kShipped; + case LanguageFeature::kUndefined: + return FeatureStatus::kUnknown; + } + + return FeatureStatus::kUnknown; +} + +} // namespace tint::wgsl diff --git a/3rdparty/dawn/src/tint/lang/wgsl/feature_status.h b/3rdparty/dawn/src/tint/lang/wgsl/feature_status.h new file mode 100644 index 000000000..1a38bcacb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/feature_status.h @@ -0,0 +1,63 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_FEATURE_STATUS_H_ +#define SRC_TINT_LANG_WGSL_FEATURE_STATUS_H_ + +#include + +namespace tint::wgsl { + +enum class LanguageFeature : uint8_t; + +/// The status of the implementation of a WGSL language feature so that other components (like Dawn) +/// can query it. The enum values are in the order of least implemented to most implemented. +enum class FeatureStatus : uint8_t { + // The feature is not known. + kUnknown, + // The feature is known in wgsl.def but not implemented at all. + kUnimplemented, + // The feature is at least partially implemented but might contain big security of correctness + // issues. + kUnsafeExperimental, + // The feature is implemented and should be safe from a security standpoint, but shouldn't be + // exposed by default. + kExperimental, + // The feature is implemented and can be exposed by default, but is only turned on if the + // feature is explicitly enabled in the wgsl reader options. + kShippedWithKillswitch, + // The feature is exposed by default and cannot be turned off. + kShipped, +}; + +/// @param f the feature to get the status of. +/// @returns the status, or kUnknown if the feature is not known. +FeatureStatus GetLanguageFeatureStatus(LanguageFeature f); + +} // namespace tint::wgsl + +#endif // SRC_TINT_LANG_WGSL_FEATURE_STATUS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.cc b/3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.cc new file mode 100644 index 000000000..a93a83b1d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.cc @@ -0,0 +1,41 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/inspector/entry_point.h" + +namespace tint::inspector { + +StageVariable::StageVariable() = default; +StageVariable::StageVariable(const StageVariable& other) = default; +StageVariable::~StageVariable() = default; + +EntryPoint::EntryPoint() = default; +EntryPoint::EntryPoint(EntryPoint&) = default; +EntryPoint::EntryPoint(EntryPoint&&) = default; +EntryPoint::~EntryPoint() = default; + +} // namespace tint::inspector diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.h b/3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.h new file mode 100644 index 000000000..dd8e8f730 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/entry_point.h @@ -0,0 +1,224 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INSPECTOR_ENTRY_POINT_H_ +#define SRC_TINT_LANG_WGSL_INSPECTOR_ENTRY_POINT_H_ + +#include +#include +#include + +#include "src/tint/api/common/override_id.h" + +namespace tint::inspector { + +/// Base component type of a stage variable. +enum class ComponentType : uint8_t { + kF32, + kU32, + kI32, + kF16, + kUnknown, +}; + +/// Composition of components of a stage variable. +enum class CompositionType : uint8_t { + kScalar, + kVec2, + kVec3, + kVec4, + kUnknown, +}; + +/// Types of `pixel_local` variable members. +enum class PixelLocalMemberType : uint8_t { + kF32, + kU32, + kI32, + kUnknown, +}; + +/// Type of interpolation of a stage variable. +enum class InterpolationType : uint8_t { kPerspective, kLinear, kFlat, kUnknown }; + +/// Type of interpolation sampling of a stage variable. +enum class InterpolationSampling : uint8_t { + kNone, + kCenter, + kCentroid, + kSample, + kFirst, + kEither, + kUnknown +}; + +/// Reflection data about an entry point input or output. +struct StageVariable { + /// Constructor + StageVariable(); + /// Copy constructor + /// @param other the StageVariable to copy + StageVariable(const StageVariable& other); + /// Destructor + ~StageVariable(); + + /// Name of the variable in the shader. (including struct nested accessing, e.g. 'struct.var') + std::string name; + /// Name of the variable itself. (e.g. 'var') + std::string variable_name; + /// Attributes applied to the variable + struct { + /// Value of the location attribute, if set. + std::optional location; + /// Value of the color attribute, if set. + std::optional color; + /// Value of the blend_src attribute, if set. + std::optional blend_src; + } attributes; + /// Scalar type that the variable is composed of. + ComponentType component_type = ComponentType::kUnknown; + /// How the scalars are composed for the variable. + CompositionType composition_type = CompositionType::kUnknown; + /// Interpolation type of the variable. + InterpolationType interpolation_type = InterpolationType::kUnknown; + /// Interpolation sampling of the variable. + InterpolationSampling interpolation_sampling = InterpolationSampling::kUnknown; +}; + +/// Reflection data about an override variable referenced by an entry point +struct Override { + /// Name of the override + std::string name; + + /// ID of the override + OverrideId id; + + /// Type of the scalar + enum class Type { + kBool, + kFloat32, + kUint32, + kInt32, + kFloat16, + }; + + /// Type of the scalar + Type type; + + /// Does this override have an initializer? + bool is_initialized = false; + + /// Does this override have a numeric ID specified explicitly? + bool is_id_specified = false; +}; + +/// The pipeline stage +enum class PipelineStage { kVertex, kFragment, kCompute }; + +/// WorkgroupSize describes the dimensions of the workgroup grid for a compute shader. +struct WorkgroupSize { + /// The 'x' dimension of the workgroup grid + uint32_t x = 1; + /// The 'y' dimension of the workgroup grid + uint32_t y = 1; + /// The 'z' dimension of the workgroup grid + uint32_t z = 1; +}; + +/// Reflection data for an entry point in the shader. +struct EntryPoint { + /// Constructors + EntryPoint(); + /// Copy Constructor + EntryPoint(EntryPoint&); + /// Move Constructor + EntryPoint(EntryPoint&&); + ~EntryPoint(); + + /// The entry point name + std::string name; + /// The entry point stage + PipelineStage stage; + /// The workgroup size. If PipelineStage is kCompute and this holds no value, then the workgroup + /// size is derived from an override-expression. In this situation you first need to run the + /// SubstituteOverride transform before using the inspector. + std::optional workgroup_size; + /// The total size in bytes of all Workgroup storage-class storage accessed via the entry point. + uint32_t workgroup_storage_size = 0; + /// The total size in bytes of all immediate variables accessed by the entry point. + uint32_t immediate_data_size = 0; + /// List of the input variable accessed via this entry point. + std::vector input_variables; + /// List of the output variable accessed via this entry point. + std::vector output_variables; + /// List of the pipeline overridable constants accessed via this entry point. + std::vector overrides; + /// List of the variable types used in the `pixel_local` block accessed by this entry point (if + /// any). + std::vector pixel_local_members; + /// Does the entry point use the sample_mask builtin as an input builtin + /// variable. + bool input_sample_mask_used = false; + /// Does the entry point use the sample_mask builtin as an output builtin + /// variable. + bool output_sample_mask_used = false; + /// Does the entry point use the front_facing builtin + bool front_facing_used = false; + /// Does the entry point use the sample_index builtin + bool sample_index_used = false; + /// Does the entry point use the num_workgroups builtin + bool num_workgroups_used = false; + /// Does the entry point use the frag_depth builtin + bool frag_depth_used = false; + /// Does the frag shader use the position builtin + bool frag_position_used = false; + /// Does the entry point use the vertex_index builtin + bool vertex_index_used = false; + /// Does the entry point use the instance_index builtin + bool instance_index_used = false; + /// Does the entry point have a textureLoad call with a texture_depth??? texture + bool has_texture_load_with_depth_texture = false; + /// Does the entry point use texture_depth??? with a non-comparison sampler. + bool has_depth_texture_with_non_comparison_sampler = false; + /// Does the entry point use a subgroup matrix type? + bool uses_subgroup_matrix = false; + /// Does the entry point use dpdxFine, dpdyFine, or fwidthFine + bool fine_derivative_builtin_used = false; + /// Does the entry point use primitive_index + bool primitive_index_used = false; + /// Does the entry point use subgroup_invocation_id + bool subgroup_invocation_id_used = false; + /// Does the entry point use subgroup_size + bool subgroup_size_used = false; + /// The array length of the clip_distances builtin. Holding no value means the clip_distances + /// is not used. + std::optional clip_distances_size; +}; + +} // namespace tint::inspector + +#endif // SRC_TINT_LANG_WGSL_INSPECTOR_ENTRY_POINT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.cc b/3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.cc new file mode 100644 index 000000000..2612740ae --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.cc @@ -0,0 +1,1100 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/inspector/inspector.h" + +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/memory_view.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/resource_type.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/identifier_expression.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/module.h" +#include "src/tint/lang/wgsl/ast/override.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/sem/accessor_expression.h" +#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h" +#include "src/tint/lang/wgsl/sem/builtin_fn.h" +#include "src/tint/lang/wgsl/sem/call.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/module.h" +#include "src/tint/lang/wgsl/sem/statement.h" +#include "src/tint/lang/wgsl/sem/struct.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/string.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::inspector { +namespace { + +std::tuple CalculateComponentAndComposition( + const core::type::Type* type) { + // entry point in/out variables must of numeric scalar or vector types. + TINT_ASSERT(type->IsNumericScalarOrVector()); + + ComponentType componentType = Switch( + type->DeepestElement(), // + [&](const core::type::F32*) { return ComponentType::kF32; }, + [&](const core::type::F16*) { return ComponentType::kF16; }, + [&](const core::type::I32*) { return ComponentType::kI32; }, + [&](const core::type::U32*) { return ComponentType::kU32; }, // + TINT_ICE_ON_NO_MATCH); + + CompositionType compositionType; + if (auto* vec = type->As()) { + switch (vec->Width()) { + case 2: { + compositionType = CompositionType::kVec2; + break; + } + case 3: { + compositionType = CompositionType::kVec3; + break; + } + case 4: { + compositionType = CompositionType::kVec4; + break; + } + default: { + TINT_UNREACHABLE() << "unhandled composition type"; + } + } + } else { + compositionType = CompositionType::kScalar; + } + + return {componentType, compositionType}; +} + +ResourceBinding ConvertBufferToResourceBinding(const tint::sem::GlobalVariable* buffer) { + ResourceBinding result; + result.bind_group = buffer->Attributes().binding_point->group; + result.binding = buffer->Attributes().binding_point->binding; + result.variable_name = buffer->Declaration()->name->symbol.Name(); + + auto* unwrapped_type = buffer->Type()->UnwrapRef(); + result.size = unwrapped_type->Size(); + result.size_no_padding = result.size; + if (auto* str = unwrapped_type->As()) { + result.size_no_padding = str->SizeNoPadding(); + } + + if (buffer->AddressSpace() == core::AddressSpace::kStorage) { + if (buffer->Access() == core::Access::kReadWrite) { + result.resource_type = ResourceBinding::ResourceType::kStorageBuffer; + } else { + TINT_ASSERT(buffer->Access() == core::Access::kRead); + result.resource_type = ResourceBinding::ResourceType::kReadOnlyStorageBuffer; + } + } else { + TINT_ASSERT(buffer->AddressSpace() == core::AddressSpace::kUniform); + result.resource_type = ResourceBinding::ResourceType::kUniformBuffer; + } + + return result; +} + +ResourceBinding ConvertHandleToResourceBinding(const tint::sem::GlobalVariable* handle) { + ResourceBinding result; + result.bind_group = handle->Attributes().binding_point->group; + result.binding = handle->Attributes().binding_point->binding; + result.variable_name = handle->Declaration()->name->symbol.Name(); + + const core::type::Type* handle_type = handle->Type()->UnwrapRef(); + + // BindingArray only modifies the array_size member of the ResourceBinding of its inner type. + if (auto* array = handle_type->As()) { + result.array_size = array->Count()->As()->value; + handle_type = array->ElemType(); + } + + Switch( + handle_type, + + [&](const core::type::Sampler* sampler) { + if (sampler->Kind() == core::type::SamplerKind::kSampler) { + result.resource_type = ResourceBinding::ResourceType::kSampler; + } else { + TINT_ASSERT(sampler->Kind() == core::type::SamplerKind::kComparisonSampler); + result.resource_type = ResourceBinding::ResourceType::kComparisonSampler; + } + }, + + [&](const core::type::SampledTexture* tex) { + result.resource_type = ResourceBinding::ResourceType::kSampledTexture; + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(tex->Dim()); + result.sampled_kind = BaseTypeToSampledKind(tex->Type()); + }, + [&](const core::type::MultisampledTexture* tex) { + result.resource_type = ResourceBinding::ResourceType::kMultisampledTexture; + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(tex->Dim()); + result.sampled_kind = BaseTypeToSampledKind(tex->Type()); + }, + [&](const core::type::DepthTexture* tex) { + result.resource_type = ResourceBinding::ResourceType::kDepthTexture; + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(tex->Dim()); + }, + [&](const core::type::DepthMultisampledTexture* tex) { + result.resource_type = ResourceBinding::ResourceType::kDepthMultisampledTexture; + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(tex->Dim()); + }, + [&](const core::type::StorageTexture* tex) { + switch (tex->Access()) { + case core::Access::kWrite: + result.resource_type = ResourceBinding::ResourceType::kWriteOnlyStorageTexture; + break; + case core::Access::kReadWrite: + result.resource_type = ResourceBinding::ResourceType::kReadWriteStorageTexture; + break; + case core::Access::kRead: + result.resource_type = ResourceBinding::ResourceType::kReadOnlyStorageTexture; + break; + case core::Access::kUndefined: + TINT_UNREACHABLE() << "unhandled storage texture access"; + } + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(tex->Dim()); + result.sampled_kind = BaseTypeToSampledKind(tex->Type()); + result.image_format = TypeTexelFormatToResourceBindingTexelFormat(tex->TexelFormat()); + }, + [&](const core::type::ExternalTexture*) { + result.resource_type = ResourceBinding::ResourceType::kExternalTexture; + result.dim = ResourceBinding::TextureDimension::k2d; + }, + [&](const core::type::TexelBuffer* tex) { + result.resource_type = ResourceBinding::ResourceType::kReadWriteTexelBuffer; + switch (tex->Access()) { + case core::Access::kRead: + result.resource_type = ResourceBinding::ResourceType::kReadOnlyTexelBuffer; + break; + case core::Access::kReadWrite: + result.resource_type = ResourceBinding::ResourceType::kReadWriteTexelBuffer; + break; + case core::Access::kWrite: + case core::Access::kUndefined: + TINT_UNREACHABLE() << "unhandled texel buffer access"; + } + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(tex->Dim()); + result.sampled_kind = BaseTypeToSampledKind(tex->Type()); + result.image_format = TypeTexelFormatToResourceBindingTexelFormat(tex->TexelFormat()); + }, + + [&](const core::type::InputAttachment* attachment) { + result.resource_type = ResourceBinding::ResourceType::kInputAttachment; + result.input_attachment_index = handle->Attributes().input_attachment_index.value(); + result.sampled_kind = BaseTypeToSampledKind(attachment->Type()); + result.dim = TypeTextureDimensionToResourceBindingTextureDimension(attachment->Dim()); + }, + + TINT_ICE_ON_NO_MATCH); + + return result; +} + +inspector::Override MkOverride(const sem::GlobalVariable* global, OverrideId id) { + Override override; + override.name = global->Declaration()->name->symbol.Name(); + override.id = id; + + auto* type = global->Type(); + TINT_ASSERT(type->Is()); + if (type->IsBoolScalarOrVector()) { + override.type = Override::Type::kBool; + } else if (type->IsFloatScalar()) { + if (type->Is()) { + override.type = Override::Type::kFloat16; + } else { + override.type = Override::Type::kFloat32; + } + } else if (type->IsSignedIntegerScalar()) { + override.type = Override::Type::kInt32; + } else if (type->IsUnsignedIntegerScalar()) { + override.type = Override::Type::kUint32; + } else { + TINT_UNREACHABLE(); + } + + override.is_initialized = (global->Declaration()->initializer != nullptr); + override.is_id_specified = + ast::HasAttribute(global->Declaration()->attributes); + return override; +} + +bool IsFineDerivativeBuiltin(const sem::BuiltinFn* builtin) { + auto fn = builtin->Fn(); + return fn == wgsl::BuiltinFn::kDpdxFine || fn == wgsl::BuiltinFn::kDpdyFine || + fn == wgsl::BuiltinFn::kFwidthFine; +} + +bool UsesFineDerivatives(const sem::Function* func) { + for (auto& b : func->DirectlyCalledBuiltins()) { + if (IsFineDerivativeBuiltin(b)) { + return true; + } + } + + for (auto& call : func->TransitivelyCalledFunctions()) { + for (auto& b : call->DirectlyCalledBuiltins()) { + if (IsFineDerivativeBuiltin(b)) { + return true; + } + } + } + + return false; +} + +} // namespace + +Inspector::Inspector(const Program& program) : program_(program) {} + +Inspector::~Inspector() = default; + +EntryPoint Inspector::GetEntryPoint(const tint::ast::Function* func) { + EntryPoint entry_point; + TINT_ASSERT(func != nullptr); + TINT_ASSERT(func->IsEntryPoint()); + + auto* sem = program_.Sem().Get(func); + + entry_point.name = func->name->symbol.Name(); + + switch (func->PipelineStage()) { + case ast::PipelineStage::kCompute: { + entry_point.stage = PipelineStage::kCompute; + entry_point.workgroup_storage_size = ComputeWorkgroupStorageSize(func); + + auto wgsize = sem->WorkgroupSize(); + if (wgsize[0].has_value() && wgsize[1].has_value() && wgsize[2].has_value()) { + entry_point.workgroup_size = {wgsize[0].value(), wgsize[1].value(), + wgsize[2].value()}; + } + + entry_point.uses_subgroup_matrix = UsesSubgroupMatrix(sem); + + break; + } + case ast::PipelineStage::kFragment: { + entry_point.stage = PipelineStage::kFragment; + entry_point.pixel_local_members = ComputePixelLocalMemberTypes(func); + break; + } + case ast::PipelineStage::kVertex: { + entry_point.stage = PipelineStage::kVertex; + break; + } + default: { + TINT_UNREACHABLE() << "invalid pipeline stage for entry point '" << entry_point.name + << "'"; + } + } + + entry_point.immediate_data_size = ComputeImmediateDataSize(func); + + for (auto* param : sem->Parameters()) { + AddEntryPointInOutVariables( + param->Declaration()->name->symbol.Name(), param->Declaration()->name->symbol.Name(), + param->Type(), param->Declaration()->attributes, param->Attributes().location, + param->Attributes().color, /* @blend_src */ std::nullopt, entry_point.input_variables); + + entry_point.front_facing_used |= ContainsBuiltin( + core::BuiltinValue::kFrontFacing, param->Type(), param->Declaration()->attributes); + entry_point.sample_index_used |= ContainsBuiltin( + core::BuiltinValue::kSampleIndex, param->Type(), param->Declaration()->attributes); + entry_point.input_sample_mask_used |= ContainsBuiltin( + core::BuiltinValue::kSampleMask, param->Type(), param->Declaration()->attributes); + entry_point.num_workgroups_used |= ContainsBuiltin( + core::BuiltinValue::kNumWorkgroups, param->Type(), param->Declaration()->attributes); + entry_point.vertex_index_used |= ContainsBuiltin( + core::BuiltinValue::kVertexIndex, param->Type(), param->Declaration()->attributes); + entry_point.instance_index_used |= ContainsBuiltin( + core::BuiltinValue::kInstanceIndex, param->Type(), param->Declaration()->attributes); + entry_point.primitive_index_used |= ContainsBuiltin( + core::BuiltinValue::kPrimitiveIndex, param->Type(), param->Declaration()->attributes); + entry_point.subgroup_invocation_id_used |= + ContainsBuiltin(core::BuiltinValue::kSubgroupInvocationId, param->Type(), + param->Declaration()->attributes); + entry_point.subgroup_size_used |= ContainsBuiltin( + core::BuiltinValue::kSubgroupSize, param->Type(), param->Declaration()->attributes); + + if (entry_point.stage == PipelineStage::kFragment) { + entry_point.frag_position_used = ContainsBuiltin( + core::BuiltinValue::kPosition, param->Type(), param->Declaration()->attributes); + } + } + + if (!sem->ReturnType()->Is()) { + AddEntryPointInOutVariables("", "", sem->ReturnType(), func->return_type_attributes, + sem->ReturnLocation(), /* @color */ std::nullopt, + /* @blend_src */ std::nullopt, entry_point.output_variables); + + entry_point.output_sample_mask_used = ContainsBuiltin( + core::BuiltinValue::kSampleMask, sem->ReturnType(), func->return_type_attributes); + entry_point.frag_depth_used = ContainsBuiltin( + core::BuiltinValue::kFragDepth, sem->ReturnType(), func->return_type_attributes); + entry_point.clip_distances_size = GetClipDistancesBuiltinSize(sem->ReturnType()); + } + + for (auto* var : sem->TransitivelyReferencedGlobals()) { + auto* global = var->As(); + if (auto override_id = global->Attributes().override_id) { + entry_point.overrides.push_back(MkOverride(global, override_id.value())); + } + } + + const auto& texture_metadata = ComputeTextureMetadata(entry_point.name); + entry_point.has_texture_load_with_depth_texture = + texture_metadata.has_texture_load_with_depth_texture; + entry_point.has_depth_texture_with_non_comparison_sampler = + texture_metadata.has_depth_texture_with_non_comparison_sampler; + + entry_point.fine_derivative_builtin_used = UsesFineDerivatives(sem); + + return entry_point; +} + +EntryPoint Inspector::GetEntryPoint(const std::string& entry_point_name) { + auto* func = FindEntryPointByName(entry_point_name); + if (!func) { + return EntryPoint(); + } + return GetEntryPoint(func); +} + +std::vector Inspector::GetEntryPoints() { + std::vector result; + + for (auto* func : program_.AST().Functions()) { + if (!func->IsEntryPoint()) { + continue; + } + + result.push_back(GetEntryPoint(func)); + } + + return result; +} + +std::map Inspector::GetNamedOverrideIds() { + std::map result; + for (auto* var : program_.AST().GlobalVariables()) { + auto* global = program_.Sem().Get(var); + if (auto override_id = global->Attributes().override_id) { + auto name = var->name->symbol.Name(); + result[name] = override_id.value(); + } + } + return result; +} + +std::vector Inspector::GetResourceBindings(const std::string& entry_point) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + std::vector result; + auto* func_sem = program_.Sem().Get(func); + for (auto& global : func_sem->TransitivelyReferencedGlobals()) { + switch (global->AddressSpace()) { + // Resources cannot be in these address spaces. + case core::AddressSpace::kPrivate: + case core::AddressSpace::kFunction: + case core::AddressSpace::kWorkgroup: + case core::AddressSpace::kImmediate: + case core::AddressSpace::kPixelLocal: + case core::AddressSpace::kIn: + case core::AddressSpace::kOut: + case core::AddressSpace::kUndefined: + continue; + + case core::AddressSpace::kUniform: + case core::AddressSpace::kStorage: + result.push_back(ConvertBufferToResourceBinding(global)); + break; + case core::AddressSpace::kHandle: + result.push_back(ConvertHandleToResourceBinding(global)); + break; + } + } + + return result; +} + +std::vector Inspector::GetSamplerTextureUses(const std::string& entry_point) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + const auto& metadata = ComputeTextureMetadata(entry_point); + std::vector result = {metadata.sampling_pairs.begin(), + metadata.sampling_pairs.end()}; + + return result; +} + +std::vector Inspector::GetSamplerAndNonSamplerTextureUses( + const std::string& entry_point, + const BindingPoint& non_sampler_placeholder) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + // This function adds texture usages with a fake sampler binding point, only for builtins that + // don't use a sampler. Others are returned as usual. + std::vector result = GetSamplerTextureUses(entry_point); + + const auto& metadata = ComputeTextureMetadata(entry_point); + for (const auto& texture : metadata.textures_used_without_samplers) { + SamplerTexturePair new_pair; + new_pair.sampler_binding_point = non_sampler_placeholder; + new_pair.texture_binding_point = texture; + result.push_back(new_pair); + } + + return result; +} + +std::vector Inspector::GetTextureQueries( + const std::string& entry_point) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + const auto& metadata = ComputeTextureMetadata(entry_point); + + std::vector result; + for (const auto& texture : metadata.textures_with_num_levels) { + result.push_back({TextureQueryType::kTextureNumLevels, texture.group, texture.binding}); + } + for (const auto& texture : metadata.textures_with_num_samples) { + result.push_back({TextureQueryType::kTextureNumSamples, texture.group, texture.binding}); + } + + return result; +} + +const Inspector::EntryPointTextureMetadata& Inspector::ComputeTextureMetadata( + const std::string& entry_point) { + auto [entry, inserted] = texture_metadata_.emplace(entry_point, EntryPointTextureMetadata{}); + auto& metadata = entry->second; + if (!inserted) { + return metadata; + } + + Symbol entry_point_symbol = program_.Symbols().Get(entry_point); + auto& sem = program_.Sem(); + + using GlobalSet = UniqueVector; + + // Stores for each function parameter which globals are statically determined to be used as an + // argument to the function call. + Hashmap, 8> + globals_for_handle_parameters; + auto AddGlobalsAsParameter = [&](const sem::Function* fn, const sem::Parameter* param, + const GlobalSet* vars) { + auto& globals = globals_for_handle_parameters.GetOrAddZero(fn).GetOrAddZero(param); + for (const auto* var : *vars) { + globals.Add(var); + } + }; + + // Returns the set of globals for a handle argument. A scratch set is passed in to be used when + // the argument directly references a global so that a reference on the stack can be passed. + // TODO(343500108): Use std::span when we have C++20 + auto GetGlobalsForArgument = [&](const sem::Function* fn, const sem::ValueExpression* argument, + GlobalSet* scratch_global) -> const GlobalSet* { + TINT_ASSERT(scratch_global->IsEmpty()); + + // Some of the handles may come from binding_array using an indexing operation. In that case + // trace the usage of the binding_array instead. + if (auto* access = argument->As()) { + TINT_ASSERT(access->Object()->Type()->template Is()); + argument = access->Object(); + } + + // The handle param could come in a few different forms, either it's associated to a + // `GlobalVariable` or as a `Parameter`. Those are the more common case. With + // `texture_and_sampler_let` it can also come through a chain of let assignments, so we have + // to walk through any `LocalVariable` entries until we get to first non-`LocalVariable`. + // The last option is that as we walk up the let chain, we no longer find a `RootIdentifier` + // this can happen when a `getResource` is assigned into a `let`. In that case, we just + // bail out early and return an empty set as there _is no_ global handle argument. + auto* identifier = argument->RootIdentifier(); + + // With `texture_and_sampler_let` the variable maybe in a let and we need to trace the + // initializer of the let. + auto* local = identifier->As(); + while (local != nullptr) { + identifier = local->Initializer()->RootIdentifier(); + if (!identifier) { + return scratch_global; + } + local = identifier->As(); + } + + return tint::Switch( + identifier, + [&](const sem::GlobalVariable* global) { + scratch_global->Add(global); + return scratch_global; + }, + [&](const sem::Parameter* parameter) { + return &*(globals_for_handle_parameters.Get(fn)->Get(parameter)); + }, + TINT_ICE_ON_NO_MATCH); + }; + + // The actual logic to compute the relevant metadata when a builtin call is found. It gets the + // set of statically determined globals for the texture and sampler arguments. + auto RecordBuiltinCallMetadata = [&](const sem::Call* call, const sem::BuiltinFn* builtin, + const GlobalSet& textures, const GlobalSet& samplers) { + // Compute the statically used texture+sampler pairs. + for (const auto* sampler : samplers) { + auto sampler_binding_point = sampler->Attributes().binding_point.value(); + + for (const auto* texture : textures) { + auto texture_binding_point = texture->Attributes().binding_point.value(); + metadata.sampling_pairs.insert({sampler_binding_point, texture_binding_point}); + } + } + + // Also gather uses of non-storage textures that are used without a sampler + const auto* texture_type = + call->Arguments()[static_cast( + builtin->Signature().IndexOf(core::ParameterUsage::kTexture))] + ->Type(); + if (samplers.IsEmpty() && !texture_type->Is()) { + for (const auto* texture : textures) { + auto texture_binding_point = texture->Attributes().binding_point.value(); + metadata.textures_used_without_samplers.insert(texture_binding_point); + } + } + + bool uses_num_levels = false; + switch (builtin->Fn()) { + case wgsl::BuiltinFn::kTextureNumLevels: + uses_num_levels = true; + break; + + case wgsl::BuiltinFn::kTextureDimensions: + // When textureDimension takes more than one argument, one of them is a mip level + // that will get clamped using textureNumLevels. + uses_num_levels = call->Arguments().Length() > 1; + break; + + case wgsl::BuiltinFn::kTextureLoad: + // textureLoad uses textureNumLevels to clamp the level, unless the texture type + // doesn't support mipmapping. + uses_num_levels = !texture_type->IsAnyOf(); + metadata.has_texture_load_with_depth_texture |= + texture_type + ->IsAnyOf(); + break; + + case wgsl::BuiltinFn::kTextureSample: + case wgsl::BuiltinFn::kTextureSampleLevel: + case wgsl::BuiltinFn::kTextureGather: + metadata.has_depth_texture_with_non_comparison_sampler |= + texture_type + ->IsAnyOf(); + break; + + case wgsl::BuiltinFn::kTextureNumSamples: + for (const auto* texture : textures) { + auto texture_binding_point = texture->Attributes().binding_point.value(); + metadata.textures_with_num_samples.insert(texture_binding_point); + } + break; + + default: + break; + } + + if (uses_num_levels) { + for (const auto* texture : textures) { + auto texture_binding_point = texture->Attributes().binding_point.value(); + metadata.textures_with_num_levels.insert(texture_binding_point); + } + } + }; + + // Iterate the call graph in reverse topological order such that function callers come before + // their callee. + auto declarations = sem.Module()->DependencyOrderedDeclarations(); + for (auto rit = declarations.rbegin(); rit != declarations.rend(); rit++) { + auto* fn = sem.Get(*rit); + if ((fn == nullptr) || !fn->HasCallGraphEntryPoint(entry_point_symbol)) { + continue; + } + + for (auto* call : fn->DirectCalls()) { + tint::Switch( + call->Target(), + + // Propagate the used globals for handle parameters of function calls. + [&](const sem::Function* callee) { + for (size_t i = 0; i < call->Arguments().Length(); i++) { + auto parameter = sem.Get(callee->Declaration()->params[i]); + if (!parameter->Type()->IsHandle()) { + continue; + } + + // Handle parameter can only be identifiers. + GlobalSet scratch_global; + const auto* globals = + GetGlobalsForArgument(fn, call->Arguments()[i], &scratch_global); + AddGlobalsAsParameter(callee, parameter, globals); + } + }, + + [&](const sem::BuiltinFn* builtin) { + // Find sampler / texture parameters and skip over builtin calls without any. + const auto& signature = builtin->Signature(); + int texture_index = signature.IndexOf(core::ParameterUsage::kTexture); + int sampler_index = signature.IndexOf(core::ParameterUsage::kSampler); + + if (texture_index == -1) { + return; + } + + // A texture of `sem::Call` means we're dealing with a `getResource` or + // `hasResource` call. Skip it. + if (call->Arguments()[size_t(texture_index)]->Is()) { + return; + } + + // Compute the set of globals used for the texture/sampler parameter. + // It will either point to a GlobalSet on the stack when a global is used + // directly, or to the contents of globals_for_handle_parameters. + GlobalSet scratch_sampler_global; + const GlobalSet* sampler_globals = &scratch_sampler_global; + if (sampler_index != -1) { + sampler_globals = GetGlobalsForArgument( + fn, call->Arguments()[size_t(sampler_index)], &scratch_sampler_global); + } + + GlobalSet scratch_texture_global; + const GlobalSet* texture_globals = GetGlobalsForArgument( + fn, call->Arguments()[size_t(texture_index)], &scratch_texture_global); + + RecordBuiltinCallMetadata(call, builtin, *texture_globals, *sampler_globals); + }); + } + } + + return metadata; +} + +std::bitset Inspector::GetImmediateBlockInfo(const std::string& entry_point) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + auto* func_sem = program_.Sem().Get(func); + + const sem::GlobalVariable* immediate_var = nullptr; + for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) { + if (var->AddressSpace() == core::AddressSpace::kImmediate) { + immediate_var = var->As(); + break; + } + } + + if (!immediate_var) { + return {}; + } + + auto* mv = immediate_var->Type()->As(); + auto* type = mv->StoreType(); + + std::bitset accessible_slots; + + std::function mark_slots = + [&](const core::type::Type* t, uint32_t offset) { + tint::Switch( + t, + [&](const sem::Struct* str) { + for (auto* member : str->Members()) { + mark_slots(member->Type(), offset + member->Offset()); + } + }, + [&](const core::type::Matrix* mat) { + uint32_t col_stride = mat->ColumnStride(); + for (uint32_t i = 0; i < mat->Columns(); i++) { + mark_slots(mat->ColumnType(), offset + i * col_stride); + } + }, + [&](const core::type::Type* other) { + uint32_t s = other->Size(); + uint32_t start_slot = offset / kImmediateSlotSize; + uint32_t end_byte = offset + s; + uint32_t end_slot = (end_byte - 1) / kImmediateSlotSize; + for (uint32_t i = start_slot; i <= end_slot; i++) { + TINT_ASSERT(i < accessible_slots.size()); + accessible_slots[i] = true; + } + }); + }; + + mark_slots(type, 0); + + return accessible_slots; +} + +std::vector Inspector::GetUsedExtensionNames() { + auto& extensions = program_.Sem().Module()->Extensions(); + std::vector out; + out.reserve(extensions.Length()); + for (auto ext : extensions) { + out.push_back(tint::ToString(ext)); + } + return out; +} + +const ast::Function* Inspector::FindEntryPointByName(const std::string& name) { + auto* func = program_.AST().Functions().Find(program_.Symbols().Get(name)); + if (!func) { + diagnostics_.AddError(Source{}) << name << " was not found!"; + return nullptr; + } + + if (!func->IsEntryPoint()) { + diagnostics_.AddError(Source{}) << name << " is not an entry point!"; + return nullptr; + } + + return func; +} + +void Inspector::AddEntryPointInOutVariables(std::string name, + std::string variable_name, + const core::type::Type* type, + VectorRef attributes, + std::optional location, + std::optional color, + std::optional blend_src, + std::vector& variables) const { + // Skip builtins. + if (ast::HasAttribute(attributes)) { + return; + } + + auto* unwrapped_type = type->UnwrapRef(); + + if (auto* struct_ty = unwrapped_type->As()) { + // Recurse into members. + for (auto* member : struct_ty->Members()) { + AddEntryPointInOutVariables(name + "." + member->Name().Name(), member->Name().Name(), + member->Type(), member->Declaration()->attributes, + member->Attributes().location, member->Attributes().color, + member->Attributes().blend_src, variables); + } + return; + } + + // Base case: add the variable. + + StageVariable stage_variable; + stage_variable.name = name; + stage_variable.variable_name = variable_name; + std::tie(stage_variable.component_type, stage_variable.composition_type) = + CalculateComponentAndComposition(type); + + stage_variable.attributes.blend_src = blend_src; + stage_variable.attributes.location = location; + stage_variable.attributes.color = color; + + std::tie(stage_variable.interpolation_type, stage_variable.interpolation_sampling) = + CalculateInterpolationData(attributes); + + variables.push_back(stage_variable); +} + +bool Inspector::ContainsBuiltin(core::BuiltinValue builtin, + const core::type::Type* type, + VectorRef attributes) const { + auto* unwrapped_type = type->UnwrapRef(); + + if (auto* struct_ty = unwrapped_type->As()) { + // Recurse into members. + for (auto* member : struct_ty->Members()) { + if (ContainsBuiltin(builtin, member->Type(), member->Declaration()->attributes)) { + return true; + } + } + return false; + } + + // Base case: check for builtin + auto* builtin_declaration = ast::GetAttribute(attributes); + if (!builtin_declaration) { + return false; + } + return builtin_declaration->builtin == builtin; +} + +std::optional Inspector::GetClipDistancesBuiltinSize(const core::type::Type* type) const { + auto* unwrapped_type = type->UnwrapRef(); + + if (auto* struct_ty = unwrapped_type->As()) { + for (auto* member : struct_ty->Members()) { + if (ContainsBuiltin(core::BuiltinValue::kClipDistances, member->Type(), + member->Declaration()->attributes)) { + auto* array_type = member->Type()->As(); + TINT_ASSERT(array_type != nullptr) << "clip_distances is not an array"; + return array_type->ConstantCount(); + } + } + } + + return std::nullopt; +} + +std::tuple Inspector::CalculateInterpolationData( + VectorRef attributes) const { + auto* interpolation_attribute = ast::GetAttribute(attributes); + + if (!interpolation_attribute) { + return {InterpolationType::kPerspective, InterpolationSampling::kCenter}; + } + + auto ast_interpolation_type = interpolation_attribute->interpolation.type; + auto ast_sampling_type = interpolation_attribute->interpolation.sampling; + + if (ast_sampling_type == core::InterpolationSampling::kUndefined) { + if (ast_interpolation_type == core::InterpolationType::kFlat) { + ast_sampling_type = core::InterpolationSampling::kFirst; + } else { + ast_sampling_type = core::InterpolationSampling::kCenter; + } + } + + auto interpolation_type = InterpolationType::kUnknown; + switch (ast_interpolation_type) { + case core::InterpolationType::kPerspective: + interpolation_type = InterpolationType::kPerspective; + break; + case core::InterpolationType::kLinear: + interpolation_type = InterpolationType::kLinear; + break; + case core::InterpolationType::kFlat: + interpolation_type = InterpolationType::kFlat; + break; + case core::InterpolationType::kUndefined: + break; + } + + auto sampling_type = InterpolationSampling::kUnknown; + switch (ast_sampling_type) { + case core::InterpolationSampling::kUndefined: + sampling_type = InterpolationSampling::kNone; + break; + case core::InterpolationSampling::kCenter: + sampling_type = InterpolationSampling::kCenter; + break; + case core::InterpolationSampling::kCentroid: + sampling_type = InterpolationSampling::kCentroid; + break; + case core::InterpolationSampling::kSample: + sampling_type = InterpolationSampling::kSample; + break; + case core::InterpolationSampling::kFirst: + sampling_type = InterpolationSampling::kFirst; + break; + case core::InterpolationSampling::kEither: + sampling_type = InterpolationSampling::kEither; + break; + } + + return {interpolation_type, sampling_type}; +} + +uint32_t Inspector::ComputeWorkgroupStorageSize(const ast::Function* func) const { + uint32_t total_size = 0; + auto* func_sem = program_.Sem().Get(func); + for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) { + if (var->AddressSpace() == core::AddressSpace::kWorkgroup) { + auto* ty = var->Type()->UnwrapRef(); + uint32_t align = ty->Align(); + uint32_t size = ty->Size(); + + // This essentially matches std430 layout rules from GLSL, which are in + // turn specified as an upper bound for Vulkan layout sizing. Since D3D + // and Metal are even less specific, we assume Vulkan behavior as a + // good-enough approximation everywhere. + total_size += tint::RoundUp(16u, tint::RoundUp(align, size)); + } + } + + return total_size; +} + +uint32_t Inspector::ComputeImmediateDataSize(const ast::Function* func) const { + uint32_t size = 0; + auto* func_sem = program_.Sem().Get(func); + for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) { + if (var->AddressSpace() == core::AddressSpace::kImmediate) { + size += var->Type()->UnwrapRef()->Size(); + } + } + + return size; +} + +std::vector Inspector::ComputePixelLocalMemberTypes( + const ast::Function* func) const { + auto* func_sem = program_.Sem().Get(func); + for (const sem::Variable* var : func_sem->TransitivelyReferencedGlobals()) { + if (var->AddressSpace() != core::AddressSpace::kPixelLocal) { + continue; + } + + auto* str = var->Type()->UnwrapRef()->As(); + + std::vector types; + types.reserve(str->Members().Length()); + for (auto* member : str->Members()) { + PixelLocalMemberType type = Switch( + member->Type(), // + [&](const core::type::F32*) { return PixelLocalMemberType::kF32; }, + [&](const core::type::I32*) { return PixelLocalMemberType::kI32; }, + [&](const core::type::U32*) { return PixelLocalMemberType::kU32; }, // + TINT_ICE_ON_NO_MATCH); + types.push_back(type); + } + + return types; + } + + return {}; +} + +bool Inspector::UsesSubgroupMatrix(const sem::Function* func) const { + if (func->DirectlyUsedSubgroupMatrix()) { + return true; + } + for (auto& call : func->TransitivelyCalledFunctions()) { + if (call->DirectlyUsedSubgroupMatrix()) { + return true; + } + } + return false; +} + +std::vector Inspector::Overrides() { + std::vector results; + + for (auto* var : program_.AST().GlobalVariables()) { + auto* global = program_.Sem().Get(var); + if (!global || !global->Declaration()->Is()) { + continue; + } + + results.push_back(MkOverride(global, global->Attributes().override_id.value())); + } + return results; +} + +std::unordered_set Inspector::GetResourceTableInfo(const std::string& entry_point) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + auto& sem = program_.Sem(); + Symbol entry_point_symbol = program_.Symbols().Get(entry_point); + + std::unordered_set types; + + auto declarations = sem.Module()->DependencyOrderedDeclarations(); + for (auto rit = declarations.rbegin(); rit != declarations.rend(); rit++) { + auto* fn = sem.Get(*rit); + if ((fn == nullptr) || !fn->HasCallGraphEntryPoint(entry_point_symbol)) { + continue; + } + + for (auto* call : fn->DirectCalls()) { + tint::Switch( + call->Target(), // + [&](const sem::BuiltinFn* builtin) { + if (builtin->Fn() != wgsl::BuiltinFn::kHasResource && + builtin->Fn() != wgsl::BuiltinFn::kGetResource) { + return; + } + + auto* decl = call->Declaration(); + const auto* ident = decl->target->identifier->As(); + + TINT_ASSERT(ident); + TINT_ASSERT(ident->arguments.Length() == 1); + + auto* type_expr = sem.Get(ident->arguments[0])->As(); + TINT_ASSERT(type_expr); + + types.insert(core::type::TypeToResourceType(type_expr->Type())); + }); + } + } + + return types; +} + +} // namespace tint::inspector diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.h b/3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.h new file mode 100644 index 000000000..64025d939 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/inspector.h @@ -0,0 +1,241 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INSPECTOR_INSPECTOR_H_ +#define SRC_TINT_LANG_WGSL_INSPECTOR_INSPECTOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/api/common/override_id.h" + +#include "src/tint/api/common/resource_type.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/inspector/entry_point.h" +#include "src/tint/lang/wgsl/inspector/resource_binding.h" +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/sem/sampler_texture_pair.h" + +namespace tint::inspector { + +/// A temporary alias to sem::SamplerTexturePair. [DEPRECATED] +using SamplerTexturePair = sem::SamplerTexturePair; + +/// The maximum size of the immediate buffer in bytes. +constexpr size_t kMaxImmediateSize = 64; +/// The size of a single slot in the immediate buffer in bytes. +constexpr size_t kImmediateSlotSize = 4; +/// The number of slots in the immediate buffer. +constexpr size_t kImmediateSlotCount = kMaxImmediateSize / kImmediateSlotSize; + +/// Extracts information from a program +class Inspector { + public: + /// Constructor + /// @param program Shader program to extract information from. + explicit Inspector(const Program& program); + + /// Destructor + ~Inspector(); + + /// @returns error messages from the Inspector + std::string error() { return diagnostics_.Str(); } + /// @returns true if an error was encountered + bool has_error() const { return diagnostics_.ContainsErrors(); } + + /// @returns vector of entry point information + std::vector GetEntryPoints(); + + /// @param entry_point name of the entry point to get information about + /// @returns the entry point information + EntryPoint GetEntryPoint(const std::string& entry_point); + + /// @returns map of module-constant name to pipeline constant ID + std::map GetNamedOverrideIds(); + + /// @returns vector of all overrides + std::vector Overrides(); + + /// @param entry_point name of the entry point to get information about. + /// @returns vector of all types returned from any resource table calls. + std::unordered_set GetResourceTableInfo(const std::string& entry_point); + + /// @param entry_point name of the entry point to get information about. + /// @returns vector of all of the resource bindings. + std::vector GetResourceBindings(const std::string& entry_point); + + /// @param entry_point name of the entry point to get information about. + /// @returns vector of all of the sampler/texture sampling pairs that are used + /// by that entry point. + std::vector GetSamplerTextureUses(const std::string& entry_point); + + /// @param entry_point name of the entry point to get information about. + /// @param non_sampler_placeholder the sampler binding point placeholder to use for texture-only + /// access (e.g., textureLoad). + /// @returns vector of sampler/texture sampling pairs that are used by given entry point. + /// Contains all texture usages with and without a sampler. Note that storage textures are not + /// included. + std::vector GetSamplerAndNonSamplerTextureUses( + const std::string& entry_point, + const BindingPoint& non_sampler_placeholder); + + /// @param entry_point name of the entry point to get information about + /// @returns a bitset where the nth bit is true if the nth 4-byte slot of the immediate block + /// may be used by the entry point. Returns an empty bitset if the immediate block is not + /// referenced. + std::bitset GetImmediateBlockInfo(const std::string& entry_point); + + /// @returns vector of all valid extension names used by the program. There + /// will be no duplicated names in the returned vector even if an extension + /// is enabled multiple times. + std::vector GetUsedExtensionNames(); + + /// The information needed to be supplied. + enum class TextureQueryType : uint8_t { + /// Texture Num Levels + kTextureNumLevels, + /// Texture Num Samples + kTextureNumSamples, + }; + /// Information on level and sample calls by a given texture binding point + struct LevelSampleInfo { + /// The type of function + TextureQueryType type = TextureQueryType::kTextureNumLevels; + /// The group number + uint32_t group = 0; + /// The binding number + uint32_t binding = 0; + + /// Equality operator + /// @param rhs the LevelSampleInfo to compare against + /// @returns true if this LevelSampleInfo is equal to `rhs` + bool operator==(const LevelSampleInfo& rhs) const { + return this->type == rhs.type && this->group == rhs.group && + this->binding == rhs.binding; + } + + /// Inequality operator + /// @param rhs the LevelSampleInfo to compare against + /// @returns true if this LevelSampleInfo is not equal to `rhs` + bool operator!=(const LevelSampleInfo& rhs) const { return !(*this == rhs); } + }; + + /// @param ep the entry point to get the information for + /// @returns a vector of information for textures which call textureNumLevels and + /// textureNumSamples for backends which require additional support for those methods. Each + /// binding point will only be returned once regardless of the number of calls made. The + /// texture types for `textureNumSamples` is disjoint from the texture types in + /// `textureNumLevels` so the binding point will always be one or the other. + std::vector GetTextureQueries(const std::string& ep); + + private: + const Program& program_; + diag::List diagnostics_; + + struct EntryPointTextureMetadata { + std::unordered_set textures_used_without_samplers; + std::unordered_set textures_with_num_levels; + std::unordered_set textures_with_num_samples; + std::unordered_set sampling_pairs; + bool has_texture_load_with_depth_texture = false; + bool has_depth_texture_with_non_comparison_sampler = false; + }; + std::unordered_map texture_metadata_; + + /// Computes the texture metadata for `entry_point` and returns it. + const EntryPointTextureMetadata& ComputeTextureMetadata(const std::string& entry_point); + + /// @param name name of the entry point to find + /// @returns a pointer to the entry point if it exists, otherwise returns + /// nullptr and sets the error string. + const ast::Function* FindEntryPointByName(const std::string& name); + + /// Recursively add entry point IO variables. + /// If `type` is a struct, recurse into members, appending the member name. + /// Otherwise, add the variable unless it is a builtin. + /// @param name the name of the variable being added, including struct nested accessings. + /// @param variable_name the name of the variable being added + /// @param type the type of the variable + /// @param attributes the variable attributes + /// @param location the location attribute value if provided + /// @param color the color attribute value if provided + /// @param blend_src the blend_src attribute value if provided + /// @param variables the list to add the variables to + void AddEntryPointInOutVariables(std::string name, + std::string variable_name, + const core::type::Type* type, + VectorRef attributes, + std::optional location, + std::optional color, + std::optional blend_src, + std::vector& variables) const; + + /// Recursively determine if the type contains builtin. + /// If `type` is a struct, recurse into members to check for the attribute. + /// Otherwise, check `attributes` for the attribute. + bool ContainsBuiltin(core::BuiltinValue builtin, + const core::type::Type* type, + VectorRef attributes) const; + /// Get the array length of the builtin clip_distances when it is used. + /// @param type the type of the variable + /// @returns the array length of the builtin clip_distances or empty when it is not used + std::optional GetClipDistancesBuiltinSize(const core::type::Type* type) const; + + /// @param attributes attributes associated with the parameter or structure member + /// @returns the interpolation type and sampling modes for the value + std::tuple CalculateInterpolationData( + VectorRef attributes) const; + + /// @param func the root function of the callgraph to consider for the computation. + /// @returns the total size in bytes of all Workgroup storage-class storage accessed via func. + uint32_t ComputeWorkgroupStorageSize(const ast::Function* func) const; + + /// @param func the root function of the callgraph to consider for the computation. + /// @returns the total size in bytes of all immediate data variables accessed via func. + uint32_t ComputeImmediateDataSize(const ast::Function* func) const; + + /// @param func the root function of the callgraph to consider for the computation + /// @returns the list of member types for the `pixel_local` variable accessed via func, if any. + std::vector ComputePixelLocalMemberTypes(const ast::Function* func) const; + + /// @returns `true` if @p func uses any subgroup matrix types + bool UsesSubgroupMatrix(const sem::Function* func) const; + + /// @param func the function of the entry point. Must be non-nullptr and true for IsEntryPoint() + /// @returns the entry point information + EntryPoint GetEntryPoint(const tint::ast::Function* func); +}; + +} // namespace tint::inspector + +#endif // SRC_TINT_LANG_WGSL_INSPECTOR_INSPECTOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.cc b/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.cc new file mode 100644 index 000000000..a45f031af --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.cc @@ -0,0 +1,175 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/inspector/resource_binding.h" + +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/vector.h" + +namespace tint::inspector { + +ResourceBinding::TextureDimension TypeTextureDimensionToResourceBindingTextureDimension( + const core::type::TextureDimension& type_dim) { + switch (type_dim) { + case core::type::TextureDimension::k1d: + return ResourceBinding::TextureDimension::k1d; + case core::type::TextureDimension::k2d: + return ResourceBinding::TextureDimension::k2d; + case core::type::TextureDimension::k2dArray: + return ResourceBinding::TextureDimension::k2dArray; + case core::type::TextureDimension::k3d: + return ResourceBinding::TextureDimension::k3d; + case core::type::TextureDimension::kCube: + return ResourceBinding::TextureDimension::kCube; + case core::type::TextureDimension::kCubeArray: + return ResourceBinding::TextureDimension::kCubeArray; + case core::type::TextureDimension::kNone: + return ResourceBinding::TextureDimension::kNone; + } + return ResourceBinding::TextureDimension::kNone; +} + +ResourceBinding::SampledKind BaseTypeToSampledKind(const core::type::Type* base_type) { + if (!base_type) { + return ResourceBinding::SampledKind::kUnknown; + } + + if (auto* at = base_type->As()) { + base_type = at->ElemType(); + } else if (auto* mt = base_type->As()) { + base_type = mt->Type(); + } else if (auto* vt = base_type->As()) { + base_type = vt->Type(); + } + + if (base_type->Is()) { + return ResourceBinding::SampledKind::kFloat; + } else if (base_type->Is()) { + return ResourceBinding::SampledKind::kUInt; + } else if (base_type->Is()) { + return ResourceBinding::SampledKind::kSInt; + } else { + return ResourceBinding::SampledKind::kUnknown; + } +} + +ResourceBinding::TexelFormat TypeTexelFormatToResourceBindingTexelFormat( + const core::TexelFormat& image_format) { + switch (image_format) { + case core::TexelFormat::kR8Snorm: + return ResourceBinding::TexelFormat::kR8Snorm; + case core::TexelFormat::kR8Uint: + return ResourceBinding::TexelFormat::kR8Uint; + case core::TexelFormat::kR8Sint: + return ResourceBinding::TexelFormat::kR8Sint; + case core::TexelFormat::kRg8Unorm: + return ResourceBinding::TexelFormat::kRg8Unorm; + case core::TexelFormat::kRg8Snorm: + return ResourceBinding::TexelFormat::kRg8Snorm; + case core::TexelFormat::kRg8Uint: + return ResourceBinding::TexelFormat::kRg8Uint; + case core::TexelFormat::kRg8Sint: + return ResourceBinding::TexelFormat::kRg8Sint; + case core::TexelFormat::kR16Unorm: + return ResourceBinding::TexelFormat::kR16Unorm; + case core::TexelFormat::kR16Snorm: + return ResourceBinding::TexelFormat::kR16Snorm; + case core::TexelFormat::kR16Uint: + return ResourceBinding::TexelFormat::kR16Uint; + case core::TexelFormat::kR16Sint: + return ResourceBinding::TexelFormat::kR16Sint; + case core::TexelFormat::kR16Float: + return ResourceBinding::TexelFormat::kR16Float; + case core::TexelFormat::kRg16Unorm: + return ResourceBinding::TexelFormat::kRg16Unorm; + case core::TexelFormat::kRg16Snorm: + return ResourceBinding::TexelFormat::kRg16Snorm; + case core::TexelFormat::kRg16Uint: + return ResourceBinding::TexelFormat::kRg16Uint; + case core::TexelFormat::kRg16Sint: + return ResourceBinding::TexelFormat::kRg16Sint; + case core::TexelFormat::kRg16Float: + return ResourceBinding::TexelFormat::kRg16Float; + case core::TexelFormat::kRgb10A2Uint: + return ResourceBinding::TexelFormat::kRgb10A2Uint; + case core::TexelFormat::kRgb10A2Unorm: + return ResourceBinding::TexelFormat::kRgb10A2Unorm; + case core::TexelFormat::kRg11B10Ufloat: + return ResourceBinding::TexelFormat::kRg11B10Ufloat; + case core::TexelFormat::kBgra8Unorm: + return ResourceBinding::TexelFormat::kBgra8Unorm; + case core::TexelFormat::kR32Uint: + return ResourceBinding::TexelFormat::kR32Uint; + case core::TexelFormat::kR32Sint: + return ResourceBinding::TexelFormat::kR32Sint; + case core::TexelFormat::kR32Float: + return ResourceBinding::TexelFormat::kR32Float; + case core::TexelFormat::kRgba8Unorm: + return ResourceBinding::TexelFormat::kRgba8Unorm; + case core::TexelFormat::kRgba8Snorm: + return ResourceBinding::TexelFormat::kRgba8Snorm; + case core::TexelFormat::kRgba8Uint: + return ResourceBinding::TexelFormat::kRgba8Uint; + case core::TexelFormat::kRgba8Sint: + return ResourceBinding::TexelFormat::kRgba8Sint; + case core::TexelFormat::kRg32Uint: + return ResourceBinding::TexelFormat::kRg32Uint; + case core::TexelFormat::kRg32Sint: + return ResourceBinding::TexelFormat::kRg32Sint; + case core::TexelFormat::kRg32Float: + return ResourceBinding::TexelFormat::kRg32Float; + case core::TexelFormat::kRgba16Unorm: + return ResourceBinding::TexelFormat::kRgba16Unorm; + case core::TexelFormat::kRgba16Snorm: + return ResourceBinding::TexelFormat::kRgba16Snorm; + case core::TexelFormat::kRgba16Uint: + return ResourceBinding::TexelFormat::kRgba16Uint; + case core::TexelFormat::kRgba16Sint: + return ResourceBinding::TexelFormat::kRgba16Sint; + case core::TexelFormat::kRgba16Float: + return ResourceBinding::TexelFormat::kRgba16Float; + case core::TexelFormat::kRgba32Uint: + return ResourceBinding::TexelFormat::kRgba32Uint; + case core::TexelFormat::kRgba32Sint: + return ResourceBinding::TexelFormat::kRgba32Sint; + case core::TexelFormat::kRgba32Float: + return ResourceBinding::TexelFormat::kRgba32Float; + case core::TexelFormat::kR8Unorm: + return ResourceBinding::TexelFormat::kR8Unorm; + case core::TexelFormat::kUndefined: + return ResourceBinding::TexelFormat::kNone; + } + return ResourceBinding::TexelFormat::kNone; +} + +} // namespace tint::inspector diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.h b/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.h new file mode 100644 index 000000000..1c26a3666 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding.h @@ -0,0 +1,176 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INSPECTOR_RESOURCE_BINDING_H_ +#define SRC_TINT_LANG_WGSL_INSPECTOR_RESOURCE_BINDING_H_ + +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::inspector { + +/// Container for information about how a resource is bound +struct ResourceBinding { + /// The dimensionality of a texture + enum class TextureDimension : uint8_t { + /// 1 dimensional texture + k1d, + /// 2 dimensional texture + k2d, + /// 2 dimensional array texture + k2dArray, + /// 3 dimensional texture + k3d, + /// cube texture + kCube, + /// cube array texture + kCubeArray, + /// Invalid texture + kNone, + }; + + /// Component type of the texture's data. Same as the Sampled Type parameter + /// in SPIR-V OpTypeImage. + enum class SampledKind : uint8_t { kFloat, kUInt, kSInt, kUnknown }; + + /// Enumerator of texel image formats + enum class TexelFormat : uint8_t { + kR8Snorm, + kR8Uint, + kR8Sint, + kRg8Unorm, + kRg8Snorm, + kRg8Uint, + kRg8Sint, + kR16Unorm, + kR16Snorm, + kR16Uint, + kR16Sint, + kR16Float, + kRg16Unorm, + kRg16Snorm, + kRg16Uint, + kRg16Sint, + kRg16Float, + kBgra8Unorm, + kRgba8Unorm, + kRgba8Snorm, + kRgba8Uint, + kRgba8Sint, + kRgba16Unorm, + kRgba16Snorm, + kRgba16Uint, + kRgba16Sint, + kRgba16Float, + kR32Uint, + kR32Sint, + kR32Float, + kRg32Uint, + kRg32Sint, + kRg32Float, + kRgba32Uint, + kRgba32Sint, + kRgba32Float, + kR8Unorm, + kRgb10A2Uint, + kRgb10A2Unorm, + kRg11B10Ufloat, + kNone, + }; + + /// kXXX maps to entries returned by GetXXXResourceBindings call. + enum class ResourceType { + kUniformBuffer, + kStorageBuffer, + kReadOnlyStorageBuffer, + kSampler, + kComparisonSampler, + kSampledTexture, + kMultisampledTexture, + kWriteOnlyStorageTexture, + kReadOnlyStorageTexture, + kReadWriteStorageTexture, + kDepthTexture, + kDepthMultisampledTexture, + kExternalTexture, + kReadOnlyTexelBuffer, + kReadWriteTexelBuffer, + kInputAttachment, + }; + + /// Type of resource that is bound. + ResourceType resource_type; + /// Bind group the binding belongs + uint32_t bind_group; + /// Identifier to identify this binding within the bind group + uint32_t binding; + /// Input attachment index. Only available for input attachments. + uint32_t input_attachment_index; + /// Size for this binding, in bytes, if defined. + uint64_t size; + /// The array_size, if the binding is in a binding_array + std::optional array_size; + /// Size for this binding without trailing structure padding, in bytes, if + /// defined. + uint64_t size_no_padding; + /// Dimensionality of this binding, if defined. + TextureDimension dim; + /// Kind of data being sampled, if defined. + SampledKind sampled_kind; + /// Format of data, if defined. + TexelFormat image_format; + /// Variable name of the binding. + std::string variable_name; +}; + +/// Convert from internal core::type::TextureDimension to public +/// ResourceBinding::TextureDimension +/// @param type_dim internal value to convert from +/// @returns the publicly visible equivalent +ResourceBinding::TextureDimension TypeTextureDimensionToResourceBindingTextureDimension( + const core::type::TextureDimension& type_dim); + +/// Infer ResourceBinding::SampledKind for a given core::type::Type +/// @param base_type internal type to infer from +/// @returns the publicly visible equivalent +ResourceBinding::SampledKind BaseTypeToSampledKind(const core::type::Type* base_type); + +/// Convert from internal core::TexelFormat to public +/// ResourceBinding::TexelFormat +/// @param image_format internal value to convert from +/// @returns the publicly visible equivalent +ResourceBinding::TexelFormat TypeTexelFormatToResourceBindingTexelFormat( + const core::TexelFormat& image_format); + +} // namespace tint::inspector + +#endif // SRC_TINT_LANG_WGSL_INSPECTOR_RESOURCE_BINDING_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding_info.h b/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding_info.h new file mode 100644 index 000000000..9b99aa405 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/resource_binding_info.h @@ -0,0 +1,52 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INSPECTOR_RESOURCE_BINDING_INFO_H_ +#define SRC_TINT_LANG_WGSL_INSPECTOR_RESOURCE_BINDING_INFO_H_ + +#include +#include +#include + +#include "src/tint/api/common/resource_type.h" + +namespace tint::inspector { + +/// Container for information about how a resource is bound +struct ResourceBindingInfo { + /// Bind group the binding belongs + uint32_t group; + /// Identifier to identify this binding within the bind group + uint32_t binding; + + /// The types used with the binding array + std::vector type_info{}; +}; + +} // namespace tint::inspector + +#endif // SRC_TINT_LANG_WGSL_INSPECTOR_RESOURCE_BINDING_INFO_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.cc b/3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.cc new file mode 100644 index 000000000..cc8de5f57 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.cc @@ -0,0 +1,86 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/inspector/scalar.h" + +namespace tint::inspector { + +Scalar::Scalar() : type_(kNull) {} + +Scalar::Scalar(bool val) : type_(kBool) { + value_.b = val; +} + +Scalar::Scalar(uint32_t val) : type_(kU32) { + value_.u = val; +} + +Scalar::Scalar(int32_t val) : type_(kI32) { + value_.i = val; +} + +Scalar::Scalar(float val) : type_(kFloat) { + value_.f = val; +} + +bool Scalar::IsNull() const { + return type_ == kNull; +} + +bool Scalar::IsBool() const { + return type_ == kBool; +} + +bool Scalar::IsU32() const { + return type_ == kU32; +} + +bool Scalar::IsI32() const { + return type_ == kI32; +} + +bool Scalar::IsFloat() const { + return type_ == kFloat; +} + +bool Scalar::AsBool() const { + return value_.b; +} + +uint32_t Scalar::AsU32() const { + return value_.u; +} + +int32_t Scalar::AsI32() const { + return value_.i; +} + +float Scalar::AsFloat() const { + return value_.f; +} + +} // namespace tint::inspector diff --git a/3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.h b/3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.h new file mode 100644 index 000000000..535a34628 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/inspector/scalar.h @@ -0,0 +1,91 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INSPECTOR_SCALAR_H_ +#define SRC_TINT_LANG_WGSL_INSPECTOR_SCALAR_H_ + +#include + +namespace tint::inspector { + +/// Contains a literal scalar value +class Scalar { + public: + /// Null Constructor + Scalar(); + /// @param val literal scalar value to contain + explicit Scalar(bool val); + /// @param val literal scalar value to contain + explicit Scalar(uint32_t val); + /// @param val literal scalar value to contain + explicit Scalar(int32_t val); + /// @param val literal scalar value to contain + explicit Scalar(float val); + + /// @returns true if this is a null + bool IsNull() const; + /// @returns true if this is a bool + bool IsBool() const; + /// @returns true if this is a unsigned integer. + bool IsU32() const; + /// @returns true if this is a signed integer. + bool IsI32() const; + /// @returns true if this is a float. + bool IsFloat() const; + + /// @returns scalar value if bool, otherwise undefined behaviour. + bool AsBool() const; + /// @returns scalar value if unsigned integer, otherwise undefined behaviour. + uint32_t AsU32() const; + /// @returns scalar value if signed integer, otherwise undefined behaviour. + int32_t AsI32() const; + /// @returns scalar value if float, otherwise undefined behaviour. + float AsFloat() const; + + private: + typedef enum { + kNull, + kBool, + kU32, + kI32, + kFloat, + } Type; + + typedef union { + bool b; + uint32_t u; + int32_t i; + float f; + } Value; + + Type type_; + Value value_; +}; + +} // namespace tint::inspector + +#endif // SRC_TINT_LANG_WGSL_INSPECTOR_SCALAR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.cc b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.cc new file mode 100644 index 000000000..4e4619e29 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.cc @@ -0,0 +1,87 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/wgsl/intrinsic/ctor_conv.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include "src/tint/lang/wgsl/intrinsic/ctor_conv.h" + +namespace tint::wgsl::intrinsic { + +const char* str(CtorConv i) { + switch (i) { + case CtorConv::kNone: + return ""; + case CtorConv::kI32: + return "i32"; + case CtorConv::kU32: + return "u32"; + case CtorConv::kF32: + return "f32"; + case CtorConv::kF16: + return "f16"; + case CtorConv::kBool: + return "bool"; + case CtorConv::kVec2: + return "vec2"; + case CtorConv::kVec3: + return "vec3"; + case CtorConv::kVec4: + return "vec4"; + case CtorConv::kMat2x2: + return "mat2x2"; + case CtorConv::kMat2x3: + return "mat2x3"; + case CtorConv::kMat2x4: + return "mat2x4"; + case CtorConv::kMat3x2: + return "mat3x2"; + case CtorConv::kMat3x3: + return "mat3x3"; + case CtorConv::kMat3x4: + return "mat3x4"; + case CtorConv::kMat4x2: + return "mat4x2"; + case CtorConv::kMat4x3: + return "mat4x3"; + case CtorConv::kMat4x4: + return "mat4x4"; + } + return ""; +} + +} // namespace tint::wgsl::intrinsic + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.h b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.h new file mode 100644 index 000000000..4c568fb9b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/ctor_conv.h @@ -0,0 +1,129 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/wgsl/intrinsic/ctor_conv.h.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SRC_TINT_LANG_WGSL_INTRINSIC_CTOR_CONV_H_ +#define SRC_TINT_LANG_WGSL_INTRINSIC_CTOR_CONV_H_ + +// clang-format off + +#include + +#include "src/tint/utils/rtti/traits.h" + +namespace tint::wgsl::intrinsic { + +/// CtorConv is an enumerator of types that have a constructor or converter overload +/// declared in the intrinsic table. +enum class CtorConv : uint8_t { + kI32, + kU32, + kF32, + kF16, + kBool, + kVec2, + kVec3, + kVec4, + kMat2x2, + kMat2x3, + kMat2x4, + kMat3x2, + kMat3x3, + kMat3x4, + kMat4x2, + kMat4x3, + kMat4x4, + kNone, +}; + +/// @returns the name of the type. +const char* str(CtorConv i); + +/// Prints the CtorConv @p c to @p o +/// @param o the stream to write to +/// @param c the CtorConv +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, CtorConv c) { + return o << str(c); +} + +/// @param n the width of the vector +/// @return the CtorConv for a vector of width `n` +inline CtorConv VectorCtorConv(uint32_t n) { + switch (n) { + case 2: + return CtorConv::kVec2; + case 3: + return CtorConv::kVec3; + case 4: + return CtorConv::kVec4; + } + return CtorConv::kNone; +} + +/// @param c the number of columns in the matrix +/// @param r the number of rows in the matrix +/// @return the CtorConv for a matrix with `c` columns and `r` rows +inline CtorConv MatrixCtorConv(uint32_t c, uint32_t r) { + switch ((c - 2) * 3 + (r - 2)) { + case 0: + return CtorConv::kMat2x2; + case 1: + return CtorConv::kMat2x3; + case 2: + return CtorConv::kMat2x4; + case 3: + return CtorConv::kMat3x2; + case 4: + return CtorConv::kMat3x3; + case 5: + return CtorConv::kMat3x4; + case 6: + return CtorConv::kMat4x2; + case 7: + return CtorConv::kMat4x3; + case 8: + return CtorConv::kMat4x4; + } + return CtorConv::kNone; +} + +} // namespace tint::wgsl::intrinsic + +// clang-format on + +#endif // SRC_TINT_LANG_WGSL_INTRINSIC_CTOR_CONV_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/data.cc b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/data.cc new file mode 100644 index 000000000..f2362f7e7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/data.cc @@ -0,0 +1,15327 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +// File generated by 'tools/src/cmd/gen' using the template: +// src/tint/lang/wgsl/intrinsic/data.cc.tmpl +// +// To regenerate run: './tools/run gen' +// +// Do not modify this file directly +//////////////////////////////////////////////////////////////////////////////// + +// clang-format off + +#include +#include + +#include "src/tint/lang/core/intrinsic/type_matchers.h" +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/abstract_numeric.h" +#include "src/tint/lang/wgsl/intrinsic/dialect.h" +#include "src/tint/lang/wgsl/intrinsic/type_matchers.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::wgsl::intrinsic { + +using namespace tint::core::intrinsic; // NOLINT(build/namespaces) + +inline const core::type::AbstractFloat* BuildFa(intrinsic::MatchState& state, const core::type::Type*) { + return state.types.AFloat(); +} + +inline bool MatchFa(intrinsic::MatchState& state, const core::type::Type* ty) { + return (state.earliest_eval_stage <= core::EvaluationStage::kConstant) && + ty->IsAnyOf(); +} + +inline const core::type::AbstractInt* BuildIa(intrinsic::MatchState& state, const core::type::Type*) { + return state.types.AInt(); +} + +inline bool MatchIa(intrinsic::MatchState& state, const core::type::Type* ty) { + return (state.earliest_eval_stage <= core::EvaluationStage::kConstant) && + ty->IsAnyOf(); +} + +namespace { + +using ConstEvalFunctionIndex = tint::core::intrinsic::ConstEvalFunctionIndex; +using IntrinsicInfo = tint::core::intrinsic::IntrinsicInfo; +using MatcherIndicesIndex = tint::core::intrinsic::MatcherIndicesIndex; +using MatchState = tint::core::intrinsic::MatchState; +using Number = tint::core::intrinsic::Number; +using NumberMatcher = tint::core::intrinsic::NumberMatcher; +using NumberMatcherIndex = tint::core::intrinsic::NumberMatcherIndex; +using OverloadFlag = tint::core::intrinsic::OverloadFlag; +using OverloadFlags = tint::core::intrinsic::OverloadFlags; +using OverloadIndex = tint::core::intrinsic::OverloadIndex; +using OverloadInfo = tint::core::intrinsic::OverloadInfo; +using ParameterIndex = tint::core::intrinsic::ParameterIndex; +using ParameterInfo = tint::core::intrinsic::ParameterInfo; +using StringStream = tint::StringStream; +using TemplateIndex = tint::core::intrinsic::TemplateIndex; +using Type = tint::core::type::Type; +using TypeMatcher = tint::core::intrinsic::TypeMatcher; +using TypeMatcherIndex = tint::core::intrinsic::TypeMatcherIndex; + +template +using TemplateNumberMatcher = tint::core::intrinsic::TemplateNumberMatcher; + +template +using TemplateTypeMatcher = tint::core::intrinsic::TemplateTypeMatcher; + +/// TypeMatcher for 'type bool' +constexpr TypeMatcher kBoolMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchBool(state, ty)) { + return nullptr; + } + return BuildBool(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("bool"); + } +}; + + +/// TypeMatcher for 'type i8' +constexpr TypeMatcher kI8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchI8(state, ty)) { + return nullptr; + } + return BuildI8(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("i8"); + } +}; + + +/// TypeMatcher for 'type u8' +constexpr TypeMatcher kU8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchU8(state, ty)) { + return nullptr; + } + return BuildU8(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("u8"); + } +}; + + +/// TypeMatcher for 'type ia' +constexpr TypeMatcher kIaMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchIa(state, ty)) { + return nullptr; + } + return BuildIa(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("abstract-int"); + } +}; + + +/// TypeMatcher for 'type fa' +constexpr TypeMatcher kFaMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchFa(state, ty)) { + return nullptr; + } + return BuildFa(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("abstract-float"); + } +}; + + +/// TypeMatcher for 'type i32' +constexpr TypeMatcher kI32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchI32(state, ty)) { + return nullptr; + } + return BuildI32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("i32"); + } +}; + + +/// TypeMatcher for 'type u32' +constexpr TypeMatcher kU32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchU32(state, ty)) { + return nullptr; + } + return BuildU32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("u32"); + } +}; + + +/// TypeMatcher for 'type f32' +constexpr TypeMatcher kF32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchF32(state, ty)) { + return nullptr; + } + return BuildF32(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("f32"); + } +}; + + +/// TypeMatcher for 'type f16' +constexpr TypeMatcher kF16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchF16(state, ty)) { + return nullptr; + } + return BuildF16(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("f16"); + } +}; + + +/// TypeMatcher for 'type vec2' +constexpr TypeMatcher kVec2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec3' +constexpr TypeMatcher kVec3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec4' +constexpr TypeMatcher kVec4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchVec4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("vec4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x2' +constexpr TypeMatcher kMat2X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x3' +constexpr TypeMatcher kMat2X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat2x4' +constexpr TypeMatcher kMat2X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat2X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat2X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat2x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x2' +constexpr TypeMatcher kMat3X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x3' +constexpr TypeMatcher kMat3X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat3x4' +constexpr TypeMatcher kMat3X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat3X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat3X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat3x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x2' +constexpr TypeMatcher kMat4X2Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X2(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X2(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x2", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x3' +constexpr TypeMatcher kMat4X3Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X3(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X3(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x3", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat4x4' +constexpr TypeMatcher kMat4X4Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchMat4X4(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat4X4(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("mat4x4", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type vec' +constexpr TypeMatcher kVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("vec", N, "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type mat' +constexpr TypeMatcher kMatMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + Number M = Number::invalid; + const Type* T = nullptr; + if (!MatchMat(state, ty, N, M, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + M = state.Num(M); + if (!M.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildMat(state, ty, N, M, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText M; + state->PrintNum(M);StyledText T; + state->PrintType(T); + out << style::Type("mat", N, "x", M, "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type ptr' +constexpr TypeMatcher kPtrMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number A = Number::invalid; + if (!MatchPtr(state, ty, S, T, A)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildPtr(state, ty, S, T, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText A; + state->PrintNum(A); + out << style::Type("ptr", "<", S, ", ", T, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type ref' +constexpr TypeMatcher kRefMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number A = Number::invalid; + if (!MatchRef(state, ty, S, T, A)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildRef(state, ty, S, T, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText A; + state->PrintNum(A); + out << style::Type("ref", "<", S, ", ", T, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type atomic' +constexpr TypeMatcher kAtomicMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchAtomic(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildAtomic(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("atomic", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type runtime_array' +constexpr TypeMatcher kRuntimeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchRuntimeArray(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildRuntimeArray(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("array<", T, ">"); + } +}; + + +/// TypeMatcher for 'type array' +constexpr TypeMatcher kArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + Number N = Number::invalid; + if (!MatchArray(state, ty, T, N)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + return BuildArray(state, ty, T, N); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T);StyledText N; + state->PrintNum(N); + out << style::Type("array", "<", T, ", ", N, ">"); + } +}; + + +/// TypeMatcher for 'type binding_array' +constexpr TypeMatcher kBindingArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + Number N = Number::invalid; + if (!MatchBindingArray(state, ty, T, N)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + return BuildBindingArray(state, ty, T, N); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T);StyledText N; + state->PrintNum(N); + out << style::Type("binding_array", "<", T, ", ", N, ">"); + } +}; + + +/// TypeMatcher for 'type sampler' +constexpr TypeMatcher kSamplerMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchSampler(state, ty)) { + return nullptr; + } + return BuildSampler(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("sampler"); + } +}; + + +/// TypeMatcher for 'type sampler_comparison' +constexpr TypeMatcher kSamplerComparisonMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchSamplerComparison(state, ty)) { + return nullptr; + } + return BuildSamplerComparison(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("sampler_comparison"); + } +}; + + +/// TypeMatcher for 'type texture_1d' +constexpr TypeMatcher kTexture1DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture1D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture1D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_1d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_2d' +constexpr TypeMatcher kTexture2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture2D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture2D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_2d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_2d_array' +constexpr TypeMatcher kTexture2DArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture2DArray(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture2DArray(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_2d_array", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_3d' +constexpr TypeMatcher kTexture3DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTexture3D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTexture3D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_3d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_cube' +constexpr TypeMatcher kTextureCubeMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTextureCube(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTextureCube(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_cube", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_cube_array' +constexpr TypeMatcher kTextureCubeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTextureCubeArray(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTextureCubeArray(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_cube_array", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_multisampled_2d' +constexpr TypeMatcher kTextureMultisampled2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchTextureMultisampled2D(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildTextureMultisampled2D(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("texture_multisampled_2d", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type texture_depth_2d' +constexpr TypeMatcher kTextureDepth2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepth2D(state, ty)) { + return nullptr; + } + return BuildTextureDepth2D(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_2d"); + } +}; + + +/// TypeMatcher for 'type texture_depth_2d_array' +constexpr TypeMatcher kTextureDepth2DArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepth2DArray(state, ty)) { + return nullptr; + } + return BuildTextureDepth2DArray(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_2d_array"); + } +}; + + +/// TypeMatcher for 'type texture_depth_cube' +constexpr TypeMatcher kTextureDepthCubeMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepthCube(state, ty)) { + return nullptr; + } + return BuildTextureDepthCube(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_cube"); + } +}; + + +/// TypeMatcher for 'type texture_depth_cube_array' +constexpr TypeMatcher kTextureDepthCubeArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepthCubeArray(state, ty)) { + return nullptr; + } + return BuildTextureDepthCubeArray(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_cube_array"); + } +}; + + +/// TypeMatcher for 'type texture_depth_multisampled_2d' +constexpr TypeMatcher kTextureDepthMultisampled2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureDepthMultisampled2D(state, ty)) { + return nullptr; + } + return BuildTextureDepthMultisampled2D(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_depth_multisampled_2d"); + } +}; + + +/// TypeMatcher for 'type texture_storage_1d' +constexpr TypeMatcher kTextureStorage1DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage1D(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage1D(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_1d", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_storage_2d' +constexpr TypeMatcher kTextureStorage2DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage2D(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage2D(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_2d", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_storage_2d_array' +constexpr TypeMatcher kTextureStorage2DArrayMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage2DArray(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage2DArray(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_2d_array", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_storage_3d' +constexpr TypeMatcher kTextureStorage3DMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTextureStorage3D(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTextureStorage3D(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texture_storage_3d", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type texture_external' +constexpr TypeMatcher kTextureExternalMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchTextureExternal(state, ty)) { + return nullptr; + } + return BuildTextureExternal(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("texture_external"); + } +}; + + +/// TypeMatcher for 'type texel_buffer' +constexpr TypeMatcher kTexelBufferMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number F = Number::invalid; + Number A = Number::invalid; + if (!MatchTexelBuffer(state, ty, F, A)) { + return nullptr; + } + F = state.Num(F); + if (!F.IsValid()) { + return nullptr; + } + A = state.Num(A); + if (!A.IsValid()) { + return nullptr; + } + return BuildTexelBuffer(state, ty, F, A); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText F; + state->PrintNum(F);StyledText A; + state->PrintNum(A); + out << style::Type("texel_buffer", "<", F, ", ", A, ">"); + } +}; + + +/// TypeMatcher for 'type input_attachment' +constexpr TypeMatcher kInputAttachmentMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchInputAttachment(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildInputAttachment(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("input_attachment", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type __modf_result' +constexpr TypeMatcher kModfResultMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchModfResult(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildModfResult(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("__modf_result_", T); + } +}; + + +/// TypeMatcher for 'type __modf_result_vec' +constexpr TypeMatcher kModfResultVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchModfResultVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildModfResultVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("__modf_result_vec", N, "_", T); + } +}; + + +/// TypeMatcher for 'type __frexp_result' +constexpr TypeMatcher kFrexpResultMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchFrexpResult(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildFrexpResult(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("__frexp_result_", T); + } +}; + + +/// TypeMatcher for 'type __frexp_result_vec' +constexpr TypeMatcher kFrexpResultVecMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + const Type* T = nullptr; + if (!MatchFrexpResultVec(state, ty, N, T)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildFrexpResultVec(state, ty, N, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N);StyledText T; + state->PrintType(T); + out << style::Type("__frexp_result_vec", N, "_", T); + } +}; + + +/// TypeMatcher for 'type __atomic_compare_exchange_result' +constexpr TypeMatcher kAtomicCompareExchangeResultMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + const Type* T = nullptr; + if (!MatchAtomicCompareExchangeResult(state, ty, T)) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + return BuildAtomicCompareExchangeResult(state, ty, T); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText T; + state->PrintType(T); + out << style::Type("__atomic_compare_exchange_result", "<", T, ">"); + } +}; + + +/// TypeMatcher for 'type subgroup_matrix' +constexpr TypeMatcher kSubgroupMatrixMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number S = Number::invalid; + const Type* T = nullptr; + Number C = Number::invalid; + Number R = Number::invalid; + if (!MatchSubgroupMatrix(state, ty, S, T, C, R)) { + return nullptr; + } + S = state.Num(S); + if (!S.IsValid()) { + return nullptr; + } + T = state.Type(T); + if (T == nullptr) { + return nullptr; + } + C = state.Num(C); + if (!C.IsValid()) { + return nullptr; + } + R = state.Num(R); + if (!R.IsValid()) { + return nullptr; + } + return BuildSubgroupMatrix(state, ty, S, T, C, R); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText S; + state->PrintNum(S);StyledText T; + state->PrintType(T);StyledText C; + state->PrintNum(C);StyledText R; + state->PrintNum(R); + out << style::Type("subgroup_matrix", "<", S, ", ", T, ", ", C, ", ", R, ">"); + } +}; + + +/// TypeMatcher for 'type unsized_buffer' +constexpr TypeMatcher kUnsizedBufferMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchUnsizedBuffer(state, ty)) { + return nullptr; + } + return BuildUnsizedBuffer(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("buffer"); + } +}; + + +/// TypeMatcher for 'type buffer' +constexpr TypeMatcher kBufferMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + Number N = Number::invalid; + if (!MatchBuffer(state, ty, N)) { + return nullptr; + } + N = state.Num(N); + if (!N.IsValid()) { + return nullptr; + } + return BuildBuffer(state, ty, N); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) {StyledText N; + state->PrintNum(N); + out << style::Type("buffer", "<", N, ">"); + } +}; + + +/// TypeMatcher for 'type __constructible' +constexpr TypeMatcher kConstructibleMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (!MatchConstructible(state, ty)) { + return nullptr; + } + return BuildConstructible(state, ty); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { + out << style::Type("any concrete constructible type"); + } +}; + + +/// TypeMatcher for 'match scalar' +constexpr TypeMatcher kScalarMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kFaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match concrete_scalar' +constexpr TypeMatcher kConcreteScalarMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_f32' +constexpr TypeMatcher kScalarNoF32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kFaMatcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_f16' +constexpr TypeMatcher kScalarNoF16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kFaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_i32' +constexpr TypeMatcher kScalarNoI32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kFaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_u32' +constexpr TypeMatcher kScalarNoU32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchBool(state, ty)) { + return BuildBool(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kFaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kBoolMatcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match scalar_no_bool' +constexpr TypeMatcher kScalarNoBoolMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kFaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fia_fiu32_f16' +constexpr TypeMatcher kFiaFiu32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kFaMatcher.print(nullptr, out); out << style::Plain(", "); kIaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fia_fi32_f16' +constexpr TypeMatcher kFiaFi32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kFaMatcher.print(nullptr, out); out << style::Plain(", "); kIaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fia_fiu32' +constexpr TypeMatcher kFiaFiu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kFaMatcher.print(nullptr, out); out << style::Plain(", "); kIaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fa_f32' +constexpr TypeMatcher kFaF32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kFaMatcher.print(nullptr, out); out << style::Plain(" or "); kF32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fa_f32_f16' +constexpr TypeMatcher kFaF32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchFa(state, ty)) { + return BuildFa(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kFaMatcher.print(nullptr, out); out << style::Plain(", "); kF32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match ia_iu32' +constexpr TypeMatcher kIaIu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match ia_i32' +constexpr TypeMatcher kIaI32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchIa(state, ty)) { + return BuildIa(state, ty); + } + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kIaMatcher.print(nullptr, out); out << style::Plain(" or "); kI32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fiu32_f16' +constexpr TypeMatcher kFiu32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fiu32' +constexpr TypeMatcher kFiu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fi32_f16' +constexpr TypeMatcher kFi32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match fi32' +constexpr TypeMatcher kFi32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(" or "); kI32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match f32_f16' +constexpr TypeMatcher kF32F16Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(" or "); kF16Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu32' +constexpr TypeMatcher kIu32Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(" or "); kU32Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu32_iu8' +constexpr TypeMatcher kIu32Iu8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(", "); kI8Matcher.print(nullptr, out); out << style::Plain(" or "); kU8Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match iu8' +constexpr TypeMatcher kIu8Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kI8Matcher.print(nullptr, out); out << style::Plain(" or "); kU8Matcher.print(nullptr, out);} +}; + +/// TypeMatcher for 'match subgroup_matrix_elements' +constexpr TypeMatcher kSubgroupMatrixElementsMatcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { + if (MatchI32(state, ty)) { + return BuildI32(state, ty); + } + if (MatchU32(state, ty)) { + return BuildU32(state, ty); + } + if (MatchF32(state, ty)) { + return BuildF32(state, ty); + } + if (MatchF16(state, ty)) { + return BuildF16(state, ty); + } + if (MatchU8(state, ty)) { + return BuildU8(state, ty); + } + if (MatchI8(state, ty)) { + return BuildI8(state, ty); + } + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. + kF32Matcher.print(nullptr, out); out << style::Plain(", "); kF16Matcher.print(nullptr, out); out << style::Plain(", "); kU32Matcher.print(nullptr, out); out << style::Plain(", "); kI32Matcher.print(nullptr, out); out << style::Plain(", "); kU8Matcher.print(nullptr, out); out << style::Plain(" or "); kI8Matcher.print(nullptr, out);} +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_left' +constexpr NumberMatcher kSubgroupMatrixKindLeftMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kLeft)) { + return Number(static_cast(core::SubgroupMatrixKind::kLeft)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("left"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_right' +constexpr NumberMatcher kSubgroupMatrixKindRightMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kRight)) { + return Number(static_cast(core::SubgroupMatrixKind::kRight)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("right"); + } +}; + +/// EnumMatcher for 'match subgroup_matrix_kind_result' +constexpr NumberMatcher kSubgroupMatrixKindResultMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::SubgroupMatrixKind::kResult)) { + return Number(static_cast(core::SubgroupMatrixKind::kResult)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("result"); + } +}; + +/// EnumMatcher for 'match f32_texel_format' +constexpr NumberMatcher kF32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Unorm: + case core::TexelFormat::kR8Snorm: + case core::TexelFormat::kRg8Unorm: + case core::TexelFormat::kRg8Snorm: + case core::TexelFormat::kBgra8Unorm: + case core::TexelFormat::kRgba8Unorm: + case core::TexelFormat::kRgba8Snorm: + case core::TexelFormat::kR16Unorm: + case core::TexelFormat::kR16Snorm: + case core::TexelFormat::kRg16Unorm: + case core::TexelFormat::kRg16Snorm: + case core::TexelFormat::kRgba16Unorm: + case core::TexelFormat::kRgba16Snorm: + case core::TexelFormat::kR16Float: + case core::TexelFormat::kRg16Float: + case core::TexelFormat::kRgba16Float: + case core::TexelFormat::kR32Float: + case core::TexelFormat::kRg32Float: + case core::TexelFormat::kRgba32Float: + case core::TexelFormat::kRgb10A2Unorm: + case core::TexelFormat::kRg11B10Ufloat: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8unorm")<< style::Plain(", ") << style::Enum("r8snorm")<< style::Plain(", ") << style::Enum("rg8unorm")<< style::Plain(", ") << style::Enum("rg8snorm")<< style::Plain(", ") << style::Enum("bgra8unorm")<< style::Plain(", ") << style::Enum("rgba8unorm")<< style::Plain(", ") << style::Enum("rgba8snorm")<< style::Plain(", ") << style::Enum("r16unorm")<< style::Plain(", ") << style::Enum("r16snorm")<< style::Plain(", ") << style::Enum("rg16unorm")<< style::Plain(", ") << style::Enum("rg16snorm")<< style::Plain(", ") << style::Enum("rgba16unorm")<< style::Plain(", ") << style::Enum("rgba16snorm")<< style::Plain(", ") << style::Enum("r16float")<< style::Plain(", ") << style::Enum("rg16float")<< style::Plain(", ") << style::Enum("rgba16float")<< style::Plain(", ") << style::Enum("r32float")<< style::Plain(", ") << style::Enum("rg32float")<< style::Plain(", ") << style::Enum("rgba32float")<< style::Plain(", ") << style::Enum("rgb10a2unorm")<< style::Plain(" or ") << style::Enum("rg11b10ufloat"); + } +}; + +/// EnumMatcher for 'match i32_texel_format' +constexpr NumberMatcher kI32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Sint: + case core::TexelFormat::kRg8Sint: + case core::TexelFormat::kRgba8Sint: + case core::TexelFormat::kR16Sint: + case core::TexelFormat::kRg16Sint: + case core::TexelFormat::kRgba16Sint: + case core::TexelFormat::kR32Sint: + case core::TexelFormat::kRg32Sint: + case core::TexelFormat::kRgba32Sint: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8sint")<< style::Plain(", ") << style::Enum("rg8sint")<< style::Plain(", ") << style::Enum("rgba8sint")<< style::Plain(", ") << style::Enum("r16sint")<< style::Plain(", ") << style::Enum("rg16sint")<< style::Plain(", ") << style::Enum("rgba16sint")<< style::Plain(", ") << style::Enum("r32sint")<< style::Plain(", ") << style::Enum("rg32sint")<< style::Plain(" or ") << style::Enum("rgba32sint"); + } +}; + +/// EnumMatcher for 'match u32_texel_format' +constexpr NumberMatcher kU32TexelFormatMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::TexelFormat::kR8Uint: + case core::TexelFormat::kRg8Uint: + case core::TexelFormat::kR16Uint: + case core::TexelFormat::kRg16Uint: + case core::TexelFormat::kRgba8Uint: + case core::TexelFormat::kRgba16Uint: + case core::TexelFormat::kR32Uint: + case core::TexelFormat::kRg32Uint: + case core::TexelFormat::kRgba32Uint: + case core::TexelFormat::kRgb10A2Uint: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("r8uint")<< style::Plain(", ") << style::Enum("rg8uint")<< style::Plain(", ") << style::Enum("r16uint")<< style::Plain(", ") << style::Enum("rg16uint")<< style::Plain(", ") << style::Enum("rgba8uint")<< style::Plain(", ") << style::Enum("rgba16uint")<< style::Plain(", ") << style::Enum("r32uint")<< style::Plain(", ") << style::Enum("rg32uint")<< style::Plain(", ") << style::Enum("rgba32uint")<< style::Plain(" or ") << style::Enum("rgb10a2uint"); + } +}; + +/// EnumMatcher for 'match read' +constexpr NumberMatcher kReadMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kRead)) { + return Number(static_cast(core::Access::kRead)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read"); + } +}; + +/// EnumMatcher for 'match write' +constexpr NumberMatcher kWriteMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kWrite)) { + return Number(static_cast(core::Access::kWrite)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("write"); + } +}; + +/// EnumMatcher for 'match read_write' +constexpr NumberMatcher kReadWriteMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::Access::kReadWrite)) { + return Number(static_cast(core::Access::kReadWrite)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match readable' +constexpr NumberMatcher kReadableMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::Access::kRead: + case core::Access::kReadWrite: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("read")<< style::Plain(" or ") << style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match writable' +constexpr NumberMatcher kWritableMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::Access::kWrite: + case core::Access::kReadWrite: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("write")<< style::Plain(" or ") << style::Enum("read_write"); + } +}; + +/// EnumMatcher for 'match function_private_workgroup' +constexpr NumberMatcher kFunctionPrivateWorkgroupMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kFunction: + case core::AddressSpace::kPrivate: + case core::AddressSpace::kWorkgroup: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("function")<< style::Plain(", ") << style::Enum("private")<< style::Plain(" or ") << style::Enum("workgroup"); + } +}; + +/// EnumMatcher for 'match workgroup_or_storage' +constexpr NumberMatcher kWorkgroupOrStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kWorkgroup: + case core::AddressSpace::kStorage: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("workgroup")<< style::Plain(" or ") << style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match storage' +constexpr NumberMatcher kStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::AddressSpace::kStorage)) { + return Number(static_cast(core::AddressSpace::kStorage)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("storage"); + } +}; + +/// EnumMatcher for 'match workgroup' +constexpr NumberMatcher kWorkgroupMatcher { +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast(core::AddressSpace::kWorkgroup)) { + return Number(static_cast(core::AddressSpace::kWorkgroup)); + } + return Number::invalid; + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("workgroup"); + } +}; + +/// EnumMatcher for 'match uniform_or_storage' +constexpr NumberMatcher kUniformOrStorageMatcher { +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast(number.Value())) { + case core::AddressSpace::kUniform: + case core::AddressSpace::kStorage: + return number; + default: + return Number::invalid; + } + }, +/* print */ [](MatchState*, StyledText& out) { + out<< style::Enum("uniform")<< style::Plain(" or ") << style::Enum("storage"); + } +}; + +/// Type and number matchers + +/// The template types, types, and type matchers +constexpr TypeMatcher kTypeMatchers[] = { + /* [0] */ TemplateTypeMatcher<0>::matcher, + /* [1] */ TemplateTypeMatcher<1>::matcher, + /* [2] */ TemplateTypeMatcher<2>::matcher, + /* [3] */ TemplateTypeMatcher<3>::matcher, + /* [4] */ TemplateTypeMatcher<4>::matcher, + /* [5] */ TemplateTypeMatcher<5>::matcher, + /* [6] */ kBoolMatcher, + /* [7] */ kI8Matcher, + /* [8] */ kU8Matcher, + /* [9] */ kIaMatcher, + /* [10] */ kFaMatcher, + /* [11] */ kI32Matcher, + /* [12] */ kU32Matcher, + /* [13] */ kF32Matcher, + /* [14] */ kF16Matcher, + /* [15] */ kVec2Matcher, + /* [16] */ kVec3Matcher, + /* [17] */ kVec4Matcher, + /* [18] */ kMat2X2Matcher, + /* [19] */ kMat2X3Matcher, + /* [20] */ kMat2X4Matcher, + /* [21] */ kMat3X2Matcher, + /* [22] */ kMat3X3Matcher, + /* [23] */ kMat3X4Matcher, + /* [24] */ kMat4X2Matcher, + /* [25] */ kMat4X3Matcher, + /* [26] */ kMat4X4Matcher, + /* [27] */ kVecMatcher, + /* [28] */ kMatMatcher, + /* [29] */ kPtrMatcher, + /* [30] */ kRefMatcher, + /* [31] */ kAtomicMatcher, + /* [32] */ kRuntimeArrayMatcher, + /* [33] */ kArrayMatcher, + /* [34] */ kBindingArrayMatcher, + /* [35] */ kSamplerMatcher, + /* [36] */ kSamplerComparisonMatcher, + /* [37] */ kTexture1DMatcher, + /* [38] */ kTexture2DMatcher, + /* [39] */ kTexture2DArrayMatcher, + /* [40] */ kTexture3DMatcher, + /* [41] */ kTextureCubeMatcher, + /* [42] */ kTextureCubeArrayMatcher, + /* [43] */ kTextureMultisampled2DMatcher, + /* [44] */ kTextureDepth2DMatcher, + /* [45] */ kTextureDepth2DArrayMatcher, + /* [46] */ kTextureDepthCubeMatcher, + /* [47] */ kTextureDepthCubeArrayMatcher, + /* [48] */ kTextureDepthMultisampled2DMatcher, + /* [49] */ kTextureStorage1DMatcher, + /* [50] */ kTextureStorage2DMatcher, + /* [51] */ kTextureStorage2DArrayMatcher, + /* [52] */ kTextureStorage3DMatcher, + /* [53] */ kTextureExternalMatcher, + /* [54] */ kTexelBufferMatcher, + /* [55] */ kInputAttachmentMatcher, + /* [56] */ kModfResultMatcher, + /* [57] */ kModfResultVecMatcher, + /* [58] */ kFrexpResultMatcher, + /* [59] */ kFrexpResultVecMatcher, + /* [60] */ kAtomicCompareExchangeResultMatcher, + /* [61] */ kSubgroupMatrixMatcher, + /* [62] */ kUnsizedBufferMatcher, + /* [63] */ kBufferMatcher, + /* [64] */ kConstructibleMatcher, + /* [65] */ kScalarMatcher, + /* [66] */ kConcreteScalarMatcher, + /* [67] */ kScalarNoF32Matcher, + /* [68] */ kScalarNoF16Matcher, + /* [69] */ kScalarNoI32Matcher, + /* [70] */ kScalarNoU32Matcher, + /* [71] */ kScalarNoBoolMatcher, + /* [72] */ kFiaFiu32F16Matcher, + /* [73] */ kFiaFi32F16Matcher, + /* [74] */ kFiaFiu32Matcher, + /* [75] */ kFaF32Matcher, + /* [76] */ kFaF32F16Matcher, + /* [77] */ kIaIu32Matcher, + /* [78] */ kIaI32Matcher, + /* [79] */ kFiu32F16Matcher, + /* [80] */ kFiu32Matcher, + /* [81] */ kFi32F16Matcher, + /* [82] */ kFi32Matcher, + /* [83] */ kF32F16Matcher, + /* [84] */ kIu32Matcher, + /* [85] */ kIu32Iu8Matcher, + /* [86] */ kIu8Matcher, + /* [87] */ kSubgroupMatrixElementsMatcher, +}; + +/// The template numbers, and number matchers +constexpr NumberMatcher kNumberMatchers[] = { + /* [0] */ TemplateNumberMatcher<0>::matcher, + /* [1] */ TemplateNumberMatcher<1>::matcher, + /* [2] */ TemplateNumberMatcher<2>::matcher, + /* [3] */ TemplateNumberMatcher<3>::matcher, + /* [4] */ TemplateNumberMatcher<4>::matcher, + /* [5] */ TemplateNumberMatcher<5>::matcher, + /* [6] */ kSubgroupMatrixKindLeftMatcher, + /* [7] */ kSubgroupMatrixKindRightMatcher, + /* [8] */ kSubgroupMatrixKindResultMatcher, + /* [9] */ kF32TexelFormatMatcher, + /* [10] */ kI32TexelFormatMatcher, + /* [11] */ kU32TexelFormatMatcher, + /* [12] */ kReadMatcher, + /* [13] */ kWriteMatcher, + /* [14] */ kReadWriteMatcher, + /* [15] */ kReadableMatcher, + /* [16] */ kWritableMatcher, + /* [17] */ kFunctionPrivateWorkgroupMatcher, + /* [18] */ kWorkgroupOrStorageMatcher, + /* [19] */ kStorageMatcher, + /* [20] */ kWorkgroupMatcher, + /* [21] */ kUniformOrStorageMatcher, +}; + +constexpr MatcherIndex kMatcherIndices[] = { + /* [0] */ MatcherIndex(29), + /* [1] */ MatcherIndex(18), + /* [2] */ MatcherIndex(33), + /* [3] */ MatcherIndex(2), + /* [4] */ MatcherIndex(5), + /* [5] */ MatcherIndex(15), + /* [6] */ MatcherIndex(14), + /* [7] */ MatcherIndex(29), + /* [8] */ MatcherIndex(18), + /* [9] */ MatcherIndex(33), + /* [10] */ MatcherIndex(11), + /* [11] */ MatcherIndex(5), + /* [12] */ MatcherIndex(15), + /* [13] */ MatcherIndex(80), + /* [14] */ MatcherIndex(29), + /* [15] */ MatcherIndex(18), + /* [16] */ MatcherIndex(33), + /* [17] */ MatcherIndex(12), + /* [18] */ MatcherIndex(5), + /* [19] */ MatcherIndex(15), + /* [20] */ MatcherIndex(1), + /* [21] */ MatcherIndex(29), + /* [22] */ MatcherIndex(18), + /* [23] */ MatcherIndex(33), + /* [24] */ MatcherIndex(1), + /* [25] */ MatcherIndex(4), + /* [26] */ MatcherIndex(16), + /* [27] */ MatcherIndex(0), + /* [28] */ MatcherIndex(29), + /* [29] */ MatcherIndex(18), + /* [30] */ MatcherIndex(33), + /* [31] */ MatcherIndex(11), + /* [32] */ MatcherIndex(4), + /* [33] */ MatcherIndex(16), + /* [34] */ MatcherIndex(12), + /* [35] */ MatcherIndex(29), + /* [36] */ MatcherIndex(18), + /* [37] */ MatcherIndex(33), + /* [38] */ MatcherIndex(12), + /* [39] */ MatcherIndex(4), + /* [40] */ MatcherIndex(16), + /* [41] */ MatcherIndex(13), + /* [42] */ MatcherIndex(29), + /* [43] */ MatcherIndex(19), + /* [44] */ MatcherIndex(32), + /* [45] */ MatcherIndex(0), + /* [46] */ MatcherIndex(1), + /* [47] */ MatcherIndex(29), + /* [48] */ MatcherIndex(20), + /* [49] */ MatcherIndex(31), + /* [50] */ MatcherIndex(0), + /* [51] */ MatcherIndex(14), + /* [52] */ MatcherIndex(29), + /* [53] */ MatcherIndex(1), + /* [54] */ MatcherIndex(31), + /* [55] */ MatcherIndex(0), + /* [56] */ MatcherIndex(14), + /* [57] */ MatcherIndex(61), + /* [58] */ MatcherIndex(1), + /* [59] */ MatcherIndex(2), + /* [60] */ MatcherIndex(3), + /* [61] */ MatcherIndex(4), + /* [62] */ MatcherIndex(29), + /* [63] */ MatcherIndex(19), + /* [64] */ MatcherIndex(32), + /* [65] */ MatcherIndex(2), + /* [66] */ MatcherIndex(15), + /* [67] */ MatcherIndex(13), + /* [68] */ MatcherIndex(29), + /* [69] */ MatcherIndex(19), + /* [70] */ MatcherIndex(32), + /* [71] */ MatcherIndex(11), + /* [72] */ MatcherIndex(15), + /* [73] */ MatcherIndex(12), + /* [74] */ MatcherIndex(29), + /* [75] */ MatcherIndex(19), + /* [76] */ MatcherIndex(32), + /* [77] */ MatcherIndex(12), + /* [78] */ MatcherIndex(15), + /* [79] */ MatcherIndex(11), + /* [80] */ MatcherIndex(29), + /* [81] */ MatcherIndex(19), + /* [82] */ MatcherIndex(32), + /* [83] */ MatcherIndex(1), + /* [84] */ MatcherIndex(16), + /* [85] */ MatcherIndex(11), + /* [86] */ MatcherIndex(61), + /* [87] */ MatcherIndex(0), + /* [88] */ MatcherIndex(1), + /* [89] */ MatcherIndex(2), + /* [90] */ MatcherIndex(3), + /* [91] */ MatcherIndex(29), + /* [92] */ MatcherIndex(19), + /* [93] */ MatcherIndex(32), + /* [94] */ MatcherIndex(11), + /* [95] */ MatcherIndex(16), + /* [96] */ MatcherIndex(1), + /* [97] */ MatcherIndex(29), + /* [98] */ MatcherIndex(19), + /* [99] */ MatcherIndex(32), + /* [100] */ MatcherIndex(12), + /* [101] */ MatcherIndex(16), + /* [102] */ MatcherIndex(9), + /* [103] */ MatcherIndex(61), + /* [104] */ MatcherIndex(8), + /* [105] */ MatcherIndex(0), + /* [106] */ MatcherIndex(2), + /* [107] */ MatcherIndex(3), + /* [108] */ MatcherIndex(61), + /* [109] */ MatcherIndex(6), + /* [110] */ MatcherIndex(1), + /* [111] */ MatcherIndex(4), + /* [112] */ MatcherIndex(3), + /* [113] */ MatcherIndex(61), + /* [114] */ MatcherIndex(7), + /* [115] */ MatcherIndex(1), + /* [116] */ MatcherIndex(2), + /* [117] */ MatcherIndex(4), + /* [118] */ MatcherIndex(61), + /* [119] */ MatcherIndex(8), + /* [120] */ MatcherIndex(1), + /* [121] */ MatcherIndex(2), + /* [122] */ MatcherIndex(3), + /* [123] */ MatcherIndex(61), + /* [124] */ MatcherIndex(6), + /* [125] */ MatcherIndex(0), + /* [126] */ MatcherIndex(4), + /* [127] */ MatcherIndex(3), + /* [128] */ MatcherIndex(61), + /* [129] */ MatcherIndex(7), + /* [130] */ MatcherIndex(0), + /* [131] */ MatcherIndex(2), + /* [132] */ MatcherIndex(4), + /* [133] */ MatcherIndex(61), + /* [134] */ MatcherIndex(0), + /* [135] */ MatcherIndex(7), + /* [136] */ MatcherIndex(1), + /* [137] */ MatcherIndex(2), + /* [138] */ MatcherIndex(61), + /* [139] */ MatcherIndex(0), + /* [140] */ MatcherIndex(8), + /* [141] */ MatcherIndex(1), + /* [142] */ MatcherIndex(2), + /* [143] */ MatcherIndex(29), + /* [144] */ MatcherIndex(2), + /* [145] */ MatcherIndex(63), + /* [146] */ MatcherIndex(3), + /* [147] */ MatcherIndex(1), + /* [148] */ MatcherIndex(29), + /* [149] */ MatcherIndex(1), + /* [150] */ MatcherIndex(63), + /* [151] */ MatcherIndex(2), + /* [152] */ MatcherIndex(0), + /* [153] */ MatcherIndex(28), + /* [154] */ MatcherIndex(0), + /* [155] */ MatcherIndex(0), + /* [156] */ MatcherIndex(1), + /* [157] */ MatcherIndex(28), + /* [158] */ MatcherIndex(1), + /* [159] */ MatcherIndex(0), + /* [160] */ MatcherIndex(2), + /* [161] */ MatcherIndex(28), + /* [162] */ MatcherIndex(0), + /* [163] */ MatcherIndex(1), + /* [164] */ MatcherIndex(2), + /* [165] */ MatcherIndex(29), + /* [166] */ MatcherIndex(20), + /* [167] */ MatcherIndex(0), + /* [168] */ MatcherIndex(14), + /* [169] */ MatcherIndex(29), + /* [170] */ MatcherIndex(2), + /* [171] */ MatcherIndex(0), + /* [172] */ MatcherIndex(1), + /* [173] */ MatcherIndex(29), + /* [174] */ MatcherIndex(2), + /* [175] */ MatcherIndex(62), + /* [176] */ MatcherIndex(1), + /* [177] */ MatcherIndex(29), + /* [178] */ MatcherIndex(1), + /* [179] */ MatcherIndex(62), + /* [180] */ MatcherIndex(0), + /* [181] */ MatcherIndex(29), + /* [182] */ MatcherIndex(0), + /* [183] */ MatcherIndex(1), + /* [184] */ MatcherIndex(2), + /* [185] */ MatcherIndex(30), + /* [186] */ MatcherIndex(0), + /* [187] */ MatcherIndex(1), + /* [188] */ MatcherIndex(2), + /* [189] */ MatcherIndex(28), + /* [190] */ MatcherIndex(1), + /* [191] */ MatcherIndex(2), + /* [192] */ MatcherIndex(0), + /* [193] */ MatcherIndex(28), + /* [194] */ MatcherIndex(2), + /* [195] */ MatcherIndex(3), + /* [196] */ MatcherIndex(0), + /* [197] */ MatcherIndex(28), + /* [198] */ MatcherIndex(1), + /* [199] */ MatcherIndex(3), + /* [200] */ MatcherIndex(0), + /* [201] */ MatcherIndex(28), + /* [202] */ MatcherIndex(2), + /* [203] */ MatcherIndex(1), + /* [204] */ MatcherIndex(0), + /* [205] */ MatcherIndex(27), + /* [206] */ MatcherIndex(0), + /* [207] */ MatcherIndex(1), + /* [208] */ MatcherIndex(27), + /* [209] */ MatcherIndex(0), + /* [210] */ MatcherIndex(6), + /* [211] */ MatcherIndex(27), + /* [212] */ MatcherIndex(1), + /* [213] */ MatcherIndex(0), + /* [214] */ MatcherIndex(27), + /* [215] */ MatcherIndex(1), + /* [216] */ MatcherIndex(80), + /* [217] */ MatcherIndex(27), + /* [218] */ MatcherIndex(1), + /* [219] */ MatcherIndex(2), + /* [220] */ MatcherIndex(27), + /* [221] */ MatcherIndex(1), + /* [222] */ MatcherIndex(14), + /* [223] */ MatcherIndex(27), + /* [224] */ MatcherIndex(1), + /* [225] */ MatcherIndex(12), + /* [226] */ MatcherIndex(27), + /* [227] */ MatcherIndex(1), + /* [228] */ MatcherIndex(9), + /* [229] */ MatcherIndex(27), + /* [230] */ MatcherIndex(0), + /* [231] */ MatcherIndex(13), + /* [232] */ MatcherIndex(59), + /* [233] */ MatcherIndex(0), + /* [234] */ MatcherIndex(1), + /* [235] */ MatcherIndex(27), + /* [236] */ MatcherIndex(0), + /* [237] */ MatcherIndex(2), + /* [238] */ MatcherIndex(57), + /* [239] */ MatcherIndex(0), + /* [240] */ MatcherIndex(1), + /* [241] */ MatcherIndex(49), + /* [242] */ MatcherIndex(0), + /* [243] */ MatcherIndex(1), + /* [244] */ MatcherIndex(50), + /* [245] */ MatcherIndex(0), + /* [246] */ MatcherIndex(1), + /* [247] */ MatcherIndex(51), + /* [248] */ MatcherIndex(0), + /* [249] */ MatcherIndex(1), + /* [250] */ MatcherIndex(52), + /* [251] */ MatcherIndex(0), + /* [252] */ MatcherIndex(1), + /* [253] */ MatcherIndex(54), + /* [254] */ MatcherIndex(0), + /* [255] */ MatcherIndex(1), + /* [256] */ MatcherIndex(49), + /* [257] */ MatcherIndex(1), + /* [258] */ MatcherIndex(2), + /* [259] */ MatcherIndex(50), + /* [260] */ MatcherIndex(1), + /* [261] */ MatcherIndex(2), + /* [262] */ MatcherIndex(51), + /* [263] */ MatcherIndex(1), + /* [264] */ MatcherIndex(2), + /* [265] */ MatcherIndex(52), + /* [266] */ MatcherIndex(1), + /* [267] */ MatcherIndex(2), + /* [268] */ MatcherIndex(54), + /* [269] */ MatcherIndex(1), + /* [270] */ MatcherIndex(2), + /* [271] */ MatcherIndex(27), + /* [272] */ MatcherIndex(2), + /* [273] */ MatcherIndex(0), + /* [274] */ MatcherIndex(27), + /* [275] */ MatcherIndex(1), + /* [276] */ MatcherIndex(6), + /* [277] */ MatcherIndex(17), + /* [278] */ MatcherIndex(14), + /* [279] */ MatcherIndex(58), + /* [280] */ MatcherIndex(0), + /* [281] */ MatcherIndex(56), + /* [282] */ MatcherIndex(0), + /* [283] */ MatcherIndex(17), + /* [284] */ MatcherIndex(13), + /* [285] */ MatcherIndex(17), + /* [286] */ MatcherIndex(11), + /* [287] */ MatcherIndex(17), + /* [288] */ MatcherIndex(12), + /* [289] */ MatcherIndex(37), + /* [290] */ MatcherIndex(0), + /* [291] */ MatcherIndex(38), + /* [292] */ MatcherIndex(0), + /* [293] */ MatcherIndex(39), + /* [294] */ MatcherIndex(0), + /* [295] */ MatcherIndex(40), + /* [296] */ MatcherIndex(0), + /* [297] */ MatcherIndex(41), + /* [298] */ MatcherIndex(0), + /* [299] */ MatcherIndex(42), + /* [300] */ MatcherIndex(0), + /* [301] */ MatcherIndex(43), + /* [302] */ MatcherIndex(0), + /* [303] */ MatcherIndex(17), + /* [304] */ MatcherIndex(0), + /* [305] */ MatcherIndex(37), + /* [306] */ MatcherIndex(13), + /* [307] */ MatcherIndex(38), + /* [308] */ MatcherIndex(13), + /* [309] */ MatcherIndex(39), + /* [310] */ MatcherIndex(13), + /* [311] */ MatcherIndex(40), + /* [312] */ MatcherIndex(13), + /* [313] */ MatcherIndex(41), + /* [314] */ MatcherIndex(13), + /* [315] */ MatcherIndex(42), + /* [316] */ MatcherIndex(13), + /* [317] */ MatcherIndex(15), + /* [318] */ MatcherIndex(0), + /* [319] */ MatcherIndex(55), + /* [320] */ MatcherIndex(0), + /* [321] */ MatcherIndex(60), + /* [322] */ MatcherIndex(0), + /* [323] */ MatcherIndex(37), + /* [324] */ MatcherIndex(1), + /* [325] */ MatcherIndex(38), + /* [326] */ MatcherIndex(1), + /* [327] */ MatcherIndex(39), + /* [328] */ MatcherIndex(1), + /* [329] */ MatcherIndex(40), + /* [330] */ MatcherIndex(1), + /* [331] */ MatcherIndex(41), + /* [332] */ MatcherIndex(1), + /* [333] */ MatcherIndex(42), + /* [334] */ MatcherIndex(1), + /* [335] */ MatcherIndex(43), + /* [336] */ MatcherIndex(1), + /* [337] */ MatcherIndex(15), + /* [338] */ MatcherIndex(9), + /* [339] */ MatcherIndex(17), + /* [340] */ MatcherIndex(9), + /* [341] */ MatcherIndex(17), + /* [342] */ MatcherIndex(1), + /* [343] */ MatcherIndex(18), + /* [344] */ MatcherIndex(0), + /* [345] */ MatcherIndex(18), + /* [346] */ MatcherIndex(13), + /* [347] */ MatcherIndex(18), + /* [348] */ MatcherIndex(14), + /* [349] */ MatcherIndex(19), + /* [350] */ MatcherIndex(0), + /* [351] */ MatcherIndex(19), + /* [352] */ MatcherIndex(13), + /* [353] */ MatcherIndex(19), + /* [354] */ MatcherIndex(14), + /* [355] */ MatcherIndex(20), + /* [356] */ MatcherIndex(13), + /* [357] */ MatcherIndex(20), + /* [358] */ MatcherIndex(14), + /* [359] */ MatcherIndex(21), + /* [360] */ MatcherIndex(0), + /* [361] */ MatcherIndex(21), + /* [362] */ MatcherIndex(13), + /* [363] */ MatcherIndex(21), + /* [364] */ MatcherIndex(14), + /* [365] */ MatcherIndex(22), + /* [366] */ MatcherIndex(0), + /* [367] */ MatcherIndex(22), + /* [368] */ MatcherIndex(13), + /* [369] */ MatcherIndex(22), + /* [370] */ MatcherIndex(14), + /* [371] */ MatcherIndex(23), + /* [372] */ MatcherIndex(0), + /* [373] */ MatcherIndex(23), + /* [374] */ MatcherIndex(13), + /* [375] */ MatcherIndex(23), + /* [376] */ MatcherIndex(14), + /* [377] */ MatcherIndex(24), + /* [378] */ MatcherIndex(0), + /* [379] */ MatcherIndex(24), + /* [380] */ MatcherIndex(13), + /* [381] */ MatcherIndex(24), + /* [382] */ MatcherIndex(14), + /* [383] */ MatcherIndex(25), + /* [384] */ MatcherIndex(0), + /* [385] */ MatcherIndex(25), + /* [386] */ MatcherIndex(13), + /* [387] */ MatcherIndex(25), + /* [388] */ MatcherIndex(14), + /* [389] */ MatcherIndex(26), + /* [390] */ MatcherIndex(0), + /* [391] */ MatcherIndex(26), + /* [392] */ MatcherIndex(13), + /* [393] */ MatcherIndex(26), + /* [394] */ MatcherIndex(14), + /* [395] */ MatcherIndex(72), + /* [396] */ MatcherIndex(76), + /* [397] */ MatcherIndex(84), + /* [398] */ MatcherIndex(78), + /* [399] */ MatcherIndex(65), + /* [400] */ MatcherIndex(73), + /* [401] */ MatcherIndex(64), + /* [402] */ MatcherIndex(44), + /* [403] */ MatcherIndex(45), + /* [404] */ MatcherIndex(46), + /* [405] */ MatcherIndex(47), + /* [406] */ MatcherIndex(48), + /* [407] */ MatcherIndex(53), + /* [408] */ MatcherIndex(35), + /* [409] */ MatcherIndex(36), + /* [410] */ MatcherIndex(10), + /* [411] */ MatcherIndex(79), + /* [412] */ MatcherIndex(83), + /* [413] */ MatcherIndex(85), + /* [414] */ MatcherIndex(86), + /* [415] */ MatcherIndex(66), + /* [416] */ MatcherIndex(77), + /* [417] */ MatcherIndex(69), + /* [418] */ MatcherIndex(70), + /* [419] */ MatcherIndex(67), + /* [420] */ MatcherIndex(68), + /* [421] */ MatcherIndex(71), +}; + +static_assert(MatcherIndicesIndex::CanIndex(kMatcherIndices), + "MatcherIndicesIndex is not large enough to index kMatcherIndices"); + +constexpr ParameterInfo kParameters[] = { + { + /* [0] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(52), + }, + { + /* [1] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [2] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [3] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [4] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [5] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [6] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [7] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [8] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [9] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [10] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [11] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [12] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [13] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [14] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [15] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [16] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [17] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [18] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [19] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(309), + }, + { + /* [20] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [21] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [22] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [23] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [24] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [25] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [26] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [27] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(293), + }, + { + /* [28] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [29] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [30] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [31] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [32] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(403), + }, + { + /* [33] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(409), + }, + { + /* [34] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [35] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [36] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [37] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [38] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(309), + }, + { + /* [39] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [40] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [41] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [42] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [43] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [44] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(307), + }, + { + /* [45] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [46] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [47] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [48] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [49] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [50] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(311), + }, + { + /* [51] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [52] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [53] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [54] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [55] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(84), + }, + { + /* [56] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(315), + }, + { + /* [57] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [58] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [59] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [60] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [61] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [62] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(309), + }, + { + /* [63] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [64] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [65] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [66] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [67] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [68] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(403), + }, + { + /* [69] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [70] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [71] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [72] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [73] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [74] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [75] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(291), + }, + { + /* [76] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [77] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [78] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [79] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [80] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(299), + }, + { + /* [81] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [82] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [83] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [84] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(403), + }, + { + /* [85] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [86] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [87] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [88] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [89] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [90] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(409), + }, + { + /* [91] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [92] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [93] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [94] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(405), + }, + { + /* [95] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(409), + }, + { + /* [96] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [97] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [98] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [99] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(309), + }, + { + /* [100] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [101] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [102] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [103] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [104] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(307), + }, + { + /* [105] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [106] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [107] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [108] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [109] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(311), + }, + { + /* [110] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [111] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [112] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [113] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(84), + }, + { + /* [114] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(315), + }, + { + /* [115] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [116] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [117] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [118] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [119] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(313), + }, + { + /* [120] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [121] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [122] */ + /* usage */ core::ParameterUsage::kDdx, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [123] */ + /* usage */ core::ParameterUsage::kDdy, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [124] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(307), + }, + { + /* [125] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [126] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [127] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [128] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [129] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(311), + }, + { + /* [130] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [131] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [132] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [133] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(84), + }, + { + /* [134] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(315), + }, + { + /* [135] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [136] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [137] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [138] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [139] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [140] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [141] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [142] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [143] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [144] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(405), + }, + { + /* [145] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [146] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [147] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [148] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [149] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(80), + }, + { + /* [150] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [151] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [152] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [153] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [154] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(21), + }, + { + /* [155] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [156] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [157] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [158] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [159] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(91), + }, + { + /* [160] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [161] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [162] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [163] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [164] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(97), + }, + { + /* [165] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [166] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [167] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [168] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [169] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(28), + }, + { + /* [170] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [171] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [172] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [173] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [174] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(35), + }, + { + /* [175] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [176] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [177] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [178] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [179] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [180] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [181] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [182] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [183] */ + /* usage */ core::ParameterUsage::kComponent, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [184] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(297), + }, + { + /* [185] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [186] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [187] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [188] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [189] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [190] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [191] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(404), + }, + { + /* [192] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(409), + }, + { + /* [193] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [194] */ + /* usage */ core::ParameterUsage::kDepthRef, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [195] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(307), + }, + { + /* [196] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [197] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [198] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(78), + }, + { + /* [199] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(311), + }, + { + /* [200] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [201] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [202] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(84), + }, + { + /* [203] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(313), + }, + { + /* [204] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [205] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [206] */ + /* usage */ core::ParameterUsage::kBias, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [207] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(305), + }, + { + /* [208] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [209] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [210] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [211] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(313), + }, + { + /* [212] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [213] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [214] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [215] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(404), + }, + { + /* [216] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [217] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(40), + }, + { + /* [218] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [219] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(262), + }, + { + /* [220] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [221] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(60), + }, + { + /* [222] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(283), + }, + { + /* [223] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(262), + }, + { + /* [224] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [225] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(60), + }, + { + /* [226] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(285), + }, + { + /* [227] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(262), + }, + { + /* [228] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [229] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(60), + }, + { + /* [230] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [231] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(293), + }, + { + /* [232] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [233] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [234] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(60), + }, + { + /* [235] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(403), + }, + { + /* [236] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [237] */ + /* usage */ core::ParameterUsage::kArrayIndex, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [238] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [239] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(62), + }, + { + /* [240] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [241] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [242] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [243] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(0), + }, + { + /* [244] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [245] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [246] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [247] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(68), + }, + { + /* [248] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [249] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [250] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [251] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(74), + }, + { + /* [252] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [253] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [254] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [255] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(7), + }, + { + /* [256] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [257] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [258] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [259] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(14), + }, + { + /* [260] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [261] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [262] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [263] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [264] */ + /* usage */ core::ParameterUsage::kY, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [265] */ + /* usage */ core::ParameterUsage::kZ, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [266] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [267] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [268] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [269] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [270] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [271] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [272] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [273] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [274] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [275] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(303), + }, + { + /* [276] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(303), + }, + { + /* [277] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(303), + }, + { + /* [278] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(303), + }, + { + /* [279] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(211), + }, + { + /* [280] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(211), + }, + { + /* [281] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(211), + }, + { + /* [282] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [283] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [284] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [285] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [286] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [287] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [288] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [289] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [290] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(109), + }, + { + /* [291] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [292] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [293] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(208), + }, + { + /* [294] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(208), + }, + { + /* [295] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(407), + }, + { + /* [296] */ + /* usage */ core::ParameterUsage::kSampler, + /* matcher_indices */ MatcherIndicesIndex(408), + }, + { + /* [297] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [298] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(256), + }, + { + /* [299] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [300] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(283), + }, + { + /* [301] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(259), + }, + { + /* [302] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [303] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(283), + }, + { + /* [304] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(265), + }, + { + /* [305] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [306] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(283), + }, + { + /* [307] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(268), + }, + { + /* [308] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [309] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(283), + }, + { + /* [310] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(256), + }, + { + /* [311] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [312] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(285), + }, + { + /* [313] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(259), + }, + { + /* [314] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [315] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(285), + }, + { + /* [316] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(265), + }, + { + /* [317] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [318] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(285), + }, + { + /* [319] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(268), + }, + { + /* [320] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [321] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(285), + }, + { + /* [322] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(256), + }, + { + /* [323] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [324] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [325] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(259), + }, + { + /* [326] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [327] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [328] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(265), + }, + { + /* [329] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [330] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [331] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(268), + }, + { + /* [332] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [333] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [334] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(289), + }, + { + /* [335] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [336] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [337] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(291), + }, + { + /* [338] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [339] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [340] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(295), + }, + { + /* [341] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(95), + }, + { + /* [342] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [343] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(301), + }, + { + /* [344] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [345] */ + /* usage */ core::ParameterUsage::kSampleIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [346] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [347] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [348] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [349] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(406), + }, + { + /* [350] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [351] */ + /* usage */ core::ParameterUsage::kSampleIndex, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [352] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(123), + }, + { + /* [353] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(128), + }, + { + /* [354] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(118), + }, + { + /* [355] */ + /* usage */ core::ParameterUsage::kXy, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [356] */ + /* usage */ core::ParameterUsage::kZ, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [357] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [358] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [359] */ + /* usage */ core::ParameterUsage::kYz, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [360] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [361] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [362] */ + /* usage */ core::ParameterUsage::kY, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [363] */ + /* usage */ core::ParameterUsage::kZw, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [364] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [365] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [366] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [367] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(235), + }, + { + /* [368] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(289), + }, + { + /* [369] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [370] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(291), + }, + { + /* [371] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [372] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(293), + }, + { + /* [373] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [374] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(295), + }, + { + /* [375] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [376] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(297), + }, + { + /* [377] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [378] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(299), + }, + { + /* [379] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [380] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(402), + }, + { + /* [381] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [382] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(403), + }, + { + /* [383] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [384] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(404), + }, + { + /* [385] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [386] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(405), + }, + { + /* [387] */ + /* usage */ core::ParameterUsage::kLevel, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [388] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(407), + }, + { + /* [389] */ + /* usage */ core::ParameterUsage::kCoords, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [390] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [391] */ + /* usage */ core::ParameterUsage::kSourceLaneIndex, + /* matcher_indices */ MatcherIndicesIndex(397), + }, + { + /* [392] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [393] */ + /* usage */ core::ParameterUsage::kSourceLaneIndex, + /* matcher_indices */ MatcherIndicesIndex(397), + }, + { + /* [394] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [395] */ + /* usage */ core::ParameterUsage::kMask, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [396] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [397] */ + /* usage */ core::ParameterUsage::kMask, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [398] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [399] */ + /* usage */ core::ParameterUsage::kDelta, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [400] */ + /* usage */ core::ParameterUsage::kValue, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [401] */ + /* usage */ core::ParameterUsage::kDelta, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [402] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [403] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(397), + }, + { + /* [404] */ + /* usage */ core::ParameterUsage::kE, + /* matcher_indices */ MatcherIndicesIndex(205), + }, + { + /* [405] */ + /* usage */ core::ParameterUsage::kId, + /* matcher_indices */ MatcherIndicesIndex(397), + }, + { + /* [406] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(108), + }, + { + /* [407] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(113), + }, + { + /* [408] */ + /* usage */ core::ParameterUsage::kM, + /* matcher_indices */ MatcherIndicesIndex(86), + }, + { + /* [409] */ + /* usage */ core::ParameterUsage::kS, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [410] */ + /* usage */ core::ParameterUsage::kM, + /* matcher_indices */ MatcherIndicesIndex(133), + }, + { + /* [411] */ + /* usage */ core::ParameterUsage::kS, + /* matcher_indices */ MatcherIndicesIndex(10), + }, + { + /* [412] */ + /* usage */ core::ParameterUsage::kM, + /* matcher_indices */ MatcherIndicesIndex(138), + }, + { + /* [413] */ + /* usage */ core::ParameterUsage::kS, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [414] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(143), + }, + { + /* [415] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [416] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(143), + }, + { + /* [417] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(10), + }, + { + /* [418] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(173), + }, + { + /* [419] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(17), + }, + { + /* [420] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(173), + }, + { + /* [421] */ + /* usage */ core::ParameterUsage::kOffset, + /* matcher_indices */ MatcherIndicesIndex(10), + }, + { + /* [422] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(211), + }, + { + /* [423] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [424] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(211), + }, + { + /* [425] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(223), + }, + { + /* [426] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(189), + }, + { + /* [427] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(189), + }, + { + /* [428] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [429] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(189), + }, + { + /* [430] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(211), + }, + { + /* [431] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(271), + }, + { + /* [432] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(189), + }, + { + /* [433] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(197), + }, + { + /* [434] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(201), + }, + { + /* [435] */ + /* usage */ core::ParameterUsage::kXy, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [436] */ + /* usage */ core::ParameterUsage::kZw, + /* matcher_indices */ MatcherIndicesIndex(317), + }, + { + /* [437] */ + /* usage */ core::ParameterUsage::kXyz, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [438] */ + /* usage */ core::ParameterUsage::kW, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [439] */ + /* usage */ core::ParameterUsage::kX, + /* matcher_indices */ MatcherIndicesIndex(27), + }, + { + /* [440] */ + /* usage */ core::ParameterUsage::kZyw, + /* matcher_indices */ MatcherIndicesIndex(26), + }, + { + /* [441] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(42), + }, + { + /* [442] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(6), + }, + { + /* [443] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(217), + }, + { + /* [444] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(220), + }, + { + /* [445] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(102), + }, + { + /* [446] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(226), + }, + { + /* [447] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(5), + }, + { + /* [448] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(277), + }, + { + /* [449] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(19), + }, + { + /* [450] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(153), + }, + { + /* [451] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(41), + }, + { + /* [452] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(229), + }, + { + /* [453] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(66), + }, + { + /* [454] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(283), + }, + { + /* [455] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(285), + }, + { + /* [456] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(287), + }, + { + /* [457] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(161), + }, + { + /* [458] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(165), + }, + { + /* [459] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(47), + }, + { + /* [460] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(241), + }, + { + /* [461] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(244), + }, + { + /* [462] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(247), + }, + { + /* [463] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(250), + }, + { + /* [464] */ + /* usage */ core::ParameterUsage::kTexture, + /* matcher_indices */ MatcherIndicesIndex(253), + }, + { + /* [465] */ + /* usage */ core::ParameterUsage::kInputAttachment, + /* matcher_indices */ MatcherIndicesIndex(319), + }, + { + /* [466] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(148), + }, + { + /* [467] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(177), + }, + { + /* [468] */ + /* usage */ core::ParameterUsage::kIndex, + /* matcher_indices */ MatcherIndicesIndex(3), + }, + { + /* [469] */ + /* usage */ core::ParameterUsage::kIndex, + /* matcher_indices */ MatcherIndicesIndex(20), + }, + { + /* [470] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(185), + }, + { + /* [471] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(181), + }, + { + /* [472] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(10), + }, + { + /* [473] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(95), + }, + { + /* [474] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(341), + }, + { + /* [475] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(343), + }, + { + /* [476] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(345), + }, + { + /* [477] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(347), + }, + { + /* [478] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(349), + }, + { + /* [479] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(351), + }, + { + /* [480] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(353), + }, + { + /* [481] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(166), + }, + { + /* [482] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(355), + }, + { + /* [483] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(357), + }, + { + /* [484] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(359), + }, + { + /* [485] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(361), + }, + { + /* [486] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(363), + }, + { + /* [487] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(365), + }, + { + /* [488] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(367), + }, + { + /* [489] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(369), + }, + { + /* [490] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(371), + }, + { + /* [491] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(373), + }, + { + /* [492] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(375), + }, + { + /* [493] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(377), + }, + { + /* [494] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(379), + }, + { + /* [495] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(381), + }, + { + /* [496] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(383), + }, + { + /* [497] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(385), + }, + { + /* [498] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(387), + }, + { + /* [499] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(389), + }, + { + /* [500] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(391), + }, + { + /* [501] */ + /* usage */ core::ParameterUsage::kNone, + /* matcher_indices */ MatcherIndicesIndex(393), + }, +}; + +static_assert(ParameterIndex::CanIndex(kParameters), + "ParameterIndex is not large enough to index kParameters"); + +constexpr TemplateInfo kTemplates[] = { + { + /* [0] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(57), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [1] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [2] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(411), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [3] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [4] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [5] */ + /* name */ "AC", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [6] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(57), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [7] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [8] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(114), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [9] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [10] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [11] */ + /* name */ "AC", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [12] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(57), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [13] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [14] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(104), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [15] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [16] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [17] */ + /* name */ "AC", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [18] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(412), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [19] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [20] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [21] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [22] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [23] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(411), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [24] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [25] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [26] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [27] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [28] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [29] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [30] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [31] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [32] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [33] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(413), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [34] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(414), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [35] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [36] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [37] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [38] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [39] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [40] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [41] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [42] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [43] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [44] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(412), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [45] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [46] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [47] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [48] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [49] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [50] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [51] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [52] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [53] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(414), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [54] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(413), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [55] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [56] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [57] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [58] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [59] */ + /* name */ "TR", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [60] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [61] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [62] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [63] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [64] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(102), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [65] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(26), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [66] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [67] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [68] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [69] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(410), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [70] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(26), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [71] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [72] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [73] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(10), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [74] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(26), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [75] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [76] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [77] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [78] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [79] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [80] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [81] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(102), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [82] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [83] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [84] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [85] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(410), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [86] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [87] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [88] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [89] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(10), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [90] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [91] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [92] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [93] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(102), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [94] */ + /* name */ "RW", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [95] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [96] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [97] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(410), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [98] */ + /* name */ "RW", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [99] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [100] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [101] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(10), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [102] */ + /* name */ "RW", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [103] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [104] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [105] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [106] */ + /* name */ "AS", + /* matcher_indices */ MatcherIndicesIndex(359), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [107] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [108] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(396), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [109] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(398), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [110] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [111] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [112] */ + /* name */ "AS", + /* matcher_indices */ MatcherIndicesIndex(1), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [113] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [114] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(395), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [115] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [116] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [117] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(1), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [118] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(396), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [119] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [120] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [121] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [122] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(214), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [123] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [124] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [125] */ + /* name */ "M", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [126] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [127] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(396), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [128] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [129] */ + /* name */ "M", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [130] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [131] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [132] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [133] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [134] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [135] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [136] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(323), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [137] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [138] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [139] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(325), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [140] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [141] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [142] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(327), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [143] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [144] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [145] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(329), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [146] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [147] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [148] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(331), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [149] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [150] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [151] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(333), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [152] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [153] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [154] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(335), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [155] */ + /* name */ "K", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [156] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [157] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [158] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [159] */ + /* name */ "A", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [160] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(396), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [161] */ + /* name */ "C", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [162] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [163] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [164] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(26), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [165] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [166] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [167] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(220), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [168] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [169] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(399), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [170] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [171] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(400), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [172] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [173] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(411), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [174] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(223), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [175] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [176] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(415), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [177] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(5), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [178] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [179] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(277), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [180] */ + /* name */ "S", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [181] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(13), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [182] */ + /* name */ "L", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [183] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [184] */ + /* name */ "R", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [185] */ + /* name */ "F", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [186] */ + /* name */ "W", + /* matcher_indices */ MatcherIndicesIndex(26), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [187] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(402), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [188] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [189] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(403), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [190] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [191] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(404), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [192] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [193] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(405), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [194] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [195] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(406), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [196] */ + /* name */ "I", + /* matcher_indices */ MatcherIndicesIndex(397), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [197] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(416), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [198] */ + /* name */ "N", + /* matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* kind */ TemplateInfo::Kind::kNumber, + }, + { + /* [199] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(41), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [200] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(419), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [201] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(6), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [202] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(420), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [203] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(10), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [204] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(417), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [205] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(17), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [206] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(418), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [207] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(109), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [208] */ + /* name */ "U", + /* matcher_indices */ MatcherIndicesIndex(421), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [209] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(12), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [210] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(401), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [211] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(417), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [212] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(418), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [213] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(419), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [214] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(420), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [215] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(421), + /* kind */ TemplateInfo::Kind::kType, + }, + { + /* [216] */ + /* name */ "T", + /* matcher_indices */ MatcherIndicesIndex(412), + /* kind */ TemplateInfo::Kind::kType, + }, +}; + +static_assert(TemplateIndex::CanIndex(kTemplates), + "TemplateIndex is not large enough to index kTemplates"); + +constexpr core::constant::Eval::Function kConstEvalFunctions[] = { + /* [0] */ &core::constant::Eval::abs, + /* [1] */ &core::constant::Eval::acos, + /* [2] */ &core::constant::Eval::acosh, + /* [3] */ &core::constant::Eval::all, + /* [4] */ &core::constant::Eval::any, + /* [5] */ &core::constant::Eval::asin, + /* [6] */ &core::constant::Eval::asinh, + /* [7] */ &core::constant::Eval::atan, + /* [8] */ &core::constant::Eval::atan2, + /* [9] */ &core::constant::Eval::atanh, + /* [10] */ &core::constant::Eval::bitcast, + /* [11] */ &core::constant::Eval::ceil, + /* [12] */ &core::constant::Eval::clamp, + /* [13] */ &core::constant::Eval::cos, + /* [14] */ &core::constant::Eval::cosh, + /* [15] */ &core::constant::Eval::countLeadingZeros, + /* [16] */ &core::constant::Eval::countOneBits, + /* [17] */ &core::constant::Eval::countTrailingZeros, + /* [18] */ &core::constant::Eval::cross, + /* [19] */ &core::constant::Eval::degrees, + /* [20] */ &core::constant::Eval::determinant, + /* [21] */ &core::constant::Eval::distance, + /* [22] */ &core::constant::Eval::dot, + /* [23] */ &core::constant::Eval::dot4I8Packed, + /* [24] */ &core::constant::Eval::dot4U8Packed, + /* [25] */ &core::constant::Eval::exp, + /* [26] */ &core::constant::Eval::exp2, + /* [27] */ &core::constant::Eval::extractBits, + /* [28] */ &core::constant::Eval::faceForward, + /* [29] */ &core::constant::Eval::firstLeadingBit, + /* [30] */ &core::constant::Eval::firstTrailingBit, + /* [31] */ &core::constant::Eval::floor, + /* [32] */ &core::constant::Eval::fma, + /* [33] */ &core::constant::Eval::fract, + /* [34] */ &core::constant::Eval::frexp, + /* [35] */ &core::constant::Eval::insertBits, + /* [36] */ &core::constant::Eval::inverseSqrt, + /* [37] */ &core::constant::Eval::ldexp, + /* [38] */ &core::constant::Eval::length, + /* [39] */ &core::constant::Eval::log, + /* [40] */ &core::constant::Eval::log2, + /* [41] */ &core::constant::Eval::max, + /* [42] */ &core::constant::Eval::min, + /* [43] */ &core::constant::Eval::mix, + /* [44] */ &core::constant::Eval::modf, + /* [45] */ &core::constant::Eval::normalize, + /* [46] */ &core::constant::Eval::pack2x16float, + /* [47] */ &core::constant::Eval::pack2x16snorm, + /* [48] */ &core::constant::Eval::pack2x16unorm, + /* [49] */ &core::constant::Eval::pack4x8snorm, + /* [50] */ &core::constant::Eval::pack4x8unorm, + /* [51] */ &core::constant::Eval::pack4xI8, + /* [52] */ &core::constant::Eval::pack4xU8, + /* [53] */ &core::constant::Eval::pack4xI8Clamp, + /* [54] */ &core::constant::Eval::pack4xU8Clamp, + /* [55] */ &core::constant::Eval::pow, + /* [56] */ &core::constant::Eval::quantizeToF16, + /* [57] */ &core::constant::Eval::radians, + /* [58] */ &core::constant::Eval::reflect, + /* [59] */ &core::constant::Eval::refract, + /* [60] */ &core::constant::Eval::reverseBits, + /* [61] */ &core::constant::Eval::round, + /* [62] */ &core::constant::Eval::saturate, + /* [63] */ &core::constant::Eval::select_bool, + /* [64] */ &core::constant::Eval::select_boolvec, + /* [65] */ &core::constant::Eval::sign, + /* [66] */ &core::constant::Eval::sin, + /* [67] */ &core::constant::Eval::sinh, + /* [68] */ &core::constant::Eval::smoothstep, + /* [69] */ &core::constant::Eval::sqrt, + /* [70] */ &core::constant::Eval::step, + /* [71] */ &core::constant::Eval::tan, + /* [72] */ &core::constant::Eval::tanh, + /* [73] */ &core::constant::Eval::transpose, + /* [74] */ &core::constant::Eval::trunc, + /* [75] */ &core::constant::Eval::unpack2x16float, + /* [76] */ &core::constant::Eval::unpack2x16snorm, + /* [77] */ &core::constant::Eval::unpack2x16unorm, + /* [78] */ &core::constant::Eval::unpack4x8snorm, + /* [79] */ &core::constant::Eval::unpack4x8unorm, + /* [80] */ &core::constant::Eval::unpack4xI8, + /* [81] */ &core::constant::Eval::unpack4xU8, + /* [82] */ &core::constant::Eval::Identity, + /* [83] */ &core::constant::Eval::Not, + /* [84] */ &core::constant::Eval::Complement, + /* [85] */ &core::constant::Eval::UnaryMinus, + /* [86] */ &core::constant::Eval::Plus, + /* [87] */ &core::constant::Eval::Minus, + /* [88] */ &core::constant::Eval::Multiply, + /* [89] */ &core::constant::Eval::MultiplyMatVec, + /* [90] */ &core::constant::Eval::MultiplyVecMat, + /* [91] */ &core::constant::Eval::MultiplyMatMat, + /* [92] */ &core::constant::Eval::Divide, + /* [93] */ &core::constant::Eval::Modulo, + /* [94] */ &core::constant::Eval::Xor, + /* [95] */ &core::constant::Eval::And, + /* [96] */ &core::constant::Eval::Or, + /* [97] */ &core::constant::Eval::LogicalAnd, + /* [98] */ &core::constant::Eval::LogicalOr, + /* [99] */ &core::constant::Eval::Equal, + /* [100] */ &core::constant::Eval::NotEqual, + /* [101] */ &core::constant::Eval::LessThan, + /* [102] */ &core::constant::Eval::GreaterThan, + /* [103] */ &core::constant::Eval::LessThanEqual, + /* [104] */ &core::constant::Eval::GreaterThanEqual, + /* [105] */ &core::constant::Eval::ShiftLeft, + /* [106] */ &core::constant::Eval::ShiftRight, + /* [107] */ &core::constant::Eval::Zero, + /* [108] */ &core::constant::Eval::Conv, + /* [109] */ &core::constant::Eval::VecSplat, + /* [110] */ &core::constant::Eval::VecInitS, + /* [111] */ &core::constant::Eval::VecInitM, + /* [112] */ &core::constant::Eval::MatInitS, + /* [113] */ &core::constant::Eval::MatInitV, +}; + +static_assert(ConstEvalFunctionIndex::CanIndex(kConstEvalFunctions), + "ConstEvalFunctionIndex is not large enough to index kConstEvalFunctions"); + +constexpr OverloadInfo kOverloads[] = { + { + /* [0] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(130), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [1] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(130), + /* parameters */ ParameterIndex(337), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [2] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(231), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [3] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(130), + /* parameters */ ParameterIndex(340), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [4] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(133), + /* parameters */ ParameterIndex(343), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [5] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(131), + /* parameters */ ParameterIndex(346), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [6] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(77), + /* parameters */ ParameterIndex(235), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [7] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(134), + /* parameters */ ParameterIndex(349), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [8] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(388), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [9] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [10] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(84), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [11] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(88), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [12] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [13] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(84), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [14] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(88), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [15] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [16] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(84), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [17] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(88), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [18] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [19] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(84), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [20] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(88), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [21] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(80), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [22] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(84), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [23] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(88), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [24] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [25] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [26] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [27] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [28] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [29] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [30] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [31] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [32] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [33] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [34] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [35] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [36] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [37] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [38] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [39] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [40] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(181), + /* parameters */ ParameterIndex(368), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [41] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(75), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [42] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(181), + /* parameters */ ParameterIndex(370), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [43] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(27), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [44] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(181), + /* parameters */ ParameterIndex(372), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [45] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(340), + /* return_matcher_indices */ MatcherIndicesIndex(33), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [46] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(181), + /* parameters */ ParameterIndex(374), + /* return_matcher_indices */ MatcherIndicesIndex(33), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [47] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(184), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [48] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(181), + /* parameters */ ParameterIndex(376), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [49] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(80), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [50] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(181), + /* parameters */ ParameterIndex(378), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [51] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(343), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [52] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [53] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(380), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [54] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [55] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(382), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [56] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [57] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(384), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [58] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [59] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(386), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [60] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(349), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [61] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(460), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [62] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(461), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [63] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(462), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [64] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(463), + /* return_matcher_indices */ MatcherIndicesIndex(33), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [65] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(464), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [66] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(185), + /* parameters */ ParameterIndex(460), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [67] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(185), + /* parameters */ ParameterIndex(461), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [68] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(185), + /* parameters */ ParameterIndex(462), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [69] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(185), + /* parameters */ ParameterIndex(463), + /* return_matcher_indices */ MatcherIndicesIndex(33), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [70] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(185), + /* parameters */ ParameterIndex(464), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [71] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(295), + /* return_matcher_indices */ MatcherIndicesIndex(72), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [72] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(339), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [73] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [74] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [75] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [76] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [77] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [78] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [79] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [80] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(355), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [81] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(355), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [82] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(358), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [83] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(358), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [84] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(361), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [85] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(361), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [86] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(435), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [87] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(435), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [88] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(437), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [89] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(437), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [90] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(439), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [91] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(439), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [92] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(199), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [93] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(201), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [94] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(203), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [95] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(205), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [96] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(207), + /* parameters */ ParameterIndex(474), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [97] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(101), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [98] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [99] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [100] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [101] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [102] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [103] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [104] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [105] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(355), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [106] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(355), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [107] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(358), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [108] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(358), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(111), + }, + { + /* [109] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(199), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [110] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(201), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [111] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(203), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [112] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(205), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [113] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(207), + /* parameters */ ParameterIndex(473), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [114] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(207), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [115] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [116] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(195), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [117] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(19), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [118] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(99), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [119] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(50), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [120] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(199), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [121] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(119), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [122] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(56), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [123] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [124] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(187), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [125] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [126] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(84), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [127] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(215), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [128] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [129] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(207), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [130] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(124), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [131] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(124), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [132] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(62), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [133] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(62), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [134] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(129), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [135] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(129), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [136] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(211), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [137] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(134), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [138] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [139] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [140] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [141] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [142] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(67), + /* parameters */ ParameterIndex(215), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [143] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [144] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(298), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [145] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(301), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [146] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(219), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [147] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(63), + /* parameters */ ParameterIndex(304), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [148] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(92), + /* parameters */ ParameterIndex(307), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [149] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(310), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [150] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(313), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [151] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(223), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [152] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(68), + /* parameters */ ParameterIndex(316), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [153] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(96), + /* parameters */ ParameterIndex(319), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [154] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(72), + /* parameters */ ParameterIndex(322), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [155] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(72), + /* parameters */ ParameterIndex(325), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [156] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(72), + /* parameters */ ParameterIndex(227), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [157] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(72), + /* parameters */ ParameterIndex(328), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [158] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(100), + /* parameters */ ParameterIndex(331), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [159] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(337), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [160] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [161] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [162] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [163] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [164] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(109), + }, + { + /* [165] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [166] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(263), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(110), + }, + { + /* [167] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(199), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [168] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(201), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [169] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(203), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [170] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(205), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [171] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(207), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(317), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [172] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(74), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [173] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(74), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [174] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(26), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [175] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(26), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [176] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(183), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [177] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(79), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [178] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(139), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [179] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(187), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [180] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(68), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [181] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(84), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [182] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(215), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [183] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(144), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [184] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(136), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [185] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(139), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [186] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(142), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [187] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [188] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(148), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [189] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(151), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [190] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(154), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [191] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(187), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [192] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(189), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [193] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(191), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [194] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(193), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [195] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(195), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [196] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(136), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [197] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(139), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [198] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(142), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [199] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(145), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [200] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(148), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [201] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(151), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [202] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(154), + /* parameters */ ParameterIndex(468), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [203] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(187), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [204] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(189), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [205] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(191), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [206] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(193), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [207] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(195), + /* parameters */ ParameterIndex(469), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [208] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(165), + /* parameters */ ParameterIndex(287), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [209] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(442), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [210] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(122), + /* parameters */ ParameterIndex(443), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [211] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(167), + /* parameters */ ParameterIndex(444), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [212] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(205), + /* parameters */ ParameterIndex(445), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [213] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(174), + /* parameters */ ParameterIndex(446), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [214] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(447), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [215] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(209), + /* parameters */ ParameterIndex(448), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [216] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(177), + /* parameters */ ParameterIndex(287), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [217] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 2, + /* templates */ TemplateIndex(179), + /* parameters */ ParameterIndex(449), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(10), + }, + { + /* [218] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(334), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [219] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(75), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [220] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(27), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [221] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(340), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [222] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(184), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [223] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(80), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [224] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [225] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [226] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [227] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [228] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [229] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [230] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(422), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [231] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [232] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(127), + /* parameters */ ParameterIndex(428), + /* return_matcher_indices */ MatcherIndicesIndex(189), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [233] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(127), + /* parameters */ ParameterIndex(427), + /* return_matcher_indices */ MatcherIndicesIndex(189), + /* const_eval_fn */ ConstEvalFunctionIndex(88), + }, + { + /* [234] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(160), + /* parameters */ ParameterIndex(429), + /* return_matcher_indices */ MatcherIndicesIndex(271), + /* const_eval_fn */ ConstEvalFunctionIndex(89), + }, + { + /* [235] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(160), + /* parameters */ ParameterIndex(431), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(90), + }, + { + /* [236] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(118), + /* parameters */ ParameterIndex(433), + /* return_matcher_indices */ MatcherIndicesIndex(193), + /* const_eval_fn */ ConstEvalFunctionIndex(91), + }, + { + /* [237] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [238] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(475), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [239] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(475), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [240] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [241] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [242] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [243] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [244] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(476), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [245] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(477), + /* return_matcher_indices */ MatcherIndicesIndex(343), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [246] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [247] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(478), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [248] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(478), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [249] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [250] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [251] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [252] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [253] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(479), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [254] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(480), + /* return_matcher_indices */ MatcherIndicesIndex(349), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [255] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [256] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(481), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [257] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(481), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [258] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 8, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [259] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 8, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [260] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [261] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [262] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(482), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [263] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(483), + /* return_matcher_indices */ MatcherIndicesIndex(166), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [264] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [265] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(484), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [266] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(484), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [267] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [268] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [269] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [270] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [271] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(485), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [272] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(486), + /* return_matcher_indices */ MatcherIndicesIndex(359), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [273] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [274] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [275] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(487), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [276] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 9, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [277] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 9, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [278] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [279] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [280] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(488), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [281] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(489), + /* return_matcher_indices */ MatcherIndicesIndex(365), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [282] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [283] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(490), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [284] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(490), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [285] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 12, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [286] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 12, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [287] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [288] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [289] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(491), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [290] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(492), + /* return_matcher_indices */ MatcherIndicesIndex(371), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [291] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [292] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [293] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(493), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [294] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 8, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [295] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 8, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [296] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [297] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(267), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [298] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(494), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [299] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(495), + /* return_matcher_indices */ MatcherIndicesIndex(377), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [300] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [301] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(496), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [302] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(496), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [303] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 12, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [304] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 12, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [305] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [306] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [307] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(497), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [308] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(498), + /* return_matcher_indices */ MatcherIndicesIndex(383), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [309] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [310] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(216), + /* parameters */ ParameterIndex(499), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [311] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(499), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [312] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 16, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [313] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 16, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(112), + }, + { + /* [314] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [315] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(275), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(113), + }, + { + /* [316] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(19), + /* parameters */ ParameterIndex(500), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [317] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 1, + /* num_templates */ 1, + /* templates */ TemplateIndex(27), + /* parameters */ ParameterIndex(501), + /* return_matcher_indices */ MatcherIndicesIndex(389), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [318] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(104), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [319] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(104), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [320] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(38), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [321] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(38), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [322] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(109), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [323] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(109), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [324] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(203), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [325] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(114), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [326] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [327] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [328] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(19), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [329] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 7, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(19), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [330] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(50), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [331] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(50), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [332] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(119), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [333] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(56), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [334] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(414), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [335] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(416), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [336] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(110), + /* parameters */ ParameterIndex(414), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [337] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 4, + /* templates */ TemplateIndex(110), + /* parameters */ ParameterIndex(416), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [338] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(418), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [339] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(420), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [340] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(110), + /* parameters */ ParameterIndex(418), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [341] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 3, + /* templates */ TemplateIndex(110), + /* parameters */ ParameterIndex(420), + /* return_matcher_indices */ MatcherIndicesIndex(169), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [342] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [343] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [344] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [345] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [346] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [347] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [348] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(27), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [349] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(80), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [350] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [351] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [352] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(183), + /* parameters */ ParameterIndex(462), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [353] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(185), + /* parameters */ ParameterIndex(462), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [354] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [355] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [356] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [357] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [358] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [359] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [360] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [361] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(89), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [362] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [363] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 6, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(32), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [364] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(191), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [365] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(66), + /* parameters */ ParameterIndex(94), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [366] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(0), + /* parameters */ ParameterIndex(239), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [367] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(0), + /* parameters */ ParameterIndex(243), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [368] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(6), + /* parameters */ ParameterIndex(247), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [369] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(251), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [370] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(6), + /* parameters */ ParameterIndex(255), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [371] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 1, + /* num_templates */ 6, + /* templates */ TemplateIndex(12), + /* parameters */ ParameterIndex(259), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [372] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(1), + /* parameters */ ParameterIndex(149), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [373] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(1), + /* parameters */ ParameterIndex(154), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [374] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(159), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [375] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(13), + /* parameters */ ParameterIndex(164), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [376] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(7), + /* parameters */ ParameterIndex(169), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [377] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 5, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(13), + /* parameters */ ParameterIndex(174), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [378] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [379] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [380] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(422), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [381] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [382] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(127), + /* parameters */ ParameterIndex(426), + /* return_matcher_indices */ MatcherIndicesIndex(189), + /* const_eval_fn */ ConstEvalFunctionIndex(86), + }, + { + /* [383] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(87), + }, + { + /* [384] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(87), + }, + { + /* [385] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(422), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(87), + }, + { + /* [386] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(87), + }, + { + /* [387] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(127), + /* parameters */ ParameterIndex(426), + /* return_matcher_indices */ MatcherIndicesIndex(189), + /* const_eval_fn */ ConstEvalFunctionIndex(87), + }, + { + /* [388] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(18), + /* parameters */ ParameterIndex(406), + /* return_matcher_indices */ MatcherIndicesIndex(103), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [389] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(26), + /* parameters */ ParameterIndex(406), + /* return_matcher_indices */ MatcherIndicesIndex(103), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [390] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(33), + /* parameters */ ParameterIndex(406), + /* return_matcher_indices */ MatcherIndicesIndex(103), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [391] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 1, + /* num_templates */ 5, + /* templates */ TemplateIndex(38), + /* parameters */ ParameterIndex(406), + /* return_matcher_indices */ MatcherIndicesIndex(103), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [392] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(43), + /* parameters */ ParameterIndex(352), + /* return_matcher_indices */ MatcherIndicesIndex(118), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [393] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(48), + /* parameters */ ParameterIndex(352), + /* return_matcher_indices */ MatcherIndicesIndex(118), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [394] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(53), + /* parameters */ ParameterIndex(352), + /* return_matcher_indices */ MatcherIndicesIndex(118), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [395] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 5, + /* templates */ TemplateIndex(58), + /* parameters */ ParameterIndex(352), + /* return_matcher_indices */ MatcherIndicesIndex(118), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [396] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(105), + /* parameters */ ParameterIndex(466), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [397] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(111), + /* parameters */ ParameterIndex(466), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [398] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(105), + /* parameters */ ParameterIndex(467), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [399] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(111), + /* parameters */ ParameterIndex(467), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [400] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(92), + }, + { + /* [401] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(92), + }, + { + /* [402] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(422), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(92), + }, + { + /* [403] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(92), + }, + { + /* [404] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [405] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [406] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(422), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [407] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(423), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(93), + }, + { + /* [408] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(95), + }, + { + /* [409] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(208), + /* const_eval_fn */ ConstEvalFunctionIndex(95), + }, + { + /* [410] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(95), + }, + { + /* [411] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(95), + }, + { + /* [412] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(96), + }, + { + /* [413] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(208), + /* const_eval_fn */ ConstEvalFunctionIndex(96), + }, + { + /* [414] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(96), + }, + { + /* [415] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(96), + }, + { + /* [416] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(43), + }, + { + /* [417] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(43), + }, + { + /* [418] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(285), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(43), + }, + { + /* [419] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(288), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(63), + }, + { + /* [420] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(280), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(63), + }, + { + /* [421] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(168), + /* parameters */ ParameterIndex(291), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(64), + }, + { + /* [422] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 4, + /* templates */ TemplateIndex(22), + /* parameters */ ParameterIndex(408), + /* return_matcher_indices */ MatcherIndicesIndex(86), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [423] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(30), + /* parameters */ ParameterIndex(410), + /* return_matcher_indices */ MatcherIndicesIndex(133), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [424] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(30), + /* parameters */ ParameterIndex(412), + /* return_matcher_indices */ MatcherIndicesIndex(138), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [425] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [426] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(472), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [427] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(211), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [428] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [429] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [430] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(212), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [431] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [432] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [433] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(213), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [434] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [435] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(442), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [436] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(214), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(6), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [437] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(107), + }, + { + /* [438] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConstructor, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [439] */ + /* flags */ OverloadFlags(OverloadFlag::kIsConverter, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(215), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(108), + }, + { + /* [440] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(0), + }, + { + /* [441] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(113), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(0), + }, + { + /* [442] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(1), + }, + { + /* [443] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(1), + }, + { + /* [444] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(2), + }, + { + /* [445] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(2), + }, + { + /* [446] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(3), + }, + { + /* [447] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(3), + }, + { + /* [448] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(4), + }, + { + /* [449] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(4), + }, + { + /* [450] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(441), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [451] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(163), + /* parameters */ ParameterIndex(441), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [452] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(5), + }, + { + /* [453] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(5), + }, + { + /* [454] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(6), + }, + { + /* [455] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(6), + }, + { + /* [456] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(7), + }, + { + /* [457] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(7), + }, + { + /* [458] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(8), + }, + { + /* [459] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(127), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(8), + }, + { + /* [460] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(9), + }, + { + /* [461] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(9), + }, + { + /* [462] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(11), + }, + { + /* [463] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(11), + }, + { + /* [464] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(12), + }, + { + /* [465] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(12), + }, + { + /* [466] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(13), + }, + { + /* [467] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(13), + }, + { + /* [468] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(14), + }, + { + /* [469] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(14), + }, + { + /* [470] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(15), + }, + { + /* [471] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(15), + }, + { + /* [472] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(16), + }, + { + /* [473] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(16), + }, + { + /* [474] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(17), + }, + { + /* [475] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(17), + }, + { + /* [476] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(19), + }, + { + /* [477] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(19), + }, + { + /* [478] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(21), + }, + { + /* [479] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(20), + /* const_eval_fn */ ConstEvalFunctionIndex(21), + }, + { + /* [480] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [481] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(229), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [482] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(25), + }, + { + /* [483] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(25), + }, + { + /* [484] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(26), + }, + { + /* [485] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(26), + }, + { + /* [486] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(16), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(27), + }, + { + /* [487] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(180), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(27), + }, + { + /* [488] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(29), + }, + { + /* [489] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(29), + }, + { + /* [490] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(30), + }, + { + /* [491] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(30), + }, + { + /* [492] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(31), + }, + { + /* [493] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(31), + }, + { + /* [494] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(32), + }, + { + /* [495] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(32), + }, + { + /* [496] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(33), + }, + { + /* [497] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(33), + }, + { + /* [498] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(279), + /* const_eval_fn */ ConstEvalFunctionIndex(34), + }, + { + /* [499] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(232), + /* const_eval_fn */ ConstEvalFunctionIndex(34), + }, + { + /* [500] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(15), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(35), + }, + { + /* [501] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 4, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(35), + }, + { + /* [502] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(36), + }, + { + /* [503] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(36), + }, + { + /* [504] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(364), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(37), + }, + { + /* [505] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(366), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(37), + }, + { + /* [506] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(38), + }, + { + /* [507] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(20), + /* const_eval_fn */ ConstEvalFunctionIndex(38), + }, + { + /* [508] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(39), + }, + { + /* [509] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(39), + }, + { + /* [510] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(40), + }, + { + /* [511] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(40), + }, + { + /* [512] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(41), + }, + { + /* [513] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(113), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(41), + }, + { + /* [514] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(42), + }, + { + /* [515] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(113), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(42), + }, + { + /* [516] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(281), + /* const_eval_fn */ ConstEvalFunctionIndex(44), + }, + { + /* [517] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(238), + /* const_eval_fn */ ConstEvalFunctionIndex(44), + }, + { + /* [518] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(55), + }, + { + /* [519] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(55), + }, + { + /* [520] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(451), + /* return_matcher_indices */ MatcherIndicesIndex(41), + /* const_eval_fn */ ConstEvalFunctionIndex(56), + }, + { + /* [521] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(452), + /* return_matcher_indices */ MatcherIndicesIndex(229), + /* const_eval_fn */ ConstEvalFunctionIndex(56), + }, + { + /* [522] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(57), + }, + { + /* [523] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(57), + }, + { + /* [524] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(60), + }, + { + /* [525] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(60), + }, + { + /* [526] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(61), + }, + { + /* [527] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(61), + }, + { + /* [528] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(62), + }, + { + /* [529] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(127), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(62), + }, + { + /* [530] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(171), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(65), + }, + { + /* [531] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(170), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(65), + }, + { + /* [532] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(66), + }, + { + /* [533] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(66), + }, + { + /* [534] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(67), + }, + { + /* [535] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(67), + }, + { + /* [536] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(68), + }, + { + /* [537] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(68), + }, + { + /* [538] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(69), + }, + { + /* [539] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(69), + }, + { + /* [540] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(70), + }, + { + /* [541] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(70), + }, + { + /* [542] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(71), + }, + { + /* [543] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(71), + }, + { + /* [544] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(72), + }, + { + /* [545] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(72), + }, + { + /* [546] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(74), + }, + { + /* [547] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(74), + }, + { + /* [548] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(210), + /* parameters */ ParameterIndex(458), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [549] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(459), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [550] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(343), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [551] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(349), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [552] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(44), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [553] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(295), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [554] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(390), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [555] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(392), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [556] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(390), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [557] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(392), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [558] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(394), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [559] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(396), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [560] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(398), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [561] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(400), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [562] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(39), + /* parameters */ ParameterIndex(390), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [563] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(115), + /* parameters */ ParameterIndex(392), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [564] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(402), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [565] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(404), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [566] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(23), + /* parameters */ ParameterIndex(402), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [567] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(172), + /* parameters */ ParameterIndex(404), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [568] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(176), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [569] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(175), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [570] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(83), + }, + { + /* [571] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(293), + /* return_matcher_indices */ MatcherIndicesIndex(208), + /* const_eval_fn */ ConstEvalFunctionIndex(83), + }, + { + /* [572] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [573] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(84), + }, + { + /* [574] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(171), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [575] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(171), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(85), + }, + { + /* [576] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(94), + }, + { + /* [577] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(94), + }, + { + /* [578] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(99), + }, + { + /* [579] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(274), + /* const_eval_fn */ ConstEvalFunctionIndex(99), + }, + { + /* [580] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(100), + }, + { + /* [581] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(169), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(274), + /* const_eval_fn */ ConstEvalFunctionIndex(100), + }, + { + /* [582] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(101), + }, + { + /* [583] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(274), + /* const_eval_fn */ ConstEvalFunctionIndex(101), + }, + { + /* [584] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(102), + }, + { + /* [585] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(274), + /* const_eval_fn */ ConstEvalFunctionIndex(102), + }, + { + /* [586] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(103), + }, + { + /* [587] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(274), + /* const_eval_fn */ ConstEvalFunctionIndex(103), + }, + { + /* [588] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(104), + }, + { + /* [589] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(114), + /* parameters */ ParameterIndex(279), + /* return_matcher_indices */ MatcherIndicesIndex(274), + /* const_eval_fn */ ConstEvalFunctionIndex(104), + }, + { + /* [590] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(16), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [591] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(424), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(105), + }, + { + /* [592] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(16), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [593] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(197), + /* parameters */ ParameterIndex(424), + /* return_matcher_indices */ MatcherIndicesIndex(211), + /* const_eval_fn */ ConstEvalFunctionIndex(106), + }, + { + /* [594] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(108), + /* parameters */ ParameterIndex(271), + /* return_matcher_indices */ MatcherIndicesIndex(26), + /* const_eval_fn */ ConstEvalFunctionIndex(18), + }, + { + /* [595] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(450), + /* return_matcher_indices */ MatcherIndicesIndex(20), + /* const_eval_fn */ ConstEvalFunctionIndex(20), + }, + { + /* [596] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(113), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(20), + /* const_eval_fn */ ConstEvalFunctionIndex(22), + }, + { + /* [597] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(10), + /* const_eval_fn */ ConstEvalFunctionIndex(23), + }, + { + /* [598] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(24), + }, + { + /* [599] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(284), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(28), + }, + { + /* [600] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(45), + }, + { + /* [601] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(453), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(46), + }, + { + /* [602] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(453), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(47), + }, + { + /* [603] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(453), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(48), + }, + { + /* [604] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(454), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(49), + }, + { + /* [605] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(454), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(50), + }, + { + /* [606] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(455), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(51), + }, + { + /* [607] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(456), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(52), + }, + { + /* [608] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(455), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(53), + }, + { + /* [609] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(456), + /* return_matcher_indices */ MatcherIndicesIndex(17), + /* const_eval_fn */ ConstEvalFunctionIndex(54), + }, + { + /* [610] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(179), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(58), + }, + { + /* [611] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(107), + /* parameters */ ParameterIndex(285), + /* return_matcher_indices */ MatcherIndicesIndex(205), + /* const_eval_fn */ ConstEvalFunctionIndex(59), + }, + { + /* [612] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [613] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(125), + /* parameters */ ParameterIndex(457), + /* return_matcher_indices */ MatcherIndicesIndex(157), + /* const_eval_fn */ ConstEvalFunctionIndex(73), + }, + { + /* [614] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(66), + /* const_eval_fn */ ConstEvalFunctionIndex(75), + }, + { + /* [615] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(66), + /* const_eval_fn */ ConstEvalFunctionIndex(76), + }, + { + /* [616] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(66), + /* const_eval_fn */ ConstEvalFunctionIndex(77), + }, + { + /* [617] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(78), + }, + { + /* [618] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(283), + /* const_eval_fn */ ConstEvalFunctionIndex(79), + }, + { + /* [619] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(285), + /* const_eval_fn */ ConstEvalFunctionIndex(80), + }, + { + /* [620] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(17), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(81), + }, + { + /* [621] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(76), + /* parameters */ ParameterIndex(465), + /* return_matcher_indices */ MatcherIndicesIndex(303), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [622] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(116), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [623] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(116), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(/* invalid */), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [624] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(116), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [625] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 3, + /* num_explicit_templates */ 0, + /* num_templates */ 2, + /* templates */ TemplateIndex(116), + /* parameters */ ParameterIndex(0), + /* return_matcher_indices */ MatcherIndicesIndex(321), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [626] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(287), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [627] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 0, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(/* invalid */), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [628] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(152), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [629] */ + /* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 1, + /* templates */ TemplateIndex(104), + /* parameters */ ParameterIndex(1), + /* return_matcher_indices */ MatcherIndicesIndex(27), + /* const_eval_fn */ ConstEvalFunctionIndex(82), + }, + { + /* [630] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(470), + /* return_matcher_indices */ MatcherIndicesIndex(181), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [631] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 1, + /* num_explicit_templates */ 0, + /* num_templates */ 3, + /* templates */ TemplateIndex(157), + /* parameters */ ParameterIndex(471), + /* return_matcher_indices */ MatcherIndicesIndex(185), + /* const_eval_fn */ ConstEvalFunctionIndex(/* invalid */), + }, + { + /* [632] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(97), + }, + { + /* [633] */ + /* flags */ OverloadFlags(OverloadFlag::kIsOperator, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline, OverloadFlag::kMustUse), + /* num_parameters */ 2, + /* num_explicit_templates */ 0, + /* num_templates */ 0, + /* templates */ TemplateIndex(/* invalid */), + /* parameters */ ParameterIndex(282), + /* return_matcher_indices */ MatcherIndicesIndex(109), + /* const_eval_fn */ ConstEvalFunctionIndex(98), + }, +}; + +static_assert(OverloadIndex::CanIndex(kOverloads), + "OverloadIndex is not large enough to index kOverloads"); + +constexpr IntrinsicInfo kBuiltins[] = { + { + /* [0] */ + /* fn abs[T : fia_fiu32_f16](T) -> T */ + /* fn abs[N : num, T : fia_fiu32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(440), + }, + { + /* [1] */ + /* fn acos[T : fa_f32_f16](@test_value(0.96891242171) T) -> T */ + /* fn acos[N : num, T : fa_f32_f16](@test_value(0.96891242171) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(442), + }, + { + /* [2] */ + /* fn acosh[T : fa_f32_f16](@test_value(1.5430806348) T) -> T */ + /* fn acosh[N : num, T : fa_f32_f16](@test_value(1.5430806348) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(444), + }, + { + /* [3] */ + /* fn all(bool) -> bool */ + /* fn all[N : num](vec) -> bool */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(446), + }, + { + /* [4] */ + /* fn any(bool) -> bool */ + /* fn any[N : num](vec) -> bool */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(448), + }, + { + /* [5] */ + /* fn arrayLength[T, R : read](ptr, R>) -> u32 */ + /* fn arrayLength[T, W : writable](ptr, W>) -> u32 */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(450), + }, + { + /* [6] */ + /* fn asin[T : fa_f32_f16](@test_value(0.479425538604) T) -> T */ + /* fn asin[N : num, T : fa_f32_f16](@test_value(0.479425538604) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(452), + }, + { + /* [7] */ + /* fn asinh[T : fa_f32_f16](T) -> T */ + /* fn asinh[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(454), + }, + { + /* [8] */ + /* fn atan[T : fa_f32_f16](T) -> T */ + /* fn atan[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(456), + }, + { + /* [9] */ + /* fn atan2[T : fa_f32_f16](T, T) -> T */ + /* fn atan2[T : fa_f32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(458), + }, + { + /* [10] */ + /* fn atanh[T : fa_f32_f16](@test_value(0.5) T) -> T */ + /* fn atanh[N : num, T : fa_f32_f16](@test_value(0.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(460), + }, + { + /* [11] */ + /* fn bitcast[U : fiu32](U) -> T */ + /* fn bitcast(f16) -> T */ + /* fn bitcast>[N : num, U : fiu32](vec) -> T */ + /* fn bitcast>[N : num](vec) -> T */ + /* fn bitcast(ia) -> T */ + /* fn bitcast>[N : num](vec) -> T */ + /* fn bitcast(vec2) -> T */ + /* fn bitcast>(vec4) -> T */ + /* fn bitcast>[S : fiu32](S) -> T */ + /* fn bitcast>[S : fiu32](vec2) -> T */ + /* num overloads */ 10, + /* overloads */ OverloadIndex(208), + }, + { + /* [12] */ + /* fn ceil[T : fa_f32_f16](@test_value(1.5) T) -> T */ + /* fn ceil[N : num, T : fa_f32_f16](@test_value(1.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(462), + }, + { + /* [13] */ + /* fn clamp[T : fia_fiu32_f16](T, T, T) -> T */ + /* fn clamp[T : fia_fiu32_f16, N : num](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(464), + }, + { + /* [14] */ + /* fn cos[T : fa_f32_f16](@test_value(0) T) -> T */ + /* fn cos[N : num, T : fa_f32_f16](@test_value(0) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(466), + }, + { + /* [15] */ + /* fn cosh[T : fa_f32_f16](@test_value(0) T) -> T */ + /* fn cosh[N : num, T : fa_f32_f16](@test_value(0) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(468), + }, + { + /* [16] */ + /* fn countLeadingZeros[T : iu32](T) -> T */ + /* fn countLeadingZeros[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(470), + }, + { + /* [17] */ + /* fn countOneBits[T : iu32](T) -> T */ + /* fn countOneBits[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(472), + }, + { + /* [18] */ + /* fn countTrailingZeros[T : iu32](T) -> T */ + /* fn countTrailingZeros[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(474), + }, + { + /* [19] */ + /* fn cross[T : fa_f32_f16](vec3, vec3) -> vec3 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(594), + }, + { + /* [20] */ + /* fn degrees[T : fa_f32_f16](T) -> T */ + /* fn degrees[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(476), + }, + { + /* [21] */ + /* fn determinant[N : num, T : fa_f32_f16](mat) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(595), + }, + { + /* [22] */ + /* fn distance[T : fa_f32_f16](T, T) -> T */ + /* fn distance[N : num, T : fa_f32_f16](vec, vec) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(478), + }, + { + /* [23] */ + /* fn dot[N : num, T : fia_fiu32_f16](vec, vec) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(596), + }, + { + /* [24] */ + /* fn dot4I8Packed(u32, u32) -> i32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(597), + }, + { + /* [25] */ + /* fn dot4U8Packed(u32, u32) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(598), + }, + { + /* [26] */ + /* fn dpdx(f32) -> f32 */ + /* fn dpdx[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [27] */ + /* fn dpdxCoarse(f32) -> f32 */ + /* fn dpdxCoarse[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [28] */ + /* fn dpdxFine(f32) -> f32 */ + /* fn dpdxFine[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [29] */ + /* fn dpdy(f32) -> f32 */ + /* fn dpdy[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [30] */ + /* fn dpdyCoarse(f32) -> f32 */ + /* fn dpdyCoarse[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [31] */ + /* fn dpdyFine(f32) -> f32 */ + /* fn dpdyFine[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [32] */ + /* fn exp[T : fa_f32_f16](T) -> T */ + /* fn exp[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(482), + }, + { + /* [33] */ + /* fn exp2[T : fa_f32_f16](T) -> T */ + /* fn exp2[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(484), + }, + { + /* [34] */ + /* fn extractBits[T : iu32](T, u32, u32) -> T */ + /* fn extractBits[N : num, T : iu32](vec, u32, u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(486), + }, + { + /* [35] */ + /* fn faceForward[N : num, T : fa_f32_f16](vec, vec, vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(599), + }, + { + /* [36] */ + /* fn firstLeadingBit[T : iu32](T) -> T */ + /* fn firstLeadingBit[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(488), + }, + { + /* [37] */ + /* fn firstTrailingBit[T : iu32](T) -> T */ + /* fn firstTrailingBit[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(490), + }, + { + /* [38] */ + /* fn floor[T : fa_f32_f16](@test_value(1.5) T) -> T */ + /* fn floor[N : num, T : fa_f32_f16](@test_value(1.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(492), + }, + { + /* [39] */ + /* fn fma[T : fa_f32_f16](T, T, T) -> T */ + /* fn fma[N : num, T : fa_f32_f16](vec, vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(494), + }, + { + /* [40] */ + /* fn fract[T : fa_f32_f16](@test_value(1.25) T) -> T */ + /* fn fract[N : num, T : fa_f32_f16](@test_value(1.25) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(496), + }, + { + /* [41] */ + /* fn frexp[T : fa_f32_f16](T) -> __frexp_result */ + /* fn frexp[N : num, T : fa_f32_f16](vec) -> __frexp_result_vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(498), + }, + { + /* [42] */ + /* fn fwidth(f32) -> f32 */ + /* fn fwidth[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [43] */ + /* fn fwidthCoarse(f32) -> f32 */ + /* fn fwidthCoarse[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [44] */ + /* fn fwidthFine(f32) -> f32 */ + /* fn fwidthFine[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(480), + }, + { + /* [45] */ + /* fn insertBits[T : iu32](T, T, u32, u32) -> T */ + /* fn insertBits[N : num, T : iu32](vec, vec, u32, u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(500), + }, + { + /* [46] */ + /* fn inverseSqrt[T : fa_f32_f16](T) -> T */ + /* fn inverseSqrt[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(502), + }, + { + /* [47] */ + /* fn ldexp[T : fa_f32_f16, U : ia_i32](T, U) -> T */ + /* fn ldexp[N : num, T : fa_f32_f16, U : ia_i32](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(504), + }, + { + /* [48] */ + /* fn length[T : fa_f32_f16](@test_value(0) T) -> T */ + /* fn length[N : num, T : fa_f32_f16](@test_value(0) vec) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(506), + }, + { + /* [49] */ + /* fn log[T : fa_f32_f16](T) -> T */ + /* fn log[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(508), + }, + { + /* [50] */ + /* fn log2[T : fa_f32_f16](T) -> T */ + /* fn log2[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(510), + }, + { + /* [51] */ + /* fn max[T : fia_fiu32_f16](T, T) -> T */ + /* fn max[N : num, T : fia_fiu32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(512), + }, + { + /* [52] */ + /* fn min[T : fia_fiu32_f16](T, T) -> T */ + /* fn min[N : num, T : fia_fiu32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(514), + }, + { + /* [53] */ + /* fn mix[T : fa_f32_f16](T, T, T) -> T */ + /* fn mix[N : num, T : fa_f32_f16](vec, vec, vec) -> vec */ + /* fn mix[N : num, T : fa_f32_f16](vec, vec, T) -> vec */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(416), + }, + { + /* [54] */ + /* fn modf[T : fa_f32_f16](@test_value(-1.5) T) -> __modf_result */ + /* fn modf[N : num, T : fa_f32_f16](@test_value(-1.5) vec) -> __modf_result_vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(516), + }, + { + /* [55] */ + /* fn normalize[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(600), + }, + { + /* [56] */ + /* fn pack2x16float(vec2) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(601), + }, + { + /* [57] */ + /* fn pack2x16snorm(vec2) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(602), + }, + { + /* [58] */ + /* fn pack2x16unorm(vec2) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(603), + }, + { + /* [59] */ + /* fn pack4x8snorm(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(604), + }, + { + /* [60] */ + /* fn pack4x8unorm(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(605), + }, + { + /* [61] */ + /* fn pack4xI8(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(606), + }, + { + /* [62] */ + /* fn pack4xU8(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(607), + }, + { + /* [63] */ + /* fn pack4xI8Clamp(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(608), + }, + { + /* [64] */ + /* fn pack4xU8Clamp(vec4) -> u32 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(609), + }, + { + /* [65] */ + /* fn pow[T : fa_f32_f16](T, T) -> T */ + /* fn pow[N : num, T : fa_f32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(518), + }, + { + /* [66] */ + /* fn quantizeToF16(f32) -> f32 */ + /* fn quantizeToF16[N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(520), + }, + { + /* [67] */ + /* fn radians[T : fa_f32_f16](T) -> T */ + /* fn radians[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(522), + }, + { + /* [68] */ + /* fn reflect[N : num, T : fa_f32_f16](vec, vec) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(610), + }, + { + /* [69] */ + /* fn refract[N : num, T : fa_f32_f16](vec, vec, T) -> vec */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(611), + }, + { + /* [70] */ + /* fn reverseBits[T : iu32](T) -> T */ + /* fn reverseBits[N : num, T : iu32](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(524), + }, + { + /* [71] */ + /* fn round[T : fa_f32_f16](@test_value(3.5) T) -> T */ + /* fn round[N : num, T : fa_f32_f16](@test_value(3.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(526), + }, + { + /* [72] */ + /* fn saturate[T : fa_f32_f16](@test_value(2) T) -> T */ + /* fn saturate[T : fa_f32_f16, N : num](@test_value(2) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(528), + }, + { + /* [73] */ + /* fn select[T : scalar](T, T, bool) -> T */ + /* fn select[T : scalar, N : num](vec, vec, bool) -> vec */ + /* fn select[N : num, T : scalar](vec, vec, vec) -> vec */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(419), + }, + { + /* [74] */ + /* fn sign[T : fia_fi32_f16](T) -> T */ + /* fn sign[N : num, T : fia_fi32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(530), + }, + { + /* [75] */ + /* fn sin[T : fa_f32_f16](@test_value(1.57079632679) T) -> T */ + /* fn sin[N : num, T : fa_f32_f16](@test_value(1.57079632679) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(532), + }, + { + /* [76] */ + /* fn sinh[T : fa_f32_f16](T) -> T */ + /* fn sinh[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(534), + }, + { + /* [77] */ + /* fn smoothstep[T : fa_f32_f16](@test_value(2) T, @test_value(4) T, @test_value(3) T) -> T */ + /* fn smoothstep[N : num, T : fa_f32_f16](@test_value(2) vec, @test_value(4) vec, @test_value(3) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(536), + }, + { + /* [78] */ + /* fn sqrt[T : fa_f32_f16](T) -> T */ + /* fn sqrt[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(538), + }, + { + /* [79] */ + /* fn step[T : fa_f32_f16](T, T) -> T */ + /* fn step[N : num, T : fa_f32_f16](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(540), + }, + { + /* [80] */ + /* fn storageBarrier() */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(612), + }, + { + /* [81] */ + /* fn tan[T : fa_f32_f16](T) -> T */ + /* fn tan[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(542), + }, + { + /* [82] */ + /* fn tanh[T : fa_f32_f16](T) -> T */ + /* fn tanh[N : num, T : fa_f32_f16](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(544), + }, + { + /* [83] */ + /* fn transpose[M : num, N : num, T : fa_f32_f16](mat) -> mat */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(613), + }, + { + /* [84] */ + /* fn trunc[T : fa_f32_f16](@test_value(1.5) T) -> T */ + /* fn trunc[N : num, T : fa_f32_f16](@test_value(1.5) vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(546), + }, + { + /* [85] */ + /* fn unpack2x16float(u32) -> vec2 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(614), + }, + { + /* [86] */ + /* fn unpack2x16snorm(u32) -> vec2 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(615), + }, + { + /* [87] */ + /* fn unpack2x16unorm(u32) -> vec2 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(616), + }, + { + /* [88] */ + /* fn unpack4x8snorm(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(617), + }, + { + /* [89] */ + /* fn unpack4x8unorm(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(618), + }, + { + /* [90] */ + /* fn unpack4xI8(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(619), + }, + { + /* [91] */ + /* fn unpack4xU8(u32) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(620), + }, + { + /* [92] */ + /* fn workgroupBarrier() */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(612), + }, + { + /* [93] */ + /* fn workgroupUniformLoad[T : __constructible](ptr) -> T */ + /* fn workgroupUniformLoad[T : iu32](ptr, read_write>) -> T */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(548), + }, + { + /* [94] */ + /* fn textureBarrier() */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(612), + }, + { + /* [95] */ + /* fn textureDimensions[T : fiu32](texture: texture_1d) -> u32 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_1d, level: L) -> u32 */ + /* fn textureDimensions[T : fiu32](texture: texture_2d) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_2d, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_2d_array) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_2d_array, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_3d) -> vec3 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_3d, level: L) -> vec3 */ + /* fn textureDimensions[T : fiu32](texture: texture_cube) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_cube, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_cube_array) -> vec2 */ + /* fn textureDimensions[T : fiu32, L : iu32](texture: texture_cube_array, level: L) -> vec2 */ + /* fn textureDimensions[T : fiu32](texture: texture_multisampled_2d) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_2d) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_2d, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_2d_array) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_2d_array, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_cube) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_cube, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_cube_array) -> vec2 */ + /* fn textureDimensions[L : iu32](texture: texture_depth_cube_array, level: L) -> vec2 */ + /* fn textureDimensions(texture: texture_depth_multisampled_2d) -> vec2 */ + /* fn textureDimensions[F : texel_format, R : read](texture: texture_storage_1d) -> u32 */ + /* fn textureDimensions[F : texel_format, R : read](texture: texture_storage_2d) -> vec2 */ + /* fn textureDimensions[F : texel_format, R : read](texture: texture_storage_2d_array) -> vec2 */ + /* fn textureDimensions[F : texel_format, R : read](texture: texture_storage_3d) -> vec3 */ + /* fn textureDimensions[F : texel_format, R : read](texture: texel_buffer) -> u32 */ + /* fn textureDimensions[F : texel_format, W : writable](texture: texture_storage_1d) -> u32 */ + /* fn textureDimensions[F : texel_format, W : writable](texture: texture_storage_2d) -> vec2 */ + /* fn textureDimensions[F : texel_format, W : writable](texture: texture_storage_2d_array) -> vec2 */ + /* fn textureDimensions[F : texel_format, W : writable](texture: texture_storage_3d) -> vec3 */ + /* fn textureDimensions[F : texel_format, W : writable](texture: texel_buffer) -> u32 */ + /* fn textureDimensions(texture: texture_external) -> vec2 */ + /* num overloads */ 33, + /* overloads */ OverloadIndex(39), + }, + { + /* [96] */ + /* fn textureGather[T : fiu32, C : iu32](@const component: C, texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32](@const component: C, texture: texture_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32, A : iu32](@const component: C, texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32, A : iu32](@const component: C, texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32](@const component: C, texture: texture_cube, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureGather[T : fiu32, C : iu32, A : iu32](@const component: C, texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A) -> vec4 */ + /* fn textureGather(texture: texture_depth_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureGather(texture: texture_depth_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> vec4 */ + /* fn textureGather[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A) -> vec4 */ + /* fn textureGather[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> vec4 */ + /* fn textureGather(texture: texture_depth_cube, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureGather[A : iu32](texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: A) -> vec4 */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(172), + }, + { + /* [97] */ + /* fn textureGatherCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> vec4 */ + /* fn textureGatherCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, @const offset: vec2) -> vec4 */ + /* fn textureGatherCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32) -> vec4 */ + /* fn textureGatherCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32, @const offset: vec2) -> vec4 */ + /* fn textureGatherCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> vec4 */ + /* fn textureGatherCompare[A : iu32](texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: A, depth_ref: f32) -> vec4 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(342), + }, + { + /* [98] */ + /* fn textureNumLayers[T : fiu32](texture: texture_2d_array) -> u32 */ + /* fn textureNumLayers[T : fiu32](texture: texture_cube_array) -> u32 */ + /* fn textureNumLayers(texture: texture_depth_2d_array) -> u32 */ + /* fn textureNumLayers(texture: texture_depth_cube_array) -> u32 */ + /* fn textureNumLayers[F : texel_format, R : read](texture: texture_storage_2d_array) -> u32 */ + /* fn textureNumLayers[F : texel_format, W : writable](texture: texture_storage_2d_array) -> u32 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(348), + }, + { + /* [99] */ + /* fn textureNumLevels[T : fiu32](texture: texture_1d) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_2d) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_2d_array) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_3d) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_cube) -> u32 */ + /* fn textureNumLevels[T : fiu32](texture: texture_cube_array) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_2d) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_2d_array) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_cube) -> u32 */ + /* fn textureNumLevels(texture: texture_depth_cube_array) -> u32 */ + /* num overloads */ 10, + /* overloads */ OverloadIndex(218), + }, + { + /* [100] */ + /* fn textureNumSamples[T : fiu32](texture: texture_multisampled_2d) -> u32 */ + /* fn textureNumSamples(texture: texture_depth_multisampled_2d) -> u32 */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(550), + }, + { + /* [101] */ + /* fn textureSample(texture: texture_1d, sampler: sampler, coords: f32) -> vec4 */ + /* fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> vec4 */ + /* fn textureSample[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A) -> vec4 */ + /* fn textureSample[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> vec4 */ + /* fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3, @const offset: vec3) -> vec4 */ + /* fn textureSample(texture: texture_cube, sampler: sampler, coords: vec3) -> vec4 */ + /* fn textureSample[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A) -> vec4 */ + /* fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2) -> f32 */ + /* fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2, @const offset: vec2) -> f32 */ + /* fn textureSample[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A) -> f32 */ + /* fn textureSample[A : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, @const offset: vec2) -> f32 */ + /* fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3) -> f32 */ + /* fn textureSample[A : iu32](texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: A) -> f32 */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(114), + }, + { + /* [102] */ + /* fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32) -> vec4 */ + /* fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleBias[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, bias: f32) -> vec4 */ + /* fn textureSampleBias[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, bias: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32) -> vec4 */ + /* fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32, @const offset: vec3) -> vec4 */ + /* fn textureSampleBias(texture: texture_cube, sampler: sampler, coords: vec3, bias: f32) -> vec4 */ + /* fn textureSampleBias[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A, bias: f32) -> vec4 */ + /* num overloads */ 8, + /* overloads */ OverloadIndex(318), + }, + { + /* [103] */ + /* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> f32 */ + /* fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32) -> f32 */ + /* fn textureSampleCompare[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> f32 */ + /* fn textureSampleCompare[A : iu32](texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: A, depth_ref: f32) -> f32 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(354), + }, + { + /* [104] */ + /* fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> f32 */ + /* fn textureSampleCompareLevel(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompareLevel[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32) -> f32 */ + /* fn textureSampleCompareLevel[A : iu32](texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: A, depth_ref: f32, @const offset: vec2) -> f32 */ + /* fn textureSampleCompareLevel(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> f32 */ + /* fn textureSampleCompareLevel[A : iu32](texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: A, depth_ref: f32) -> f32 */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(360), + }, + { + /* [105] */ + /* fn textureSampleGrad(texture: texture_2d, sampler: sampler, coords: vec2, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn textureSampleGrad(texture: texture_2d, sampler: sampler, coords: vec2, ddx: vec2, ddy: vec2, @const offset: vec2) -> vec4 */ + /* fn textureSampleGrad[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, ddx: vec2, ddy: vec2) -> vec4 */ + /* fn textureSampleGrad[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, ddx: vec2, ddy: vec2, @const offset: vec2) -> vec4 */ + /* fn textureSampleGrad(texture: texture_3d, sampler: sampler, coords: vec3, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn textureSampleGrad(texture: texture_3d, sampler: sampler, coords: vec3, ddx: vec3, ddy: vec3, @const offset: vec3) -> vec4 */ + /* fn textureSampleGrad(texture: texture_cube, sampler: sampler, coords: vec3, ddx: vec3, ddy: vec3) -> vec4 */ + /* fn textureSampleGrad[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A, ddx: vec3, ddy: vec3) -> vec4 */ + /* num overloads */ 8, + /* overloads */ OverloadIndex(326), + }, + { + /* [106] */ + /* fn textureSampleLevel(texture: texture_1d, sampler: sampler, coords: f32, level: f32) -> vec4 */ + /* fn textureSampleLevel(texture: texture_2d, sampler: sampler, coords: vec2, level: f32) -> vec4 */ + /* fn textureSampleLevel(texture: texture_2d, sampler: sampler, coords: vec2, level: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleLevel[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, level: f32) -> vec4 */ + /* fn textureSampleLevel[A : iu32](texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: A, level: f32, @const offset: vec2) -> vec4 */ + /* fn textureSampleLevel(texture: texture_3d, sampler: sampler, coords: vec3, level: f32) -> vec4 */ + /* fn textureSampleLevel(texture: texture_3d, sampler: sampler, coords: vec3, level: f32, @const offset: vec3) -> vec4 */ + /* fn textureSampleLevel(texture: texture_cube, sampler: sampler, coords: vec3, level: f32) -> vec4 */ + /* fn textureSampleLevel[A : iu32](texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: A, level: f32) -> vec4 */ + /* fn textureSampleLevel[L : iu32](texture: texture_depth_2d, sampler: sampler, coords: vec2, level: L) -> f32 */ + /* fn textureSampleLevel[L : iu32](texture: texture_depth_2d, sampler: sampler, coords: vec2, level: L, @const offset: vec2) -> f32 */ + /* fn textureSampleLevel[A : iu32, L : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, level: L) -> f32 */ + /* fn textureSampleLevel[A : iu32, L : iu32](texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: A, level: L, @const offset: vec2) -> f32 */ + /* fn textureSampleLevel[L : iu32](texture: texture_depth_cube, sampler: sampler, coords: vec3, level: L) -> f32 */ + /* fn textureSampleLevel[A : iu32, L : iu32](texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: A, level: L) -> f32 */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(129), + }, + { + /* [107] */ + /* fn textureSampleBaseClampToEdge(texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 */ + /* fn textureSampleBaseClampToEdge(texture: texture_external, sampler: sampler, coords: vec2) -> vec4 */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(552), + }, + { + /* [108] */ + /* fn textureStore[C : iu32, F : f32_texel_format, W : writable](texture: texture_storage_1d, coords: C, value: vec4) */ + /* fn textureStore[C : iu32, F : f32_texel_format, W : writable](texture: texture_storage_2d, coords: vec2, value: vec4) */ + /* fn textureStore[C : iu32, F : f32_texel_format, W : writable, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A, value: vec4) */ + /* fn textureStore[C : iu32, F : f32_texel_format, W : writable](texture: texture_storage_3d, coords: vec3, value: vec4) */ + /* fn textureStore[C : iu32, F : f32_texel_format, RW : read_write](texture: texel_buffer, coords: C, value: vec4) */ + /* fn textureStore[C : iu32, F : i32_texel_format, W : writable](texture: texture_storage_1d, coords: C, value: vec4) */ + /* fn textureStore[C : iu32, F : i32_texel_format, W : writable](texture: texture_storage_2d, coords: vec2, value: vec4) */ + /* fn textureStore[C : iu32, F : i32_texel_format, W : writable, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A, value: vec4) */ + /* fn textureStore[C : iu32, F : i32_texel_format, W : writable](texture: texture_storage_3d, coords: vec3, value: vec4) */ + /* fn textureStore[C : iu32, F : i32_texel_format, RW : read_write](texture: texel_buffer, coords: C, value: vec4) */ + /* fn textureStore[C : iu32, F : u32_texel_format, W : writable](texture: texture_storage_1d, coords: C, value: vec4) */ + /* fn textureStore[C : iu32, F : u32_texel_format, W : writable](texture: texture_storage_2d, coords: vec2, value: vec4) */ + /* fn textureStore[C : iu32, F : u32_texel_format, W : writable, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A, value: vec4) */ + /* fn textureStore[C : iu32, F : u32_texel_format, W : writable](texture: texture_storage_3d, coords: vec3, value: vec4) */ + /* fn textureStore[C : iu32, F : u32_texel_format, RW : read_write](texture: texel_buffer, coords: C, value: vec4) */ + /* num overloads */ 15, + /* overloads */ OverloadIndex(144), + }, + { + /* [109] */ + /* fn textureLoad[T : fiu32, C : iu32, L : iu32](texture: texture_1d, coords: C, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, L : iu32](texture: texture_2d, coords: vec2, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, A : iu32, L : iu32](texture: texture_2d_array, coords: vec2, array_index: A, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, L : iu32](texture: texture_3d, coords: vec3, level: L) -> vec4 */ + /* fn textureLoad[T : fiu32, C : iu32, S : iu32](texture: texture_multisampled_2d, coords: vec2, sample_index: S) -> vec4 */ + /* fn textureLoad[C : iu32, L : iu32](texture: texture_depth_2d, coords: vec2, level: L) -> f32 */ + /* fn textureLoad[C : iu32, A : iu32, L : iu32](texture: texture_depth_2d_array, coords: vec2, array_index: A, level: L) -> f32 */ + /* fn textureLoad[C : iu32, S : iu32](texture: texture_depth_multisampled_2d, coords: vec2, sample_index: S) -> f32 */ + /* fn textureLoad[C : iu32](texture: texture_external, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, R : read](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, R : read](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, R : read](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, R : read](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, R : read](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, R : read](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, R : read, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, R : read, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, R : read, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, R : read](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, R : read](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, R : read](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, R : read](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, R : read](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, R : read](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, RW : read_write](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, RW : read_write](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, RW : read_write](texture: texture_storage_1d, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, RW : read_write](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, RW : read_write](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, RW : read_write](texture: texture_storage_2d, coords: vec2) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, RW : read_write, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, RW : read_write, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, RW : read_write, A : iu32](texture: texture_storage_2d_array, coords: vec2, array_index: A) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, RW : read_write](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, RW : read_write](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, RW : read_write](texture: texture_storage_3d, coords: vec3) -> vec4 */ + /* fn textureLoad[C : iu32, F : f32_texel_format, RW : read_write](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : i32_texel_format, RW : read_write](texture: texel_buffer, coords: C) -> vec4 */ + /* fn textureLoad[C : iu32, F : u32_texel_format, RW : read_write](texture: texel_buffer, coords: C) -> vec4 */ + /* num overloads */ 39, + /* overloads */ OverloadIndex(0), + }, + { + /* [110] */ + /* fn inputAttachmentLoad[T : fiu32](input_attachment: input_attachment) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(621), + }, + { + /* [111] */ + /* fn atomicLoad[T : iu32, S : workgroup_or_storage](ptr, read_write>) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(622), + }, + { + /* [112] */ + /* fn atomicStore[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(623), + }, + { + /* [113] */ + /* fn atomicAdd[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [114] */ + /* fn atomicSub[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [115] */ + /* fn atomicMax[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [116] */ + /* fn atomicMin[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [117] */ + /* fn atomicAnd[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [118] */ + /* fn atomicOr[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [119] */ + /* fn atomicXor[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [120] */ + /* fn atomicExchange[T : iu32, S : workgroup_or_storage](ptr, read_write>, T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(624), + }, + { + /* [121] */ + /* fn atomicCompareExchangeWeak[T : iu32, S : workgroup_or_storage](ptr, read_write>, T, T) -> __atomic_compare_exchange_result */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(625), + }, + { + /* [122] */ + /* fn subgroupBallot(bool) -> vec4 */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(626), + }, + { + /* [123] */ + /* fn subgroupElect() -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(627), + }, + { + /* [124] */ + /* fn subgroupBroadcast[T : fiu32_f16](value: T, @const sourceLaneIndex: iu32) -> T */ + /* fn subgroupBroadcast[N : num, T : fiu32_f16](value: vec, @const sourceLaneIndex: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(554), + }, + { + /* [125] */ + /* fn subgroupBroadcastFirst[T : fiu32_f16](value: T) -> T */ + /* fn subgroupBroadcastFirst[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [126] */ + /* fn subgroupShuffle[T : fiu32_f16](value: T, sourceLaneIndex: iu32) -> T */ + /* fn subgroupShuffle[N : num, T : fiu32_f16](value: vec, sourceLaneIndex: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(554), + }, + { + /* [127] */ + /* fn subgroupShuffleXor[T : fiu32_f16](value: T, mask: u32) -> T */ + /* fn subgroupShuffleXor[N : num, T : fiu32_f16](value: vec, mask: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(558), + }, + { + /* [128] */ + /* fn subgroupShuffleUp[T : fiu32_f16](value: T, delta: u32) -> T */ + /* fn subgroupShuffleUp[N : num, T : fiu32_f16](value: vec, delta: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(560), + }, + { + /* [129] */ + /* fn subgroupShuffleDown[T : fiu32_f16](value: T, delta: u32) -> T */ + /* fn subgroupShuffleDown[N : num, T : fiu32_f16](value: vec, delta: u32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(560), + }, + { + /* [130] */ + /* fn subgroupAdd[T : fiu32_f16](value: T) -> T */ + /* fn subgroupAdd[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [131] */ + /* fn subgroupInclusiveAdd[T : fiu32_f16](value: T) -> T */ + /* fn subgroupInclusiveAdd[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [132] */ + /* fn subgroupExclusiveAdd[T : fiu32_f16](value: T) -> T */ + /* fn subgroupExclusiveAdd[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [133] */ + /* fn subgroupMul[T : fiu32_f16](value: T) -> T */ + /* fn subgroupMul[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [134] */ + /* fn subgroupInclusiveMul[T : fiu32_f16](value: T) -> T */ + /* fn subgroupInclusiveMul[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [135] */ + /* fn subgroupExclusiveMul[T : fiu32_f16](value: T) -> T */ + /* fn subgroupExclusiveMul[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [136] */ + /* fn subgroupAnd[T : iu32](value: T) -> T */ + /* fn subgroupAnd[N : num, T : iu32](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(562), + }, + { + /* [137] */ + /* fn subgroupOr[T : iu32](value: T) -> T */ + /* fn subgroupOr[N : num, T : iu32](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(562), + }, + { + /* [138] */ + /* fn subgroupXor[T : iu32](value: T) -> T */ + /* fn subgroupXor[N : num, T : iu32](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(562), + }, + { + /* [139] */ + /* fn subgroupMin[T : fiu32_f16](value: T) -> T */ + /* fn subgroupMin[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [140] */ + /* fn subgroupMax[T : fiu32_f16](value: T) -> T */ + /* fn subgroupMax[N : num, T : fiu32_f16](value: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(556), + }, + { + /* [141] */ + /* fn subgroupAll(bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(628), + }, + { + /* [142] */ + /* fn subgroupAny(bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(628), + }, + { + /* [143] */ + /* fn quadBroadcast[T : fiu32_f16](e: T, @const id: iu32) -> T */ + /* fn quadBroadcast[N : num, T : fiu32_f16](e: vec, @const id: iu32) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(564), + }, + { + /* [144] */ + /* fn quadSwapX[T : fiu32_f16](e: T) -> T */ + /* fn quadSwapX[N : num, T : fiu32_f16](e: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(566), + }, + { + /* [145] */ + /* fn quadSwapY[T : fiu32_f16](e: T) -> T */ + /* fn quadSwapY[N : num, T : fiu32_f16](e: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(566), + }, + { + /* [146] */ + /* fn quadSwapDiagonal[T : fiu32_f16](e: T) -> T */ + /* fn quadSwapDiagonal[N : num, T : fiu32_f16](e: vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(566), + }, + { + /* [147] */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num](ptr, readable>, u32, @const bool, @test_value(8) u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num, AC : num](ptr, readable>, u32, @const bool, @test_value(8) u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : i8, C : num, R : num](ptr, readable>, u32, @const bool, @test_value(8) u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : u8, C : num, R : num](ptr, readable>, u32, @const bool, @test_value(8) u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : i8, C : num, R : num, AC : num](ptr, readable>, u32, @const bool, @test_value(8) u32) -> T */ + /* fn subgroupMatrixLoad>[K : subgroup_matrix_kind, S : u8, C : num, R : num, AC : num](ptr, readable>, u32, @const bool, @test_value(8) u32) -> T */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(366), + }, + { + /* [148] */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num](ptr, writable>, u32, subgroup_matrix, @const bool, @test_value(8) u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : fiu32_f16, C : num, R : num, AC : num](ptr, writable>, u32, subgroup_matrix, @const bool, @test_value(8) u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : i8, C : num, R : num](ptr, writable>, u32, subgroup_matrix, @const bool, @test_value(8) u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : u8, C : num, R : num](ptr, writable>, u32, subgroup_matrix, @const bool, @test_value(8) u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : i8, C : num, R : num, AC : num](ptr, writable>, u32, subgroup_matrix, @const bool, @test_value(8) u32) */ + /* fn subgroupMatrixStore[K : subgroup_matrix_kind, S : u8, C : num, R : num, AC : num](ptr, writable>, u32, subgroup_matrix, @const bool, @test_value(8) u32) */ + /* num overloads */ 6, + /* overloads */ OverloadIndex(372), + }, + { + /* [149] */ + /* fn subgroupMatrixMultiply[T : f16, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiply[T : f32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiply[T : iu8, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiply[T : iu32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(388), + }, + { + /* [150] */ + /* fn subgroupMatrixMultiplyAccumulate[T : f16, TR : f32_f16, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiplyAccumulate[T : f32, TR : f32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiplyAccumulate[T : iu8, TR : iu32_iu8, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* fn subgroupMatrixMultiplyAccumulate[T : iu32, TR : iu32, C : num, R : num, K : num](subgroup_matrix, subgroup_matrix, subgroup_matrix) -> subgroup_matrix */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(392), + }, + { + /* [151] */ + /* fn subgroupMatrixScalarAdd[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](m: subgroup_matrix, @test_value(8) s: T) -> subgroup_matrix */ + /* fn subgroupMatrixScalarAdd[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, @test_value(8) s: i32) -> subgroup_matrix */ + /* fn subgroupMatrixScalarAdd[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, @test_value(8) s: u32) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(422), + }, + { + /* [152] */ + /* fn subgroupMatrixScalarSubtract[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](m: subgroup_matrix, @test_value(8) s: T) -> subgroup_matrix */ + /* fn subgroupMatrixScalarSubtract[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, @test_value(8) s: i32) -> subgroup_matrix */ + /* fn subgroupMatrixScalarSubtract[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, @test_value(8) s: u32) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(422), + }, + { + /* [153] */ + /* fn subgroupMatrixScalarMultiply[K : subgroup_matrix_kind, T : fiu32_f16, C : num, R : num](m: subgroup_matrix, @test_value(8) s: T) -> subgroup_matrix */ + /* fn subgroupMatrixScalarMultiply[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, @test_value(8) s: i32) -> subgroup_matrix */ + /* fn subgroupMatrixScalarMultiply[K : subgroup_matrix_kind, C : num, R : num](m: subgroup_matrix, @test_value(8) s: u32) -> subgroup_matrix */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(422), + }, + { + /* [154] */ + /* fn bufferView[R : read, AS : uniform_or_storage, N : num](ptr, R>, offset: u32) -> ptr */ + /* fn bufferView[R : read, AS : uniform_or_storage, N : num](ptr, R>, offset: i32) -> ptr */ + /* fn bufferView[W : read_write, AS : workgroup_or_storage, N : num](ptr, W>, offset: u32) -> ptr */ + /* fn bufferView[W : read_write, AS : workgroup_or_storage, N : num](ptr, W>, offset: i32) -> ptr */ + /* fn bufferView[R : read, AS : uniform_or_storage](ptr, offset: u32) -> ptr */ + /* fn bufferView[R : read, AS : uniform_or_storage](ptr, offset: i32) -> ptr */ + /* fn bufferView[W : read_write, AS : workgroup_or_storage](ptr, offset: u32) -> ptr */ + /* fn bufferView[W : read_write, AS : workgroup_or_storage](ptr, offset: i32) -> ptr */ + /* num overloads */ 8, + /* overloads */ OverloadIndex(334), + }, + { + /* [155] */ + /* fn bufferLength[R : read, AS : uniform_or_storage, N : num](ptr, R>) -> u32 */ + /* fn bufferLength[W : read_write, AS : workgroup_or_storage, N : num](ptr, W>) -> u32 */ + /* fn bufferLength[R : read, AS : uniform_or_storage](ptr) -> u32 */ + /* fn bufferLength[W : read_write, AS : workgroup_or_storage](ptr) -> u32 */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(396), + }, + { + /* [156] */ + /* fn print[T : concrete_scalar](T) */ + /* fn print[N : num, T : concrete_scalar](vec) */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(568), + }, + { + /* [157] */ + /* fn __tint_materialize[T](T) -> T */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(629), + }, + { + /* [158] */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource>[K : fiu32, I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* fn hasResource[I : iu32](index: I) -> bool */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(184), + }, + { + /* [159] */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource>[K : fiu32, I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* fn getResource[I : iu32](index: I) -> T */ + /* num overloads */ 12, + /* overloads */ OverloadIndex(196), + }, +}; + +constexpr IntrinsicInfo kUnaryOperators[] = { + { + /* [0] */ + /* op &[S : address_space, T, A : access](ref) -> ptr */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(630), + }, + { + /* [1] */ + /* op *[S : address_space, T, A : access](ptr) -> ref */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(631), + }, + { + /* [2] */ + /* op !(bool) -> bool */ + /* op ![N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(570), + }, + { + /* [3] */ + /* op ~[T : ia_iu32](T) -> T */ + /* op ~[T : ia_iu32, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(572), + }, + { + /* [4] */ + /* op -[T : fia_fi32_f16](T) -> T */ + /* op -[T : fia_fi32_f16, N : num](vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(574), + }, +}; +constexpr uint8_t kUnaryOperatorAnd = 0; +constexpr uint8_t kUnaryOperatorStar = 1; +constexpr uint8_t kUnaryOperatorNot = 2; +constexpr uint8_t kUnaryOperatorComplement = 3; +constexpr uint8_t kUnaryOperatorMinus = 4; + +constexpr IntrinsicInfo kBinaryOperators[] = { + { + /* [0] */ + /* op +[T : fia_fiu32_f16](T, T) -> T */ + /* op +[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* op +[T : fia_fiu32_f16, N : num](vec, T) -> vec */ + /* op +[T : fia_fiu32_f16, N : num](T, vec) -> vec */ + /* op +[T : fa_f32_f16, N : num, M : num](mat, mat) -> mat */ + /* num overloads */ 5, + /* overloads */ OverloadIndex(378), + }, + { + /* [1] */ + /* op -[T : fia_fiu32_f16](T, T) -> T */ + /* op -[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* op -[T : fia_fiu32_f16, N : num](vec, T) -> vec */ + /* op -[T : fia_fiu32_f16, N : num](T, vec) -> vec */ + /* op -[T : fa_f32_f16, N : num, M : num](mat, mat) -> mat */ + /* num overloads */ 5, + /* overloads */ OverloadIndex(383), + }, + { + /* [2] */ + /* op *[T : fia_fiu32_f16](T, T) -> T */ + /* op *[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* op *[T : fia_fiu32_f16, N : num](vec, T) -> vec */ + /* op *[T : fia_fiu32_f16, N : num](T, vec) -> vec */ + /* op *[T : fa_f32_f16, N : num, M : num](T, mat) -> mat */ + /* op *[T : fa_f32_f16, N : num, M : num](mat, T) -> mat */ + /* op *[T : fa_f32_f16, C : num, R : num](mat, vec) -> vec */ + /* op *[T : fa_f32_f16, C : num, R : num](vec, mat) -> vec */ + /* op *[T : fa_f32_f16, K : num, C : num, R : num](mat, mat) -> mat */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(228), + }, + { + /* [3] */ + /* op /[T : fia_fiu32_f16](T, T) -> T */ + /* op /[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* op /[T : fia_fiu32_f16, N : num](vec, T) -> vec */ + /* op /[T : fia_fiu32_f16, N : num](T, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(400), + }, + { + /* [4] */ + /* op %[T : fia_fiu32_f16](T, T) -> T */ + /* op %[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* op %[T : fia_fiu32_f16, N : num](vec, T) -> vec */ + /* op %[T : fia_fiu32_f16, N : num](T, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(404), + }, + { + /* [5] */ + /* op ^[T : ia_iu32](T, T) -> T */ + /* op ^[T : ia_iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(576), + }, + { + /* [6] */ + /* op &(bool, bool) -> bool */ + /* op &[N : num](vec, vec) -> vec */ + /* op &[T : ia_iu32](T, T) -> T */ + /* op &[T : ia_iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(408), + }, + { + /* [7] */ + /* op |(bool, bool) -> bool */ + /* op |[N : num](vec, vec) -> vec */ + /* op |[T : ia_iu32](T, T) -> T */ + /* op |[T : ia_iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 4, + /* overloads */ OverloadIndex(412), + }, + { + /* [8] */ + /* op &&(bool, bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(632), + }, + { + /* [9] */ + /* op ||(bool, bool) -> bool */ + /* num overloads */ 1, + /* overloads */ OverloadIndex(633), + }, + { + /* [10] */ + /* op ==[T : scalar](T, T) -> bool */ + /* op ==[T : scalar, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(578), + }, + { + /* [11] */ + /* op !=[T : scalar](T, T) -> bool */ + /* op !=[T : scalar, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(580), + }, + { + /* [12] */ + /* op <[T : fia_fiu32_f16](T, T) -> bool */ + /* op <[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(582), + }, + { + /* [13] */ + /* op >[T : fia_fiu32_f16](T, T) -> bool */ + /* op >[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(584), + }, + { + /* [14] */ + /* op <=[T : fia_fiu32_f16](T, T) -> bool */ + /* op <=[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(586), + }, + { + /* [15] */ + /* op >=[T : fia_fiu32_f16](T, T) -> bool */ + /* op >=[T : fia_fiu32_f16, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(588), + }, + { + /* [16] */ + /* op <<[T : ia_iu32](T, u32) -> T */ + /* op <<[T : ia_iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(590), + }, + { + /* [17] */ + /* op >>[T : ia_iu32](T, u32) -> T */ + /* op >>[T : ia_iu32, N : num](vec, vec) -> vec */ + /* num overloads */ 2, + /* overloads */ OverloadIndex(592), + }, +}; +constexpr uint8_t kBinaryOperatorPlus = 0; +constexpr uint8_t kBinaryOperatorMinus = 1; +constexpr uint8_t kBinaryOperatorStar = 2; +constexpr uint8_t kBinaryOperatorDivide = 3; +constexpr uint8_t kBinaryOperatorModulo = 4; +constexpr uint8_t kBinaryOperatorXor = 5; +constexpr uint8_t kBinaryOperatorAnd = 6; +constexpr uint8_t kBinaryOperatorOr = 7; +constexpr uint8_t kBinaryOperatorLogicalAnd = 8; +constexpr uint8_t kBinaryOperatorLogicalOr = 9; +constexpr uint8_t kBinaryOperatorEqual = 10; +constexpr uint8_t kBinaryOperatorNotEqual = 11; +constexpr uint8_t kBinaryOperatorLessThan = 12; +constexpr uint8_t kBinaryOperatorGreaterThan = 13; +constexpr uint8_t kBinaryOperatorLessThanEqual = 14; +constexpr uint8_t kBinaryOperatorGreaterThanEqual = 15; +constexpr uint8_t kBinaryOperatorShiftLeft = 16; +constexpr uint8_t kBinaryOperatorShiftRight = 17; + +constexpr IntrinsicInfo kConstructorsAndConverters[] = { + { + /* [0] */ + /* ctor i32() -> i32 */ + /* ctor i32(i32) -> i32 */ + /* conv i32[T : scalar_no_i32](T) -> i32 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(425), + }, + { + /* [1] */ + /* ctor u32() -> u32 */ + /* ctor u32(u32) -> u32 */ + /* conv u32[T : scalar_no_u32](T) -> u32 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(428), + }, + { + /* [2] */ + /* ctor f32() -> f32 */ + /* ctor f32(f32) -> f32 */ + /* conv f32[T : scalar_no_f32](T) -> f32 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(431), + }, + { + /* [3] */ + /* ctor f16() -> f16 */ + /* ctor f16(f16) -> f16 */ + /* conv f16[T : scalar_no_f16](T) -> f16 */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(434), + }, + { + /* [4] */ + /* ctor bool() -> bool */ + /* ctor bool(bool) -> bool */ + /* conv bool[T : scalar_no_bool](T) -> bool */ + /* num overloads */ 3, + /* overloads */ OverloadIndex(437), + }, + { + /* [5] */ + /* ctor vec2() -> vec2 */ + /* ctor vec2() -> vec2 */ + /* ctor vec2(vec2) -> vec2 */ + /* ctor vec2[T : scalar](vec2) -> vec2 */ + /* ctor vec2(T) -> vec2 */ + /* ctor vec2[T : scalar](T) -> vec2 */ + /* ctor vec2(x: T, y: T) -> vec2 */ + /* ctor vec2[T : scalar](x: T, y: T) -> vec2 */ + /* conv vec2[U : scalar_no_f32](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_f16](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_i32](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_u32](vec2) -> vec2 */ + /* conv vec2[U : scalar_no_bool](vec2) -> vec2 */ + /* num overloads */ 13, + /* overloads */ OverloadIndex(159), + }, + { + /* [6] */ + /* ctor vec3() -> vec3 */ + /* ctor vec3() -> vec3 */ + /* ctor vec3(vec3) -> vec3 */ + /* ctor vec3[T : scalar](vec3) -> vec3 */ + /* ctor vec3(T) -> vec3 */ + /* ctor vec3[T : scalar](T) -> vec3 */ + /* ctor vec3(x: T, y: T, z: T) -> vec3 */ + /* ctor vec3[T : scalar](x: T, y: T, z: T) -> vec3 */ + /* ctor vec3(xy: vec2, z: T) -> vec3 */ + /* ctor vec3[T : scalar](xy: vec2, z: T) -> vec3 */ + /* ctor vec3(x: T, yz: vec2) -> vec3 */ + /* ctor vec3[T : scalar](x: T, yz: vec2) -> vec3 */ + /* conv vec3[U : scalar_no_f32](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_f16](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_i32](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_u32](vec3) -> vec3 */ + /* conv vec3[U : scalar_no_bool](vec3) -> vec3 */ + /* num overloads */ 17, + /* overloads */ OverloadIndex(97), + }, + { + /* [7] */ + /* ctor vec4() -> vec4 */ + /* ctor vec4() -> vec4 */ + /* ctor vec4(vec4) -> vec4 */ + /* ctor vec4[T : scalar](vec4) -> vec4 */ + /* ctor vec4(T) -> vec4 */ + /* ctor vec4[T : scalar](T) -> vec4 */ + /* ctor vec4(x: T, y: T, z: T, w: T) -> vec4 */ + /* ctor vec4[T : scalar](x: T, y: T, z: T, w: T) -> vec4 */ + /* ctor vec4(xy: vec2, z: T, w: T) -> vec4 */ + /* ctor vec4[T : scalar](xy: vec2, z: T, w: T) -> vec4 */ + /* ctor vec4(x: T, yz: vec2, w: T) -> vec4 */ + /* ctor vec4[T : scalar](x: T, yz: vec2, w: T) -> vec4 */ + /* ctor vec4(x: T, y: T, zw: vec2) -> vec4 */ + /* ctor vec4[T : scalar](x: T, y: T, zw: vec2) -> vec4 */ + /* ctor vec4(xy: vec2, zw: vec2) -> vec4 */ + /* ctor vec4[T : scalar](xy: vec2, zw: vec2) -> vec4 */ + /* ctor vec4(xyz: vec3, w: T) -> vec4 */ + /* ctor vec4[T : scalar](xyz: vec3, w: T) -> vec4 */ + /* ctor vec4(x: T, zyw: vec3) -> vec4 */ + /* ctor vec4[T : scalar](x: T, zyw: vec3) -> vec4 */ + /* conv vec4[U : scalar_no_f32](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_f16](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_i32](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_u32](vec4) -> vec4 */ + /* conv vec4[U : scalar_no_bool](vec4) -> vec4 */ + /* num overloads */ 25, + /* overloads */ OverloadIndex(72), + }, + { + /* [8] */ + /* ctor mat2x2() -> mat2x2 */ + /* ctor mat2x2(mat2x2) -> mat2x2 */ + /* ctor mat2x2[T : fa_f32_f16](mat2x2) -> mat2x2 */ + /* ctor mat2x2(T, T, T, T) -> mat2x2 */ + /* ctor mat2x2[T : fa_f32_f16](T, T, T, T) -> mat2x2 */ + /* ctor mat2x2(vec2, vec2) -> mat2x2 */ + /* ctor mat2x2[T : fa_f32_f16](vec2, vec2) -> mat2x2 */ + /* conv mat2x2(mat2x2) -> mat2x2 */ + /* conv mat2x2(mat2x2) -> mat2x2 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(237), + }, + { + /* [9] */ + /* ctor mat2x3() -> mat2x3 */ + /* ctor mat2x3(mat2x3) -> mat2x3 */ + /* ctor mat2x3[T : fa_f32_f16](mat2x3) -> mat2x3 */ + /* ctor mat2x3(T, T, T, T, T, T) -> mat2x3 */ + /* ctor mat2x3[T : fa_f32_f16](T, T, T, T, T, T) -> mat2x3 */ + /* ctor mat2x3(vec3, vec3) -> mat2x3 */ + /* ctor mat2x3[T : fa_f32_f16](vec3, vec3) -> mat2x3 */ + /* conv mat2x3(mat2x3) -> mat2x3 */ + /* conv mat2x3(mat2x3) -> mat2x3 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(246), + }, + { + /* [10] */ + /* ctor mat2x4() -> mat2x4 */ + /* ctor mat2x4(mat2x4) -> mat2x4 */ + /* ctor mat2x4[T : fa_f32_f16](mat2x4) -> mat2x4 */ + /* ctor mat2x4(T, T, T, T, T, T, T, T) -> mat2x4 */ + /* ctor mat2x4[T : fa_f32_f16](T, T, T, T, T, T, T, T) -> mat2x4 */ + /* ctor mat2x4(vec4, vec4) -> mat2x4 */ + /* ctor mat2x4[T : fa_f32_f16](vec4, vec4) -> mat2x4 */ + /* conv mat2x4(mat2x4) -> mat2x4 */ + /* conv mat2x4(mat2x4) -> mat2x4 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(255), + }, + { + /* [11] */ + /* ctor mat3x2() -> mat3x2 */ + /* ctor mat3x2(mat3x2) -> mat3x2 */ + /* ctor mat3x2[T : fa_f32_f16](mat3x2) -> mat3x2 */ + /* ctor mat3x2(T, T, T, T, T, T) -> mat3x2 */ + /* ctor mat3x2[T : fa_f32_f16](T, T, T, T, T, T) -> mat3x2 */ + /* ctor mat3x2(vec2, vec2, vec2) -> mat3x2 */ + /* ctor mat3x2[T : fa_f32_f16](vec2, vec2, vec2) -> mat3x2 */ + /* conv mat3x2(mat3x2) -> mat3x2 */ + /* conv mat3x2(mat3x2) -> mat3x2 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(264), + }, + { + /* [12] */ + /* ctor mat3x3() -> mat3x3 */ + /* ctor mat3x3(mat3x3) -> mat3x3 */ + /* ctor mat3x3[T : fa_f32_f16](mat3x3) -> mat3x3 */ + /* ctor mat3x3(T, T, T, T, T, T, T, T, T) -> mat3x3 */ + /* ctor mat3x3[T : fa_f32_f16](T, T, T, T, T, T, T, T, T) -> mat3x3 */ + /* ctor mat3x3(vec3, vec3, vec3) -> mat3x3 */ + /* ctor mat3x3[T : fa_f32_f16](vec3, vec3, vec3) -> mat3x3 */ + /* conv mat3x3(mat3x3) -> mat3x3 */ + /* conv mat3x3(mat3x3) -> mat3x3 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(273), + }, + { + /* [13] */ + /* ctor mat3x4() -> mat3x4 */ + /* ctor mat3x4(mat3x4) -> mat3x4 */ + /* ctor mat3x4[T : fa_f32_f16](mat3x4) -> mat3x4 */ + /* ctor mat3x4(T, T, T, T, T, T, T, T, T, T, T, T) -> mat3x4 */ + /* ctor mat3x4[T : fa_f32_f16](T, T, T, T, T, T, T, T, T, T, T, T) -> mat3x4 */ + /* ctor mat3x4(vec4, vec4, vec4) -> mat3x4 */ + /* ctor mat3x4[T : fa_f32_f16](vec4, vec4, vec4) -> mat3x4 */ + /* conv mat3x4(mat3x4) -> mat3x4 */ + /* conv mat3x4(mat3x4) -> mat3x4 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(282), + }, + { + /* [14] */ + /* ctor mat4x2() -> mat4x2 */ + /* ctor mat4x2(mat4x2) -> mat4x2 */ + /* ctor mat4x2[T : fa_f32_f16](mat4x2) -> mat4x2 */ + /* ctor mat4x2(T, T, T, T, T, T, T, T) -> mat4x2 */ + /* ctor mat4x2[T : fa_f32_f16](T, T, T, T, T, T, T, T) -> mat4x2 */ + /* ctor mat4x2(vec2, vec2, vec2, vec2) -> mat4x2 */ + /* ctor mat4x2[T : fa_f32_f16](vec2, vec2, vec2, vec2) -> mat4x2 */ + /* conv mat4x2(mat4x2) -> mat4x2 */ + /* conv mat4x2(mat4x2) -> mat4x2 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(291), + }, + { + /* [15] */ + /* ctor mat4x3() -> mat4x3 */ + /* ctor mat4x3(mat4x3) -> mat4x3 */ + /* ctor mat4x3[T : fa_f32_f16](mat4x3) -> mat4x3 */ + /* ctor mat4x3(T, T, T, T, T, T, T, T, T, T, T, T) -> mat4x3 */ + /* ctor mat4x3[T : fa_f32_f16](T, T, T, T, T, T, T, T, T, T, T, T) -> mat4x3 */ + /* ctor mat4x3(vec3, vec3, vec3, vec3) -> mat4x3 */ + /* ctor mat4x3[T : fa_f32_f16](vec3, vec3, vec3, vec3) -> mat4x3 */ + /* conv mat4x3(mat4x3) -> mat4x3 */ + /* conv mat4x3(mat4x3) -> mat4x3 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(300), + }, + { + /* [16] */ + /* ctor mat4x4() -> mat4x4 */ + /* ctor mat4x4(mat4x4) -> mat4x4 */ + /* ctor mat4x4[T : fa_f32_f16](mat4x4) -> mat4x4 */ + /* ctor mat4x4(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> mat4x4 */ + /* ctor mat4x4[T : fa_f32_f16](T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> mat4x4 */ + /* ctor mat4x4(vec4, vec4, vec4, vec4) -> mat4x4 */ + /* ctor mat4x4[T : fa_f32_f16](vec4, vec4, vec4, vec4) -> mat4x4 */ + /* conv mat4x4(mat4x4) -> mat4x4 */ + /* conv mat4x4(mat4x4) -> mat4x4 */ + /* num overloads */ 9, + /* overloads */ OverloadIndex(309), + }, +}; + +} // anonymous namespace + +const core::intrinsic::TableData Dialect::kData{ + /* templates */ kTemplates, + /* type_matcher_indices */ kMatcherIndices, + /* type_matchers */ kTypeMatchers, + /* number_matchers */ kNumberMatchers, + /* parameters */ kParameters, + /* overloads */ kOverloads, + /* const_eval_functions */ kConstEvalFunctions, + /* ctor_conv */ kConstructorsAndConverters, + /* builtins */ kBuiltins, + /* binary '+' */ kBinaryOperators[kBinaryOperatorPlus], + /* binary '-' */ kBinaryOperators[kBinaryOperatorMinus], + /* binary '*' */ kBinaryOperators[kBinaryOperatorStar], + /* binary '/' */ kBinaryOperators[kBinaryOperatorDivide], + /* binary '%' */ kBinaryOperators[kBinaryOperatorModulo], + /* binary '^' */ kBinaryOperators[kBinaryOperatorXor], + /* binary '&' */ kBinaryOperators[kBinaryOperatorAnd], + /* binary '|' */ kBinaryOperators[kBinaryOperatorOr], + /* binary '&&' */ kBinaryOperators[kBinaryOperatorLogicalAnd], + /* binary '||' */ kBinaryOperators[kBinaryOperatorLogicalOr], + /* binary '==' */ kBinaryOperators[kBinaryOperatorEqual], + /* binary '!=' */ kBinaryOperators[kBinaryOperatorNotEqual], + /* binary '<' */ kBinaryOperators[kBinaryOperatorLessThan], + /* binary '>' */ kBinaryOperators[kBinaryOperatorGreaterThan], + /* binary '<=' */ kBinaryOperators[kBinaryOperatorLessThanEqual], + /* binary '>=' */ kBinaryOperators[kBinaryOperatorGreaterThanEqual], + /* binary '<<' */ kBinaryOperators[kBinaryOperatorShiftLeft], + /* binary '>>' */ kBinaryOperators[kBinaryOperatorShiftRight], + /* unary '!' */ kUnaryOperators[kUnaryOperatorNot], + /* unary '~' */ kUnaryOperators[kUnaryOperatorComplement], + /* unary '-' */ kUnaryOperators[kUnaryOperatorMinus], + /* unary '*' */ kUnaryOperators[kUnaryOperatorStar], + /* unary '&' */ kUnaryOperators[kUnaryOperatorAnd], +}; + +} // namespace tint::wgsl::intrinsic + +// clang-format on diff --git a/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/dialect.h b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/dialect.h new file mode 100644 index 000000000..35d5218f7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/dialect.h @@ -0,0 +1,59 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INTRINSIC_DIALECT_H_ +#define SRC_TINT_LANG_WGSL_INTRINSIC_DIALECT_H_ + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/intrinsic/ctor_conv.h" + +namespace tint::wgsl::intrinsic { + +/// Dialect holds the intrinsic table data and types for the WGSL dialect +struct Dialect { + /// The dialect's intrinsic table data + static const core::intrinsic::TableData kData; + + /// The dialect's builtin function enumerator + using BuiltinFn = wgsl::BuiltinFn; + + /// The dialect's type constructor / convertor enumerator + using CtorConv = wgsl::intrinsic::CtorConv; + + /// @returns the name of the builtin function @p fn + /// @param fn the builtin function + static std::string_view ToString(BuiltinFn fn) { return str(fn); } + + /// @returns the name of the type constructor / convertor @p ty + /// @param ty the type constructor / convertor + static std::string_view ToString(CtorConv ty) { return str(ty); } +}; + +} // namespace tint::wgsl::intrinsic + +#endif // SRC_TINT_LANG_WGSL_INTRINSIC_DIALECT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/type_matchers.h b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/type_matchers.h new file mode 100644 index 000000000..35df47fd0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/intrinsic/type_matchers.h @@ -0,0 +1,46 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_INTRINSIC_TYPE_MATCHERS_H_ +#define SRC_TINT_LANG_WGSL_INTRINSIC_TYPE_MATCHERS_H_ + +#include "src/tint/lang/core/intrinsic/table_data.h" + +namespace tint::wgsl::intrinsic { + +inline bool MatchConstructible(core::intrinsic::MatchState&, const core::type::Type* ty) { + return ty->IsConstructible(); +} + +inline const core::type::Type* BuildConstructible(core::intrinsic::MatchState&, + const core::type::Type* ty) { + return ty; +} + +} // namespace tint::wgsl::intrinsic + +#endif // SRC_TINT_LANG_WGSL_INTRINSIC_TYPE_MATCHERS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.cc b/3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.cc new file mode 100644 index 000000000..701cc192a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.cc @@ -0,0 +1,57 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ir/builtin_call.h" + +#include + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::wgsl::ir::BuiltinCall); + +namespace tint::wgsl::ir { + +BuiltinCall::BuiltinCall(Id id, + core::ir::InstructionResult* result, + BuiltinFn fn, + VectorRef arguments) + : Base(id, result, arguments), fn_(fn) { + flags_.Add(Flag::kSequenced); + TINT_ASSERT(fn != BuiltinFn::kNone); +} + +BuiltinCall::~BuiltinCall() = default; + +BuiltinCall* BuiltinCall::Clone(core::ir::CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto new_args = ctx.Clone(Args()); + return ctx.ir.CreateInstruction(new_result, fn_, new_args); +} + +} // namespace tint::wgsl::ir diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.h b/3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.h new file mode 100644 index 000000000..3a5d91f7c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ir/builtin_call.h @@ -0,0 +1,79 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_IR_BUILTIN_CALL_H_ +#define SRC_TINT_LANG_WGSL_IR_BUILTIN_CALL_H_ + +#include + +#include "src/tint/lang/core/intrinsic/table_data.h" +#include "src/tint/lang/core/ir/builtin_call.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/intrinsic/dialect.h" +#include "src/tint/utils/rtti/castable.h" + +namespace tint::wgsl::ir { + +/// A WGSL builtin call instruction in the IR. +class BuiltinCall : public Castable { + public: + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param fn the builtin function + /// @param args the conversion arguments + BuiltinCall(Id id, + core::ir::InstructionResult* result, + BuiltinFn fn, + VectorRef args = tint::Empty); + + ~BuiltinCall() override; + + /// @copydoc core::ir::Instruction::Clone() + BuiltinCall* Clone(core::ir::CloneContext& ctx) override; + + /// @returns the builtin function + BuiltinFn Func() const { return fn_; } + + /// @returns the identifier for the function + size_t FuncId() const override { return static_cast(fn_); } + + /// @returns the friendly name for the instruction + std::string FriendlyName() const override { return std::string("wgsl.") + str(fn_); } + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override { + return intrinsic::Dialect::kData; + } + + private: + BuiltinFn fn_; +}; + +} // namespace tint::wgsl::ir + +#endif // SRC_TINT_LANG_WGSL_IR_BUILTIN_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ir/unary.cc b/3rdparty/dawn/src/tint/lang/wgsl/ir/unary.cc new file mode 100644 index 000000000..9ee0b257b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ir/unary.cc @@ -0,0 +1,55 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ir/unary.h" + +#include "src/tint/lang/core/ir/clone_context.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/wgsl/intrinsic/dialect.h" + +TINT_INSTANTIATE_TYPEINFO(tint::wgsl::ir::Unary); + +namespace tint::wgsl::ir { + +Unary::Unary(Id id) : Base(id) {} + +Unary::Unary(Id id, core::ir::InstructionResult* result, core::UnaryOp op, core::ir::Value* val) + : Base(id, result, op, val) {} + +Unary::~Unary() = default; + +Unary* Unary::Clone(core::ir::CloneContext& ctx) { + auto* new_result = ctx.Clone(Result()); + auto* val = ctx.Remap(Val()); + return ctx.ir.CreateInstruction(new_result, Op(), val); +} + +const core::intrinsic::TableData& Unary::TableData() const { + return wgsl::intrinsic::Dialect::kData; +} + +} // namespace tint::wgsl::ir diff --git a/3rdparty/dawn/src/tint/lang/wgsl/ir/unary.h b/3rdparty/dawn/src/tint/lang/wgsl/ir/unary.h new file mode 100644 index 000000000..ff4cf5853 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/ir/unary.h @@ -0,0 +1,63 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_IR_UNARY_H_ +#define SRC_TINT_LANG_WGSL_IR_UNARY_H_ + +#include "src/tint/lang/core/ir/unary.h" + +namespace tint::wgsl::ir { + +/// A WGSL-dialect unary instruction in the IR. +class Unary final : public Castable { + public: + /// The offset in Operands() for the value + static constexpr size_t kValueOperandOffset = 0; + + /// Constructor (no results, no operands) + /// @param id the instruction id + explicit Unary(Id id); + + /// Constructor + /// @param id the instruction id + /// @param result the result value + /// @param op the unary operator + /// @param val the input value for the instruction + Unary(Id id, core::ir::InstructionResult* result, core::UnaryOp op, core::ir::Value* val); + + ~Unary() override; + + /// @copydoc core::ir::Instruction::Clone() + Unary* Clone(core::ir::CloneContext& ctx) override; + + /// @returns the table data to validate this builtin + const core::intrinsic::TableData& TableData() const override; +}; + +} // namespace tint::wgsl::ir + +#endif // SRC_TINT_LANG_WGSL_IR_UNARY_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/program/program.cc b/3rdparty/dawn/src/tint/lang/wgsl/program/program.cc new file mode 100644 index 000000000..31eac9ca8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/program/program.cc @@ -0,0 +1,126 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/program/program.h" + +#include + +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint { +namespace { + +std::string DefaultPrinter(const Program&) { + return ""; +} + +} // namespace + +Program::Printer Program::printer = DefaultPrinter; + +Program::Program() = default; + +Program::Program(Program&& program) + : constants_(std::move(program.constants_)), + ast_nodes_(std::move(program.ast_nodes_)), + sem_nodes_(std::move(program.sem_nodes_)), + ast_(std::move(program.ast_)), + sem_(std::move(program.sem_)), + symbols_(std::move(program.symbols_)), + diagnostics_(std::move(program.diagnostics_)), + is_valid_(program.is_valid_) { + program.AssertNotMoved(); + program.moved_ = true; +} + +Program::Program(ProgramBuilder&& builder) { + is_valid_ = builder.IsValid(); + + // The above must be called *before* the calls to std::move() below + constants_ = std::move(builder.constants); + ast_nodes_ = std::move(builder.ASTNodes()); + sem_nodes_ = std::move(builder.SemNodes()); + ast_ = &builder.AST(); // ast::Module is actually a heap allocation. + sem_ = std::move(builder.Sem()); + symbols_ = std::move(builder.Symbols()); + diagnostics_.Add(std::move(builder.Diagnostics())); + builder.MarkAsMoved(); + + if (!is_valid_ && !diagnostics_.ContainsErrors()) { + // If the builder claims to be invalid, then we really should have an error + // message generated. If we find a situation where the program is not valid + // and there are no errors reported, add one here. + diagnostics_.AddError(Source{}) << "invalid program generated"; + } +} + +Program::~Program() = default; + +Program& Program::operator=(Program&& program) { + program.AssertNotMoved(); + program.moved_ = true; + moved_ = false; + constants_ = std::move(program.constants_); + ast_nodes_ = std::move(program.ast_nodes_); + sem_nodes_ = std::move(program.sem_nodes_); + ast_ = std::move(program.ast_); + sem_ = std::move(program.sem_); + symbols_ = std::move(program.symbols_); + diagnostics_ = std::move(program.diagnostics_); + is_valid_ = program.is_valid_; + return *this; +} + +bool Program::IsValid() const { + AssertNotMoved(); + return is_valid_; +} + +const core::type::Type* Program::TypeOf(const ast::Expression* expr) const { + return tint::Switch( + Sem().Get(expr), // + [](const sem::ValueExpression* ty_expr) { return ty_expr->Type(); }, + [](const sem::TypeExpression* ty_expr) { return ty_expr->Type(); }); +} + +const core::type::Type* Program::TypeOf(const ast::Variable* var) const { + auto* sem = Sem().Get(var); + return sem ? sem->Type() : nullptr; +} + +const core::type::Type* Program::TypeOf(const ast::TypeDecl* type_decl) const { + return Sem().Get(type_decl); +} + +void Program::AssertNotMoved() const { + TINT_ASSERT(!moved_); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/lang/wgsl/program/program.h b/3rdparty/dawn/src/tint/lang/wgsl/program/program.h new file mode 100644 index 000000000..4c13e211f --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/program/program.h @@ -0,0 +1,158 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_PROGRAM_PROGRAM_H_ +#define SRC_TINT_LANG_WGSL_PROGRAM_PROGRAM_H_ + +#include + +#include "src/tint/lang/core/constant/manager.h" +#include "src/tint/lang/core/type/manager.h" +#include "src/tint/lang/wgsl/ast/function.h" +#include "src/tint/lang/wgsl/sem/info.h" +#include "src/tint/utils/symbol/symbol_table.h" + +// Forward Declarations +namespace tint::ast { +class Module; +} // namespace tint::ast + +namespace tint { + +/// Program holds the AST, Type information and SymbolTable for a tint program. +class Program { + public: + /// ASTNodeAllocator is an alias to BlockAllocator + using ASTNodeAllocator = BlockAllocator; + + /// SemNodeAllocator is an alias to BlockAllocator + using SemNodeAllocator = BlockAllocator; + + /// Constructor + Program(); + + /// Move constructor + /// @param rhs the Program to move + Program(Program&& rhs); + + /// Move constructor from builder + /// @param builder the builder used to construct the program + explicit Program(ProgramBuilder&& builder); + + /// Destructor + ~Program(); + + /// Move assignment operator + /// @param rhs the Program to move + /// @return this Program + Program& operator=(Program&& rhs); + + /// @returns a reference to the program's types + const core::type::Manager& Types() const { + AssertNotMoved(); + return constants_.types; + } + + /// @returns a reference to the program's AST nodes storage + const ASTNodeAllocator& ASTNodes() const { + AssertNotMoved(); + return ast_nodes_; + } + + /// @returns a reference to the program's AST root Module + const ast::Module& AST() const { + AssertNotMoved(); + return *ast_; + } + + /// @returns a reference to the program's semantic info + const sem::Info& Sem() const { + AssertNotMoved(); + return sem_; + } + + /// @returns a reference to the program's SymbolTable + const SymbolTable& Symbols() const { + AssertNotMoved(); + return symbols_; + } + + /// @returns a reference to the program's diagnostics + const diag::List& Diagnostics() const { + AssertNotMoved(); + return diagnostics_; + } + + /// @returns true if the program has no error diagnostics and is not missing + /// information + bool IsValid() const; + + /// Helper for returning the resolved semantic type of the expression `expr`. + /// @param expr the AST expression + /// @return the resolved semantic type for the expression, or nullptr if the + /// expression has no resolved type. + const core::type::Type* TypeOf(const ast::Expression* expr) const; + + /// Helper for returning the resolved semantic type of the variable `var`. + /// @param var the AST variable + /// @return the resolved semantic type for the variable, or nullptr if the + /// variable has no resolved type. + const core::type::Type* TypeOf(const ast::Variable* var) const; + + /// Helper for returning the resolved semantic type of the AST type + /// declaration `type_decl`. + /// @param type_decl the AST type declaration + /// @return the resolved semantic type for the type declaration, or nullptr if + /// the type declaration has no resolved type. + const core::type::Type* TypeOf(const ast::TypeDecl* type_decl) const; + + /// A function that can be used to print a program + using Printer = std::string (*)(const Program&); + + /// The Program printer used for testing and debugging. + static Printer printer; + + private: + Program(const Program&) = delete; + + /// Asserts that the program has not been moved. + void AssertNotMoved() const; + + core::constant::Manager constants_; + ASTNodeAllocator ast_nodes_; + SemNodeAllocator sem_nodes_; + ast::Module* ast_ = nullptr; + sem::Info sem_; + SymbolTable symbols_{}; + diag::List diagnostics_; + bool is_valid_ = false; // Not valid until it is built + bool moved_ = false; +}; + +} // namespace tint + +#endif // SRC_TINT_LANG_WGSL_PROGRAM_PROGRAM_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.cc b/3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.cc new file mode 100644 index 000000000..49a546402 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.cc @@ -0,0 +1,82 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/program/program_builder.h" + +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/rtti/switch.h" + +using namespace tint::core::number_suffixes; // NOLINT + +namespace tint { + +ProgramBuilder::ProgramBuilder() = default; + +ProgramBuilder::ProgramBuilder(ProgramBuilder&& rhs) + : Builder(std::move(rhs)), + constants(std::move(rhs.constants)), + sem_nodes_(std::move(rhs.sem_nodes_)), + sem_(std::move(rhs.sem_)) {} + +ProgramBuilder::~ProgramBuilder() = default; + +ProgramBuilder& ProgramBuilder::operator=(ProgramBuilder&& rhs) { + *static_cast(this) = std::move(rhs); + constants = std::move(rhs.constants); + sem_nodes_ = std::move(rhs.sem_nodes_); + sem_ = std::move(rhs.sem_); + return *this; +} + +void ProgramBuilder::AssertNotMoved() const { + TINT_ASSERT(!moved_) << "Attempting to use ProgramBuilder after it has been moved"; +} + +const core::type::Type* ProgramBuilder::TypeOf(const ast::Expression* expr) const { + return tint::Switch( + Sem().Get(expr), // + [](const sem::ValueExpression* e) { return e->Type(); }, + [](const sem::TypeExpression* e) { return e->Type(); }); +} + +const core::type::Type* ProgramBuilder::TypeOf(const ast::Variable* var) const { + auto* sem = Sem().Get(var); + return sem ? sem->Type() : nullptr; +} + +const core::type::Type* ProgramBuilder::TypeOf(const ast::TypeDecl* type_decl) const { + return Sem().Get(type_decl); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.h b/3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.h new file mode 100644 index 000000000..b1592d656 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/program/program_builder.h @@ -0,0 +1,203 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_PROGRAM_PROGRAM_BUILDER_H_ +#define SRC_TINT_LANG_WGSL_PROGRAM_PROGRAM_BUILDER_H_ + +#include +#include +#include + +#include "src/tint/api/common/override_id.h" + +#include "src/tint/lang/core/constant/manager.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/lang/core/type/array.h" +#include "src/tint/lang/core/type/bool.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/f16.h" +#include "src/tint/lang/core/type/f32.h" +#include "src/tint/lang/core/type/i32.h" +#include "src/tint/lang/core/type/matrix.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/sampler_kind.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/core/type/u32.h" +#include "src/tint/lang/core/type/vector.h" +#include "src/tint/lang/core/type/void.h" +#include "src/tint/lang/wgsl/ast/builder.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/sem/array_count.h" +#include "src/tint/lang/wgsl/sem/struct.h" +#include "src/tint/utils/text/string.h" + +#ifdef CURRENTLY_IN_TINT_PUBLIC_HEADER +#error "internal tint header being #included from tint.h" +#endif + +namespace tint { + +/// ProgramBuilder is a mutable builder for a Program. +/// To construct a Program, populate the builder and then `std::move` it to a +/// Program. +class ProgramBuilder : public ast::Builder { + public: + /// SemNodeAllocator is an alias to BlockAllocator + using SemNodeAllocator = BlockAllocator; + + /// Constructor + ProgramBuilder(); + + /// Move constructor + /// @param rhs the builder to move + ProgramBuilder(ProgramBuilder&& rhs); + + /// Destructor + ~ProgramBuilder(); + + /// Move assignment operator + /// @param rhs the builder to move + /// @return this builder + ProgramBuilder& operator=(ProgramBuilder&& rhs); + + /// @returns a reference to the program's types + core::type::Manager& Types() { + AssertNotMoved(); + return constants.types; + } + + /// @returns a reference to the program's types + const core::type::Manager& Types() const { + AssertNotMoved(); + return constants.types; + } + + /// @returns a reference to the program's semantic nodes storage + SemNodeAllocator& SemNodes() { + AssertNotMoved(); + return sem_nodes_; + } + + /// @returns a reference to the program's semantic nodes storage + const SemNodeAllocator& SemNodes() const { + AssertNotMoved(); + return sem_nodes_; + } + + /// @returns a reference to the program's AST root Module + ast::Module& AST() { + AssertNotMoved(); + return *ast_; + } + + /// @returns a reference to the program's semantic info + sem::Info& Sem() { + AssertNotMoved(); + return sem_; + } + + /// @returns a reference to the program's semantic info + const sem::Info& Sem() const { + AssertNotMoved(); + return sem_; + } + + /// Overlay Builder::create() overloads + using Builder::create; + + /// Creates a new sem::Node owned by the ProgramBuilder. + /// When the ProgramBuilder is destructed, the sem::Node will also be destructed. + /// @param args the arguments to pass to the constructor + /// @returns the node pointer + template + requires(tint::traits::IsTypeOrDerived && + !tint::traits::IsTypeOrDerived) + T* create(ARGS&&... args) { + AssertNotMoved(); + return sem_nodes_.Create(std::forward(args)...); + } + + /// Creates a new core::type::Node owned by the ProgramBuilder. + /// When the ProgramBuilder is destructed, owned ProgramBuilder and the returned node will also + /// be destructed. If T derives from core::type::UniqueNode, then the calling create() for the + /// same `T` and arguments will return the same pointer. + /// @param args the arguments to pass to the constructor + /// @returns the new, or existing node + template + requires(traits::IsTypeOrDerived) + T* create(ARGS&&... args) { + AssertNotMoved(); + return constants.types.Get(std::forward(args)...); + } + + /// Helper for returning the resolved semantic type of the expression `expr`. + /// @note As the Resolver is run when the Program is built, this will only be + /// useful for the Resolver itself and tests that use their own Resolver. + /// @param expr the AST expression + /// @return the resolved semantic type for the expression, or nullptr if the + /// expression has no resolved type. + const core::type::Type* TypeOf(const ast::Expression* expr) const; + + /// Helper for returning the resolved semantic type of the variable `var`. + /// @note As the Resolver is run when the Program is built, this will only be + /// useful for the Resolver itself and tests that use their own Resolver. + /// @param var the AST variable + /// @return the resolved semantic type for the variable, or nullptr if the + /// variable has no resolved type. + const core::type::Type* TypeOf(const ast::Variable* var) const; + + /// Helper for returning the resolved semantic type of the AST type + /// declaration `type_decl`. + /// @note As the Resolver is run when the Program is built, this will only be + /// useful for the Resolver itself and tests that use their own Resolver. + /// @param type_decl the AST type declaration + /// @return the resolved semantic type for the type declaration, or nullptr if + /// the type declaration has no resolved type. + const core::type::Type* TypeOf(const ast::TypeDecl* type_decl) const; + + /// The constants manager + core::constant::Manager constants; + + protected: + /// Asserts that the builder has not been moved. + void AssertNotMoved() const; + + private: + SemNodeAllocator sem_nodes_; + sem::Info sem_; +}; + +} // namespace tint + +#endif // SRC_TINT_LANG_WGSL_PROGRAM_PROGRAM_BUILDER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.cc new file mode 100644 index 000000000..ee2b4e354 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.cc @@ -0,0 +1,270 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reader/lower/lower.h" + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/ir/builtin_call.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::wgsl::reader { +namespace { + +core::BuiltinFn Convert(wgsl::BuiltinFn fn) { +#define CASE(NAME) \ + case wgsl::BuiltinFn::NAME: \ + return core::BuiltinFn::NAME; + + switch (fn) { + CASE(kAbs) + CASE(kAcos) + CASE(kAcosh) + CASE(kAll) + CASE(kAny) + CASE(kArrayLength) + CASE(kAsin) + CASE(kAsinh) + CASE(kAtan) + CASE(kAtan2) + CASE(kAtanh) + CASE(kCeil) + CASE(kClamp) + CASE(kCos) + CASE(kCosh) + CASE(kCountLeadingZeros) + CASE(kCountOneBits) + CASE(kCountTrailingZeros) + CASE(kCross) + CASE(kDegrees) + CASE(kDeterminant) + CASE(kDistance) + CASE(kDot) + CASE(kDot4I8Packed) + CASE(kDot4U8Packed) + CASE(kDpdx) + CASE(kDpdxCoarse) + CASE(kDpdxFine) + CASE(kDpdy) + CASE(kDpdyCoarse) + CASE(kDpdyFine) + CASE(kExp) + CASE(kExp2) + CASE(kExtractBits) + CASE(kFaceForward) + CASE(kFirstLeadingBit) + CASE(kFirstTrailingBit) + CASE(kFloor) + CASE(kFma) + CASE(kFract) + CASE(kFrexp) + CASE(kFwidth) + CASE(kFwidthCoarse) + CASE(kFwidthFine) + CASE(kInsertBits) + CASE(kInverseSqrt) + CASE(kLdexp) + CASE(kLength) + CASE(kLog) + CASE(kLog2) + CASE(kMax) + CASE(kMin) + CASE(kMix) + CASE(kModf) + CASE(kNormalize) + CASE(kPack2X16Float) + CASE(kPack2X16Snorm) + CASE(kPack2X16Unorm) + CASE(kPack4X8Snorm) + CASE(kPack4X8Unorm) + CASE(kPack4XI8) + CASE(kPack4XU8) + CASE(kPack4XI8Clamp) + CASE(kPack4XU8Clamp) + CASE(kPow) + CASE(kQuantizeToF16) + CASE(kRadians) + CASE(kReflect) + CASE(kRefract) + CASE(kReverseBits) + CASE(kRound) + CASE(kSaturate) + CASE(kSelect) + CASE(kSign) + CASE(kSin) + CASE(kSinh) + CASE(kSmoothstep) + CASE(kSqrt) + CASE(kStep) + CASE(kStorageBarrier) + CASE(kTan) + CASE(kTanh) + CASE(kTranspose) + CASE(kTrunc) + CASE(kUnpack2X16Float) + CASE(kUnpack2X16Snorm) + CASE(kUnpack2X16Unorm) + CASE(kUnpack4X8Snorm) + CASE(kUnpack4X8Unorm) + CASE(kUnpack4XI8) + CASE(kUnpack4XU8) + CASE(kWorkgroupBarrier) + CASE(kTextureBarrier) + CASE(kTextureDimensions) + CASE(kTextureGather) + CASE(kTextureGatherCompare) + CASE(kTextureNumLayers) + CASE(kTextureNumLevels) + CASE(kTextureNumSamples) + CASE(kTextureSample) + CASE(kTextureSampleBias) + CASE(kTextureSampleCompare) + CASE(kTextureSampleCompareLevel) + CASE(kTextureSampleGrad) + CASE(kTextureSampleLevel) + CASE(kTextureSampleBaseClampToEdge) + CASE(kTextureStore) + CASE(kTextureLoad) + CASE(kAtomicLoad) + CASE(kAtomicStore) + CASE(kAtomicAdd) + CASE(kAtomicSub) + CASE(kAtomicMax) + CASE(kAtomicMin) + CASE(kAtomicAnd) + CASE(kAtomicOr) + CASE(kAtomicXor) + CASE(kAtomicExchange) + CASE(kAtomicCompareExchangeWeak) + CASE(kSubgroupBallot) + CASE(kSubgroupElect) + CASE(kSubgroupBroadcast) + CASE(kSubgroupBroadcastFirst) + CASE(kSubgroupShuffle) + CASE(kSubgroupShuffleXor) + CASE(kSubgroupShuffleUp) + CASE(kSubgroupShuffleDown) + CASE(kInputAttachmentLoad) + CASE(kSubgroupAdd) + CASE(kSubgroupInclusiveAdd) + CASE(kSubgroupExclusiveAdd) + CASE(kSubgroupMul) + CASE(kSubgroupInclusiveMul) + CASE(kSubgroupExclusiveMul) + CASE(kSubgroupAnd) + CASE(kSubgroupOr) + CASE(kSubgroupXor) + CASE(kSubgroupMin) + CASE(kSubgroupMax) + CASE(kSubgroupAll) + CASE(kSubgroupAny) + CASE(kQuadBroadcast) + CASE(kQuadSwapX) + CASE(kQuadSwapY) + CASE(kQuadSwapDiagonal) + CASE(kSubgroupMatrixLoad) + CASE(kSubgroupMatrixStore) + CASE(kSubgroupMatrixMultiply) + CASE(kSubgroupMatrixMultiplyAccumulate) + CASE(kSubgroupMatrixScalarAdd) + CASE(kSubgroupMatrixScalarSubtract) + CASE(kSubgroupMatrixScalarMultiply) + CASE(kPrint) + CASE(kHasResource) + CASE(kGetResource) + CASE(kBufferView) + CASE(kBufferLength) + case tint::wgsl::BuiltinFn::kBitcast: // should lower to ir::Bitcast + case tint::wgsl::BuiltinFn::kWorkgroupUniformLoad: // should be handled in Lower() + case tint::wgsl::BuiltinFn::kTintMaterialize: + case tint::wgsl::BuiltinFn::kNone: + break; + } + TINT_ICE() << "unhandled builtin function: " << fn; +} + +} // namespace + +Result Lower(core::ir::Module& mod) { + TINT_CHECK_RESULT( + core::ir::ValidateAndDumpIfNeeded(mod, "wgsl.Lower", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllow8BitIntegers, + })); + + core::ir::Builder b{mod}; + core::type::Manager& ty{mod.Types()}; + for (auto* inst : mod.Instructions()) { + if (auto* call = inst->As()) { + switch (call->Func()) { + case BuiltinFn::kWorkgroupUniformLoad: { + auto* param0 = call->Args()[0]; + TINT_ASSERT(param0->Type()->Is()); + auto* storeType = param0->Type()->As()->StoreType(); + // Replace: + // %value = call workgroupUniformLoad %ptr + // With: + // call workgroupBarrier + // %value = {load || atomicLoad} &ptr + // call workgroupBarrier + b.InsertBefore(call, [&] { + b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier); + if (storeType->Is()) { + b.CallWithResult(call->DetachResult(), core::BuiltinFn::kAtomicLoad, + param0); + } else { + b.LoadWithResult(call->DetachResult(), param0); + } + b.Call(ty.void_(), core::BuiltinFn::kWorkgroupBarrier); + }); + break; + } + default: { + Vector args(call->Args()); + auto* replacement = b.CallWithResult(call->DetachResult(), + Convert(call->Func()), std::move(args)); + if (!call->ExplicitTemplateParams().IsEmpty()) { + replacement->SetExplicitTemplateParams(call->ExplicitTemplateParams()); + } + call->ReplaceWith(replacement); + break; + } + } + call->Destroy(); + } + } + return Success; +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.h new file mode 100644 index 000000000..146cba989 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/lower/lower.h @@ -0,0 +1,43 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_LOWER_LOWER_H_ +#define SRC_TINT_LANG_WGSL_READER_LOWER_LOWER_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/result.h" + +namespace tint::wgsl::reader { + +/// Lower converts a WGSL-dialect IR module to a core-dialect IR module +/// @param mod the IR module +/// @return the result of the operation +Result Lower(core::ir::Module& mod); + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_LOWER_LOWER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/options.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/options.h new file mode 100644 index 000000000..622d3ca39 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/options.h @@ -0,0 +1,47 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_OPTIONS_H_ +#define SRC_TINT_LANG_WGSL_READER_OPTIONS_H_ + +#include "src/tint/lang/wgsl/allowed_features.h" +#include "src/tint/utils/reflection.h" + +namespace tint::wgsl::reader { + +/// Configuration options used for reading WGSL. +struct Options { + /// The extensions and language features that are allowed to be used. + AllowedFeatures allowed_features{}; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField(). + TINT_REFLECT(Options, allowed_features); +}; + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_OPTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.cc new file mode 100644 index 000000000..b27d36999 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.cc @@ -0,0 +1,157 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reader/parser/classify_template_args.h" + +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::wgsl::reader { + +namespace { + +/// If the token at index @p idx is a '>>', '>=' or '>>=', then the token is split into two, with +/// the first being '>', otherwise MaybeSplit() will be a no-op. +/// @param tokens the vector of tokens +/// @param idx the index of the token to (maybe) split +void MaybeSplit(std::vector& tokens, size_t idx) { + auto* cur = &tokens[idx]; + auto* next = &tokens[idx + 1]; + TINT_ASSERT(cur); + TINT_ASSERT(next); + switch (cur->type()) { + case Token::Type::kShiftRight: // '>>' + TINT_ASSERT(next->type() == Token::Type::kPlaceholder); + cur->SetType(Token::Type::kGreaterThan); + next->SetType(Token::Type::kGreaterThan); + break; + case Token::Type::kGreaterThanEqual: // '>=' + TINT_ASSERT(next->type() == Token::Type::kPlaceholder); + cur->SetType(Token::Type::kGreaterThan); + next->SetType(Token::Type::kEqual); + break; + case Token::Type::kShiftRightEqual: // '>>=' + TINT_ASSERT(next->type() == Token::Type::kPlaceholder); + cur->SetType(Token::Type::kGreaterThan); + next->SetType(Token::Type::kGreaterThanEqual); + break; + default: + break; + } +} + +} // namespace + +void ClassifyTemplateArguments(std::vector& tokens) { + const size_t count = tokens.size(); + + // The current expression nesting depth. + // Each '(', '[' increments the depth. + // Each ')', ']' decrements the depth. + uint64_t expr_depth = 0; + + // A stack of '<' tokens. + // Used to pair '<' and '>' tokens at the same expression depth. + struct StackEntry { + Token* token; // A pointer to the opening '<' token + uint64_t expr_depth; // The value of 'expr_depth' for the opening '<' + }; + Vector stack; + + for (size_t i = 0; i < count - 1; i++) { + switch (tokens[i].type()) { + case Token::Type::kIdentifier: + case Token::Type::kVar: { + auto& next = tokens[i + 1]; + if (next.type() == Token::Type::kLessThan) { + // ident '<' + // Push this '<' to the stack, along with the current nesting expr_depth. + stack.Push(StackEntry{&tokens[i + 1], expr_depth}); + i++; // Skip the '<' + } + break; + } + case Token::Type::kGreaterThan: // '>' + case Token::Type::kShiftRight: // '>>' + case Token::Type::kGreaterThanEqual: // '>=' + case Token::Type::kShiftRightEqual: // '>>=' + if (!stack.IsEmpty() && stack.Back().expr_depth == expr_depth) { + // '<' and '>' at same expr_depth, and no terminating tokens in-between. + // Consider both as a template argument list. + MaybeSplit(tokens, i); + stack.Pop().token->SetType(Token::Type::kTemplateArgsLeft); + tokens[i].SetType(Token::Type::kTemplateArgsRight); + } + break; + + case Token::Type::kParenLeft: // '(' + case Token::Type::kBracketLeft: // '[' + // Entering a nested expression + expr_depth++; + break; + + case Token::Type::kParenRight: // ')' + case Token::Type::kBracketRight: // ']' + // Exiting a nested expression + // Pop the stack until we return to the current expression expr_depth + while (!stack.IsEmpty() && stack.Back().expr_depth == expr_depth) { + stack.Pop(); + } + if (expr_depth > 0) { + expr_depth--; + } + break; + + case Token::Type::kSemicolon: // ';' + case Token::Type::kBraceLeft: // '{' + case Token::Type::kEqual: // '=' + case Token::Type::kColon: // ':' + // Expression terminating tokens. No opening template list can hold these tokens, so + // clear the stack and expression depth. + expr_depth = 0; + stack.Clear(); + break; + + case Token::Type::kOrOr: // '||' + case Token::Type::kAndAnd: // '&&' + // Treat 'a < b || c > d' as a logical binary operator of two comparison operators + // instead of a single template argument 'b||c'. + // Use parentheses around 'b||c' to parse as a template argument list. + while (!stack.IsEmpty() && stack.Back().expr_depth == expr_depth) { + stack.Pop(); + } + break; + + default: + break; + } + } +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.h new file mode 100644 index 000000000..1b80efab1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/classify_template_args.h @@ -0,0 +1,41 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_PARSER_CLASSIFY_TEMPLATE_ARGS_H_ +#define SRC_TINT_LANG_WGSL_READER_PARSER_CLASSIFY_TEMPLATE_ARGS_H_ + +#include + +#include "src/tint/lang/wgsl/reader/parser/token.h" + +namespace tint::wgsl::reader { + +void ClassifyTemplateArguments(std::vector& tokens); + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_PARSER_CLASSIFY_TEMPLATE_ARGS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/detail.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/detail.h new file mode 100644 index 000000000..74287e1d0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/detail.h @@ -0,0 +1,77 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_PARSER_DETAIL_H_ +#define SRC_TINT_LANG_WGSL_READER_PARSER_DETAIL_H_ + +#include + +namespace tint::wgsl::reader::detail { + +/// OperatorArrow is a traits helper for ParserImpl::Expect::operator->() and +/// ParserImpl::Maybe::operator->() so that pointer types are automatically +/// dereferenced. This simplifies usage by allowing +/// `result.value->field` +/// to be written as: +/// `result->field` +/// As well as reducing the amount of code, using the operator->() asserts that +/// the Expect or Maybe is not in an error state before dereferencing. +template +struct OperatorArrow { + /// type resolves to the return type for the operator->() + using type = T*; + /// @param val the value held by `ParserImpl::Expect` or + /// `ParserImpl::Maybe`. + /// @return a pointer to `val` + static inline T* ptr(T& val) { return &val; } +}; + +/// OperatorArrow template specialization for std::unique_ptr<>. +template +struct OperatorArrow> { + /// type resolves to the return type for the operator->() + using type = T*; + /// @param val the value held by `ParserImpl::Expect` or + /// `ParserImpl::Maybe`. + /// @return the raw pointer held by `val`. + static inline T* ptr(std::unique_ptr& val) { return val.get(); } +}; + +/// OperatorArrow template specialization for T*. +template +struct OperatorArrow { + /// type resolves to the return type for the operator->() + using type = T*; + /// @param val the value held by `ParserImpl::Expect` or + /// `ParserImpl::Maybe`. + /// @return `val`. + static inline T* ptr(T* val) { return val; } +}; + +} // namespace tint::wgsl::reader::detail + +#endif // SRC_TINT_LANG_WGSL_READER_PARSER_DETAIL_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.cc new file mode 100644 index 000000000..6e5fa0645 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.cc @@ -0,0 +1,1343 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "src/tint/lang/wgsl/reader/parser/lexer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/number.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/strconv/parse_num.h" +#include "src/tint/utils/text/unicode.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::wgsl::reader { +namespace { + +// Unicode parsing code assumes that the size of a single std::string element is +// 1 byte. +static_assert(sizeof(decltype(tint::Source::FileContent::data[0])) == sizeof(uint8_t), + "tint::wgsl::reader requires the size of a std::string element " + "to be a single byte"); + +// A token is ~80bytes. The 4k here comes from looking at the number of tokens in the benchmark +// programs and being a bit bigger then those need (atan2-const-eval is the outlier here). +static constexpr size_t kDefaultListSize = 4092; + +bool read_blankspace(std::string_view str, + size_t i, + bool* is_blankspace, + uint32_t* blankspace_size) { + // See https://www.w3.org/TR/WGSL/#blankspace + + auto* utf8 = reinterpret_cast(&str[i]); + auto [cp, n] = tint::utf8::Decode(utf8, str.size() - i); + + if (n == 0) { + return false; + } + + static const auto kSpace = tint::CodePoint(0x0020); // space + static const auto kHTab = tint::CodePoint(0x0009); // horizontal tab + static const auto kL2R = tint::CodePoint(0x200E); // left-to-right mark + static const auto kR2L = tint::CodePoint(0x200F); // right-to-left mark + + if (cp == kSpace || cp == kHTab || cp == kL2R || cp == kR2L) { + *is_blankspace = true; + *blankspace_size = static_cast(n); + return true; + } + + *is_blankspace = false; + return true; +} + +uint32_t dec_value(char c) { + if (c >= '0' && c <= '9') { + return static_cast(c - '0'); + } + return 0; +} + +uint32_t hex_value(char c) { + if (c >= '0' && c <= '9') { + return static_cast(c - '0'); + } + if (c >= 'a' && c <= 'f') { + return 0xA + static_cast(c - 'a'); + } + if (c >= 'A' && c <= 'F') { + return 0xA + static_cast(c - 'A'); + } + return 0; +} + +} // namespace + +Lexer::Lexer(const Source::File* file) : file_(file), location_{1, 1} {} + +Lexer::~Lexer() = default; + +std::vector Lexer::Lex() { + std::vector tokens; + tokens.reserve(kDefaultListSize); + + while (true) { + tokens.emplace_back(next()); + if (tokens.back().IsEof() || tokens.back().IsError()) { + break; + } + + // If the token can be split, we insert a placeholder element(s) into the stream to hold the + // split character. + size_t num_placeholders = tokens.back().NumPlaceholders(); + for (size_t i = 0; i < num_placeholders; i++) { + auto src = tokens.back().source(); + src.range.begin.column++; + tokens.emplace_back(Token::Type::kPlaceholder, src); + } + } + return tokens; +} + +std::string_view Lexer::line() const { + if (file_->content.lines.size() == 0) { + static const char* empty_string = ""; + return empty_string; + } + return file_->content.lines[location_.line - 1]; +} + +uint32_t Lexer::pos() const { + return location_.column - 1; +} + +uint32_t Lexer::length() const { + return static_cast(line().size()); +} + +const char& Lexer::at(uint32_t pos) const { + const auto& l = line(); + // Unlike for std::string, if pos == line().size(), indexing `l[pos]` is UB for + // std::string_view. + if (pos >= l.size()) { + static const char zero = 0; + return zero; + } + return l[pos]; +} + +// This pointer is passed into std::from_chars which requires a pointer beyond the end of contiguous +// range, not an end iterator, so will always hit this warning. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +const char* Lexer::line_end() const { + return &(line()[length() - 1]) + 1; +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +std::string_view Lexer::substr(uint32_t offset, uint32_t count) { + return line().substr(offset, count); +} + +void Lexer::advance(uint32_t offset) { + location_.column += offset; +} + +void Lexer::set_pos(uint32_t pos) { + location_.column = pos + 1; +} + +void Lexer::advance_line() { + location_.line++; + location_.column = 1; +} + +bool Lexer::is_eof() const { + return location_.line >= file_->content.lines.size() && pos() >= length(); +} + +bool Lexer::is_eol() const { + return pos() >= length(); +} + +Token Lexer::next() { + if (auto t = skip_blankspace_and_comments(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (auto t = try_hex_float(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (auto t = try_hex_integer(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (auto t = try_float(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (auto t = try_integer(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (auto t = try_ident(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (auto t = try_punctuation(); t.has_value() && !t->IsUninitialized()) { + return std::move(t.value()); + } + + if (is_null()) { + return {Token::Type::kError, begin_source(), "null character found"}; + } + if (is_bom()) { + return {Token::Type::kError, begin_source(), "invalid character (UTF-8 BOM) found"}; + } + return {Token::Type::kError, begin_source(), "invalid character found"}; +} + +Source Lexer::begin_source() const { + Source src{}; + src.file = file_; + src.range.begin = location_; + src.range.end = location_; + return src; +} + +void Lexer::end_source(Source& src) const { + src.range.end = location_; +} + +bool Lexer::is_null() const { + return (pos() < length()) && (at(pos()) == 0); +} + +bool Lexer::is_bom() const { + if (pos() + 2 >= length()) { + return false; + } + return (static_cast(at(pos())) == 0xEF && + static_cast(at(pos() + 1)) == 0xBB && + static_cast(at(pos() + 2)) == 0xBF); +} + +bool Lexer::is_digit(char ch) const { + return std::isdigit(static_cast(ch)) != 0; +} +bool Lexer::is_hex(char ch) const { + return std::isxdigit(static_cast(ch)) != 0; +} + +bool Lexer::matches(uint32_t pos, std::string_view sub_string) { + if (pos >= length()) { + return false; + } + return substr(pos, static_cast(sub_string.size())) == sub_string; +} + +bool Lexer::matches(uint32_t pos, char ch) { + if (pos >= length()) { + return false; + } + return line()[pos] == ch; +} + +std::optional Lexer::skip_blankspace_and_comments() { + for (;;) { + auto loc = location_; + while (!is_eof()) { + if (is_eol()) { + advance_line(); + continue; + } + + bool is_blankspace; + uint32_t blankspace_size; + if (!read_blankspace(line(), pos(), &is_blankspace, &blankspace_size)) { + return Token{Token::Type::kError, begin_source(), "invalid UTF-8"}; + } + if (!is_blankspace) { + break; + } + + advance(blankspace_size); + } + + auto t = skip_comment(); + if (t.has_value() && !t->IsUninitialized()) { + return t; + } + + // If the cursor didn't advance we didn't remove any blankspace + // so we're done. + if (loc == location_) { + break; + } + } + if (is_eof()) { + return Token{Token::Type::kEOF, begin_source()}; + } + + return {}; +} + +std::optional Lexer::skip_comment() { + auto unicode_length = [](std::string_view str, size_t i) { + auto* utf8 = reinterpret_cast(&str[i]); + auto [_, n] = tint::utf8::Decode(utf8, str.size() - i); + return uint32_t(n); + }; + + if (matches(pos(), "//")) { + // Line comment: ignore everything until the end of line. + while (!is_eol()) { + if (is_null()) { + return Token{Token::Type::kError, begin_source(), "null character found"}; + } + auto n = unicode_length(line(), pos()); + if (n == 0) { + return Token{Token::Type::kError, begin_source(), "invalid UTF-8"}; + } + advance(n); + } + return {}; + } + + if (matches(pos(), "/*")) { + // Block comment: ignore everything until the closing '*/' token. + + // Record source location of the initial '/*' + auto source = begin_source(); + source.range.end.column += 1; + + advance(2); + + int depth = 1; + while (!is_eof() && depth > 0) { + if (matches(pos(), "/*")) { + // Start of block comment: increase nesting depth. + advance(2); + depth++; + } else if (matches(pos(), "*/")) { + // End of block comment: decrease nesting depth. + advance(2); + depth--; + } else if (is_eol()) { + // Newline: skip and update source location. + advance_line(); + } else if (is_null()) { + return Token{Token::Type::kError, begin_source(), "null character found"}; + } else { + auto n = unicode_length(line(), pos()); + if (n == 0) { + return Token{Token::Type::kError, begin_source(), "invalid UTF-8"}; + } + // Anything else: skip and update source location. + advance(n); + } + } + if (depth > 0) { + return Token{Token::Type::kError, source, "unterminated block comment"}; + } + } + return {}; +} + +std::optional Lexer::try_float() { + auto start = pos(); + auto end = pos(); + + auto source = begin_source(); + bool has_mantissa_digits = false; + + std::optional first_significant_digit_position; + while (end < length() && is_digit(at(end))) { + if (!first_significant_digit_position.has_value() && (at(end) != '0')) { + first_significant_digit_position = end; + } + + has_mantissa_digits = true; + end++; + } + + std::optional dot_position; + if (end < length() && matches(end, '.')) { + dot_position = end; + end++; + } + + size_t zeros_before_digit = 0; + while (end < length() && is_digit(at(end))) { + if (!first_significant_digit_position.has_value()) { + if (at(end) == '0') { + zeros_before_digit += 1; + } else { + first_significant_digit_position = end; + } + } + + has_mantissa_digits = true; + end++; + } + + if (!has_mantissa_digits) { + return {}; + } + + // Parse the exponent if one exists + std::optional exponent_value_position; + bool negative_exponent = false; + if (end < length() && (matches(end, 'e') || matches(end, 'E'))) { + end++; + if (end < length() && (matches(end, '+') || matches(end, '-'))) { + negative_exponent = matches(end, '-'); + end++; + } + exponent_value_position = end; + + bool has_digits = false; + while (end < length() && isdigit(at(end))) { + has_digits = true; + end++; + } + + // If an 'e' or 'E' was present, then the number part must also be present. + if (!has_digits) { + const auto str = std::string{substr(start, end - start)}; + return Token{Token::Type::kError, source, + "incomplete exponent for floating point literal: " + str}; + } + } + + bool has_f_suffix = false; + bool has_h_suffix = false; + if (end < length() && matches(end, 'f')) { + has_f_suffix = true; + } else if (end < length() && matches(end, 'h')) { + has_h_suffix = true; + } + + if (!dot_position.has_value() && !exponent_value_position.has_value() && !has_f_suffix && + !has_h_suffix) { + // If it only has digits then it's an integer. + return {}; + } + + auto ret = tint::strconv::ParseDouble(std::string_view(&at(start), end - start)); + double value = ret == Success ? ret.Get() : 0.0; + bool overflow = + ret != Success && ret.Failure() == tint::strconv::ParseNumberError::kResultOutOfRange; + + // If the value didn't fit in a double, check for underflow as that is 0.0 in WGSL and not an + // error. + if (overflow) { + // The exponent is negative, so treat as underflow + if (negative_exponent) { + overflow = false; + value = 0.0; + } else if (dot_position.has_value() && first_significant_digit_position.has_value() && + first_significant_digit_position.value() > dot_position.value()) { + // Parse the exponent from the float if provided + size_t exp_value = 0; + bool exp_conversion_succeeded = true; + if (exponent_value_position.has_value()) { + // Note, the `at` method will return a static `0` if the provided position is >= + // length. The end pointer need to point to the correct memory location in the + // current line to use `from_chars`. + // So, handle the case where end points past the length specially. + auto exp_end = std::min(end, length()) - (has_f_suffix || has_h_suffix ? 1 : 0); + auto* exp_end_ptr = &at(exp_end); + if (exp_end >= length()) { + exp_end_ptr = line_end(); + } + auto exp_ret = std::from_chars(&at(exponent_value_position.value()), exp_end_ptr, + exp_value, 10); + + if (exp_ret.ec != std::errc{}) { + exp_conversion_succeeded = false; + } + } + // If the exponent has gone negative, then this is an underflow case + if (exp_conversion_succeeded && exp_value < zeros_before_digit) { + overflow = false; + value = 0.0; + } + } + } + + advance(end - start); + + if (has_f_suffix) { + auto f = core::CheckedConvert(AFloat(value)); + if (!overflow && f == Success) { + advance(1); + end_source(source); + return Token{Token::Type::kFloatLiteral_F, source, static_cast(f.Get())}; + } + return Token{Token::Type::kError, source, "value cannot be represented as 'f32'"}; + } + + if (has_h_suffix) { + auto f = core::CheckedConvert(AFloat(value)); + if (!overflow && f == Success) { + advance(1); + end_source(source); + return Token{Token::Type::kFloatLiteral_H, source, static_cast(f.Get())}; + } + return Token{Token::Type::kError, source, "value cannot be represented as 'f16'"}; + } + + end_source(source); + + TINT_BEGIN_DISABLE_WARNING(FLOAT_EQUAL); + if (overflow || value == HUGE_VAL || -value == HUGE_VAL) { + return Token{Token::Type::kError, source, + "value cannot be represented as 'abstract-float'"}; + } else { + return Token{Token::Type::kFloatLiteral, source, value}; + } + TINT_END_DISABLE_WARNING(FLOAT_EQUAL); +} + +std::optional Lexer::try_hex_float() { + constexpr uint64_t kExponentBits = 11; + constexpr uint64_t kMantissaBits = 52; + constexpr uint64_t kTotalBits = 1 + kExponentBits + kMantissaBits; + constexpr uint64_t kTotalMsb = kTotalBits - 1; + constexpr uint64_t kMantissaMsb = kMantissaBits - 1; + constexpr uint64_t kMantissaShiftRight = kTotalBits - kMantissaBits; + constexpr int64_t kExponentBias = 1023; + constexpr uint64_t kExponentMask = (1 << kExponentBits) - 1; + constexpr int64_t kExponentMax = kExponentMask; // Including NaN / inf + constexpr uint64_t kExponentLeftShift = kMantissaBits; + constexpr uint64_t kOne = 1; + + auto start = pos(); + auto end = pos(); + + auto source = begin_source(); + + // 0[xX]([0-9a-fA-F]*.?[0-9a-fA-F]+ | [0-9a-fA-F]+.[0-9a-fA-F]*)(p|P)(+|-)?[0-9]+ // NOLINT + + // 0[xX] + if (matches(end, '0') && (matches(end + 1, 'x') || matches(end + 1, 'X'))) { + end += 2; + } else { + return {}; + } + + uint64_t mantissa = 0; + uint64_t exponent = 0; + + // TODO(dneto): Values in the normal range for the format do not explicitly + // store the most significant bit. The algorithm here works hard to eliminate + // that bit in the representation during parsing, and then it backtracks + // when it sees it may have to explicitly represent it, and backtracks again + // when it sees the number is sub-normal (i.e. the exponent underflows). + // I suspect the logic can be clarified by storing it during parsing, and + // then removing it later only when needed. + + // `set_next_mantissa_bit_to` sets next `mantissa` bit starting from msb to + // lsb to value 1 if `set` is true, 0 otherwise. Returns true on success, i.e. + // when the bit can be accommodated in the available space. + uint64_t mantissa_next_bit = kTotalMsb; + auto set_next_mantissa_bit_to = [&](bool set, bool integer_part) -> bool { + // If adding bits for the integer part, we can overflow whether we set the + // bit or not. For the fractional part, we can only overflow when setting + // the bit. + const bool check_overflow = integer_part || set; + // Note: mantissa_next_bit actually decrements, so comparing it as + // larger than a positive number relies on wraparound. + if (check_overflow && (mantissa_next_bit > kTotalMsb)) { + return false; // Overflowed mantissa + } + if (set) { + mantissa |= (kOne << mantissa_next_bit); + } + --mantissa_next_bit; + return true; + }; + + // Collect integer range (if any) + auto integer_range = std::make_pair(end, end); + while (end < length() && is_hex(at(end))) { + integer_range.second = ++end; + } + + // .? + bool hex_point = false; + if (matches(end, '.')) { + hex_point = true; + end++; + } + + // Collect fractional range (if any) + auto fractional_range = std::make_pair(end, end); + while (end < length() && is_hex(at(end))) { + fractional_range.second = ++end; + } + + // Must have at least an integer or fractional part + if ((integer_range.first == integer_range.second) && + (fractional_range.first == fractional_range.second)) { + return {}; + } + + // Is the binary exponent present? It's optional. + const bool has_exponent = (matches(end, 'p') || matches(end, 'P')); + if (has_exponent) { + end++; + } + if (!has_exponent && !hex_point) { + // It's not a hex float. At best it's a hex integer. + return {}; + } + + // At this point, we know for sure our token is a hex float value, + // or an invalid token. + + // Parse integer part + // [0-9a-fA-F]* + + bool has_zero_integer = true; + // The magnitude is zero if and only if seen_prior_one_bits is false. + bool seen_prior_one_bits = false; + for (auto i = integer_range.first; i < integer_range.second; ++i) { + const auto nibble = hex_value(at(i)); + if (nibble != 0) { + has_zero_integer = false; + } + + for (int bit = 3; bit >= 0; --bit) { + auto v = 1 & (nibble >> bit); + + // Skip leading 0s and the first 1 + if (seen_prior_one_bits) { + if (!set_next_mantissa_bit_to(v != 0, true)) { + return Token{Token::Type::kError, source, + "mantissa is too large for hex float"}; + } + ++exponent; + } else { + if (v == 1) { + seen_prior_one_bits = true; + } + } + } + } + + // Parse fractional part + // [0-9a-fA-F]* + for (auto i = fractional_range.first; i < fractional_range.second; ++i) { + auto nibble = hex_value(at(i)); + for (int bit = 3; bit >= 0; --bit) { + auto v = 1 & (nibble >> bit); + + if (v == 1) { + seen_prior_one_bits = true; + } + + // If integer part is 0, we only start writing bits to the + // mantissa once we have a non-zero fractional bit. While the fractional + // values are 0, we adjust the exponent to avoid overflowing `mantissa`. + if (!seen_prior_one_bits) { + --exponent; + } else { + if (!set_next_mantissa_bit_to(v != 0, false)) { + return Token{Token::Type::kError, source, + "mantissa is too large for hex float"}; + } + } + } + } + + // Determine if the value of the mantissa is zero. + // Note: it's not enough to check mantissa == 0 as we drop the initial bit, + // whether it's in the integer part or the fractional part. + const bool is_zero = !seen_prior_one_bits; + TINT_ASSERT(!is_zero || mantissa == 0); + + // Parse the optional exponent. + // ((p|P)(\+|-)?[0-9]+)? + uint64_t input_exponent = 0; // Defaults to 0 if not present + int64_t exponent_sign = 1; + // If the 'p' part is present, the rest of the exponent must exist. + bool has_f_suffix = false; + bool has_h_suffix = false; + if (has_exponent) { + // Parse the rest of the exponent. + // (+|-)? + if (matches(end, '+')) { + end++; + } else if (matches(end, '-')) { + exponent_sign = -1; + end++; + } + + // Parse exponent from input + // [0-9]+ + // Allow overflow (in uint64_t) when the floating point value magnitude is + // zero. + bool has_exponent_digits = false; + while (end < length() && isdigit(at(end))) { + has_exponent_digits = true; + auto prev_exponent = input_exponent; + input_exponent = (input_exponent * 10) + dec_value(at(end)); + // Check if we've overflowed input_exponent. This only matters when + // the mantissa is non-zero. + if (!is_zero && (prev_exponent > input_exponent)) { + return Token{Token::Type::kError, source, "exponent is too large for hex float"}; + } + end++; + } + + // Parse optional 'f' or 'h' suffix. For a hex float, it can only exist + // when the exponent is present. Otherwise it will look like + // one of the mantissa digits. + if (end < length() && matches(end, 'f')) { + has_f_suffix = true; + end++; + } else if (end < length() && matches(end, 'h')) { + has_h_suffix = true; + end++; + } + + if (!has_exponent_digits) { + return Token{Token::Type::kError, source, "expected an exponent value for hex float"}; + } + } + + advance(end - start); + end_source(source); + + if (is_zero) { + // If value is zero, then ignore the exponent and produce a zero + exponent = 0; + } else { + // Ensure input exponent is not too large; i.e. that it won't overflow when + // adding the exponent bias. + const uint64_t kIntMax = static_cast(std::numeric_limits::max()); + const uint64_t kMaxInputExponent = kIntMax - kExponentBias; + if (input_exponent > kMaxInputExponent) { + return Token{Token::Type::kError, source, "exponent is too large for hex float"}; + } + + // Compute exponent so far + exponent += static_cast(static_cast(input_exponent) * exponent_sign); + + // Bias exponent if non-zero + // After this, if exponent is <= 0, our value is a denormal + exponent += kExponentBias; + + // We know the number is not zero. The MSB is 1 (by construction), and + // should be eliminated because it becomes the implicit 1 that isn't + // explicitly represented in the binary32 format. We'll bring it back + // later if we find the exponent actually underflowed, i.e. the number + // is sub-normal. + if (has_zero_integer) { + mantissa <<= 1; + --exponent; + } + } + + // We can now safely work with exponent as a signed quantity, as there's no + // chance to overflow + int64_t signed_exponent = static_cast(exponent); + + // Shift mantissa to occupy the low 23 bits + mantissa >>= kMantissaShiftRight; + + // If denormal, shift mantissa until our exponent is zero + if (!is_zero) { + // Denorm has exponent 0 and non-zero mantissa. We set the top bit here, + // then shift the mantissa to make exponent zero. + if (signed_exponent <= 0) { + mantissa >>= 1; + mantissa |= (kOne << kMantissaMsb); + } + + while (signed_exponent < 0) { + mantissa >>= 1; + ++signed_exponent; + + // If underflow, clamp to zero + if (mantissa == 0) { + signed_exponent = 0; + } + } + } + + if (signed_exponent >= kExponentMax || (signed_exponent == kExponentMax && mantissa != 0)) { + std::string type = has_f_suffix ? "f32" : (has_h_suffix ? "f16" : "abstract-float"); + return Token{Token::Type::kError, source, "value cannot be represented as '" + type + "'"}; + } + + // Combine sign, mantissa, and exponent + uint64_t result_u64 = 0; + result_u64 |= mantissa; + result_u64 |= (static_cast(signed_exponent) & kExponentMask) << kExponentLeftShift; + + // Reinterpret as f16 and return + double result_f64; + std::memcpy(&result_f64, &result_u64, 8); + + if (has_f_suffix) { + // Check value fits in f32 + if (result_f64 < static_cast(f32::kLowestValue) || + result_f64 > static_cast(f32::kHighestValue)) { + return Token{Token::Type::kError, source, "value cannot be represented as 'f32'"}; + } + // Check the value can be exactly represented, i.e. only high 23 mantissa bits are valid for + // normal f32 values, and less for subnormal f32 values. The rest low mantissa bits must be + // 0. + int valid_mantissa_bits = 0; + double abs_result_f64 = std::fabs(result_f64); + if (abs_result_f64 >= static_cast(f32::kSmallestValue)) { + // The result shall be a normal f32 value. + valid_mantissa_bits = 23; + } else if (abs_result_f64 >= static_cast(f32::kSmallestSubnormalValue)) { + // The result shall be a subnormal f32 value, represented as double. + // The smallest positive normal f32 is f32::kSmallestValue = 2^-126 = 0x1.0p-126, and + // the + // smallest positive subnormal f32 is f32::kSmallestSubnormalValue = 2^-149. Thus, the + // value v in range 2^-126 > v >= 2^-149 must be represented as a subnormal f32 + // number, but is still normal double (f64) number, and has a exponent in range -127 + // to -149, inclusive. + // A value v, if 2^-126 > v >= 2^-127, its binary32 representation will have binary form + // s_00000000_1xxxxxxxxxxxxxxxxxxxxxx, having mantissa of 1 leading 1 bit and 22 + // arbitrary bits. Since this value is represented as normal double number, the + // leading 1 bit is omitted, only the highest 22 mantissia bits can be arbitrary, and + // the rest lowest 40 mantissa bits of f64 number must be zero. + // 2^-127 > v >= 2^-128, binary32 s_00000000_01xxxxxxxxxxxxxxxxxxxxx, having mantissa of + // 1 leading 0 bit, 1 leading 1 bit, and 21 arbitrary bits. The f64 representation + // omits the leading 0 and 1 bits, and only the highest 21 mantissia bits can be + // arbitrary. + // 2^-128 > v >= 2^-129, binary32 s_00000000_001xxxxxxxxxxxxxxxxxxxx, 20 arbitrary bits. + // ... + // 2^-147 > v >= 2^-148, binary32 s_00000000_0000000000000000000001x, 1 arbitrary bit. + // 2^-148 > v >= 2^-149, binary32 s_00000000_00000000000000000000001, 0 arbitrary bit. + + // signed_exponent must be in range -149 + 1023 = 874 to -127 + 1023 = 896, inclusive + TINT_ASSERT((874 <= signed_exponent) && (signed_exponent <= 896)); + int unbiased_exponent = + static_cast(signed_exponent) - static_cast(kExponentBias); + TINT_ASSERT((-149 <= unbiased_exponent) && (unbiased_exponent <= -127)); + valid_mantissa_bits = unbiased_exponent + 149; // 0 for -149, and 22 for -127 + } else if (abs_result_f64 != 0.0) { + // The result is smaller than the smallest subnormal f32 value, but not equal to zero. + // Such value will never be exactly represented by f32. + return Token{Token::Type::kError, source, + "value cannot be exactly represented as 'f32'"}; + } + // Check the low 52-valid_mantissa_bits mantissa bits must be 0. + TINT_ASSERT((0 <= valid_mantissa_bits) && (valid_mantissa_bits <= 23)); + if (result_u64 & ((uint64_t(1) << (52 - valid_mantissa_bits)) - 1)) { + return Token{Token::Type::kError, source, + "value cannot be exactly represented as 'f32'"}; + } + return Token{Token::Type::kFloatLiteral_F, source, result_f64}; + } else if (has_h_suffix) { + // Check value fits in f16 + if (result_f64 < static_cast(f16::kLowestValue) || + result_f64 > static_cast(f16::kHighestValue)) { + return Token{Token::Type::kError, source, "value cannot be represented as 'f16'"}; + } + // Check the value can be exactly represented, i.e. only high 10 mantissa bits are valid for + // normal f16 values, and less for subnormal f16 values. The rest low mantissa bits must be + // 0. + int valid_mantissa_bits = 0; + double abs_result_f64 = std::fabs(result_f64); + if (abs_result_f64 >= static_cast(f16::kSmallestValue)) { + // The result shall be a normal f16 value. + valid_mantissa_bits = 10; + } else if (abs_result_f64 >= static_cast(f16::kSmallestSubnormalValue)) { + // The result shall be a subnormal f16 value, represented as double. + // The smallest positive normal f16 is f16::kSmallestValue = 2^-14 = 0x1.0p-14, and the + // smallest positive subnormal f16 is f16::kSmallestSubnormalValue = 2^-24. Thus, the + // value v in range 2^-14 > v >= 2^-24 must be represented as a subnormal f16 number, + // but is still normal double (f64) number, and has a exponent in range -15 to -24, + // inclusive. + // A value v, if 2^-14 > v >= 2^-15, its binary16 representation will have binary form + // s_00000_1xxxxxxxxx, having mantissa of 1 leading 1 bit and 9 arbitrary bits. Since + // this value is represented as normal double number, the leading 1 bit is omitted, + // only the highest 9 mantissia bits can be arbitrary, and the rest lowest 43 mantissa + // bits of f64 number must be zero. + // 2^-15 > v >= 2^-16, binary16 s_00000_01xxxxxxxx, having mantissa of 1 leading 0 bit, + // 1 leading 1 bit, and 8 arbitrary bits. The f64 representation omits the leading 0 + // and 1 bits, and only the highest 8 mantissia bits can be arbitrary. + // 2^-16 > v >= 2^-17, binary16 s_00000_001xxxxxxx, 7 arbitrary bits. + // ... + // 2^-22 > v >= 2^-23, binary16 s_00000_000000001x, 1 arbitrary bits. + // 2^-23 > v >= 2^-24, binary16 s_00000_0000000001, 0 arbitrary bits. + + // signed_exponent must be in range -24 + 1023 = 999 to -15 + 1023 = 1008, inclusive + TINT_ASSERT((999 <= signed_exponent) && (signed_exponent <= 1008)); + int unbiased_exponent = + static_cast(signed_exponent) - static_cast(kExponentBias); + TINT_ASSERT((-24 <= unbiased_exponent) && (unbiased_exponent <= -15)); + valid_mantissa_bits = unbiased_exponent + 24; // 0 for -24, and 9 for -15 + } else if (abs_result_f64 != 0.0) { + // The result is smaller than the smallest subnormal f16 value, but not equal to zero. + // Such value will never be exactly represented by f16. + return Token{Token::Type::kError, source, + "value cannot be exactly represented as 'f16'"}; + } + // Check the low 52-valid_mantissa_bits mantissa bits must be 0. + TINT_ASSERT((0 <= valid_mantissa_bits) && (valid_mantissa_bits <= 10)); + if (result_u64 & ((uint64_t(1) << (52 - valid_mantissa_bits)) - 1)) { + return Token{Token::Type::kError, source, + "value cannot be exactly represented as 'f16'"}; + } + return Token{Token::Type::kFloatLiteral_H, source, result_f64}; + } + + return Token{Token::Type::kFloatLiteral, source, result_f64}; +} + +Token Lexer::build_token_from_int_if_possible(Source source, + uint32_t start, + uint32_t prefix_count, + int32_t base) { + const char* start_ptr = &at(start); + // The call to `from_chars` will return the pointer to just after the last parsed character. + // We also need to tell it the maximum end character to parse. So, instead of walking all the + // characters to find the last possible and using that, we just provide the end of the string. + // We then calculate the count based off the provided end pointer and the start pointer. The + // extra `prefix_count` is to handle a `0x` which is not included in the `start` value. + const char* end_ptr = line_end(); + + int64_t value = 0; + auto res = std::from_chars(start_ptr, end_ptr, value, base); + const bool overflow = res.ec != std::errc(); + advance(static_cast(res.ptr - start_ptr) + prefix_count); + + if (matches(pos(), 'u')) { + if (!overflow && core::CheckedConvert(AInt(value)) == Success) { + advance(1); + end_source(source); + return {Token::Type::kIntLiteral_U, source, value}; + } + return {Token::Type::kError, source, "value cannot be represented as 'u32'"}; + } + + if (matches(pos(), 'i')) { + if (!overflow && core::CheckedConvert(AInt(value)) == Success) { + advance(1); + end_source(source); + return {Token::Type::kIntLiteral_I, source, value}; + } + return {Token::Type::kError, source, "value cannot be represented as 'i32'"}; + } + + // Check this last in order to get the more specific sized error messages + if (overflow) { + return {Token::Type::kError, source, "value cannot be represented as 'abstract-int'"}; + } + + end_source(source); + return {Token::Type::kIntLiteral, source, value}; +} + +std::optional Lexer::try_hex_integer() { + auto start = pos(); + auto curr = start; + + auto source = begin_source(); + + if (matches(curr, '0') && (matches(curr + 1, 'x') || matches(curr + 1, 'X'))) { + curr += 2; + } else { + return {}; + } + + if (!is_hex(at(curr))) { + return Token{Token::Type::kError, source, + "integer or float hex literal has no significant digits"}; + } + + return build_token_from_int_if_possible(source, curr, curr - start, 16); +} + +std::optional Lexer::try_integer() { + auto start = pos(); + auto curr = start; + + auto source = begin_source(); + + if (curr >= length() || !is_digit(at(curr))) { + return {}; + } + + // If the first digit is a zero this must only be zero as leading zeros + // are not allowed. + if (auto next = curr + 1; next < length()) { + if (at(curr) == '0' && is_digit(at(next))) { + return Token{Token::Type::kError, source, "integer literal cannot have leading 0s"}; + } + } + + return build_token_from_int_if_possible(source, start, 0, 10); +} + +std::optional Lexer::try_ident() { + auto source = begin_source(); + auto start = pos(); + + // Must begin with an XID_Source unicode character, or underscore + { + auto* utf8 = reinterpret_cast(&at(pos())); + auto [code_point, n] = tint::utf8::Decode(utf8, length() - pos()); + if (n == 0) { + advance(); // Skip the bad byte. + return Token{Token::Type::kError, source, "invalid UTF-8"}; + } + if (code_point != tint::CodePoint('_') && !code_point.IsXIDStart()) { + return {}; + } + // Consume start codepoint + advance(static_cast(n)); + } + + while (!is_eol()) { + // Must continue with an XID_Continue unicode character + auto* utf8 = reinterpret_cast(&at(pos())); + auto [code_point, n] = tint::utf8::Decode(utf8, line().size() - pos()); + if (n == 0) { + advance(); // Skip the bad byte. + return Token{Token::Type::kError, source, "invalid UTF-8"}; + } + if (!code_point.IsXIDContinue()) { + break; + } + + // Consume continuing codepoint + advance(static_cast(n)); + } + + auto str = substr(start, pos() - start); + end_source(source); + + if (str.length() > 1 && substr(start, 2) == "__") { + // Identifiers prefixed with two or more underscores are not allowed. + return Token{Token::Type::kError, source, + "identifiers must not start with two or more underscores"}; + } + + if (auto t = parse_keyword(str); t.has_value()) { + return Token{t.value(), source, str}; + } + + return Token{Token::Type::kIdentifier, source, str}; +} + +std::optional Lexer::try_punctuation() { + auto source = begin_source(); + auto type = Token::Type::kUninitialized; + + if (matches(pos(), '@')) { + type = Token::Type::kAttr; + advance(1); + } else if (matches(pos(), '(')) { + type = Token::Type::kParenLeft; + advance(1); + } else if (matches(pos(), ')')) { + type = Token::Type::kParenRight; + advance(1); + } else if (matches(pos(), '[')) { + type = Token::Type::kBracketLeft; + advance(1); + } else if (matches(pos(), ']')) { + type = Token::Type::kBracketRight; + advance(1); + } else if (matches(pos(), '{')) { + type = Token::Type::kBraceLeft; + advance(1); + } else if (matches(pos(), '}')) { + type = Token::Type::kBraceRight; + advance(1); + } else if (matches(pos(), '&')) { + if (matches(pos() + 1, '&')) { + type = Token::Type::kAndAnd; + advance(2); + } else if (matches(pos() + 1, '=')) { + type = Token::Type::kAndEqual; + advance(2); + } else { + type = Token::Type::kAnd; + advance(1); + } + } else if (matches(pos(), '/')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kDivisionEqual; + advance(2); + } else { + type = Token::Type::kForwardSlash; + advance(1); + } + } else if (matches(pos(), '!')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kNotEqual; + advance(2); + } else { + type = Token::Type::kBang; + advance(1); + } + } else if (matches(pos(), ':')) { + type = Token::Type::kColon; + advance(1); + } else if (matches(pos(), ',')) { + type = Token::Type::kComma; + advance(1); + } else if (matches(pos(), '=')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kEqualEqual; + advance(2); + } else { + type = Token::Type::kEqual; + advance(1); + } + } else if (matches(pos(), '>')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kGreaterThanEqual; + advance(2); + } else if (matches(pos() + 1, '>')) { + if (matches(pos() + 2, '=')) { + type = Token::Type::kShiftRightEqual; + advance(3); + } else { + type = Token::Type::kShiftRight; + advance(2); + } + } else { + type = Token::Type::kGreaterThan; + advance(1); + } + } else if (matches(pos(), '<')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kLessThanEqual; + advance(2); + } else if (matches(pos() + 1, '<')) { + if (matches(pos() + 2, '=')) { + type = Token::Type::kShiftLeftEqual; + advance(3); + } else { + type = Token::Type::kShiftLeft; + advance(2); + } + } else { + type = Token::Type::kLessThan; + advance(1); + } + } else if (matches(pos(), '%')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kModuloEqual; + advance(2); + } else { + type = Token::Type::kMod; + advance(1); + } + } else if (matches(pos(), '-')) { + if (matches(pos() + 1, '>')) { + type = Token::Type::kArrow; + advance(2); + } else if (matches(pos() + 1, '-')) { + type = Token::Type::kMinusMinus; + advance(2); + } else if (matches(pos() + 1, '=')) { + type = Token::Type::kMinusEqual; + advance(2); + } else { + type = Token::Type::kMinus; + advance(1); + } + } else if (matches(pos(), '.')) { + type = Token::Type::kPeriod; + advance(1); + } else if (matches(pos(), '+')) { + if (matches(pos() + 1, '+')) { + type = Token::Type::kPlusPlus; + advance(2); + } else if (matches(pos() + 1, '=')) { + type = Token::Type::kPlusEqual; + advance(2); + } else { + type = Token::Type::kPlus; + advance(1); + } + } else if (matches(pos(), '|')) { + if (matches(pos() + 1, '|')) { + type = Token::Type::kOrOr; + advance(2); + } else if (matches(pos() + 1, '=')) { + type = Token::Type::kOrEqual; + advance(2); + } else { + type = Token::Type::kOr; + advance(1); + } + } else if (matches(pos(), ';')) { + type = Token::Type::kSemicolon; + advance(1); + } else if (matches(pos(), '*')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kTimesEqual; + advance(2); + } else { + type = Token::Type::kStar; + advance(1); + } + } else if (matches(pos(), '~')) { + type = Token::Type::kTilde; + advance(1); + } else if (matches(pos(), '_')) { + type = Token::Type::kUnderscore; + advance(1); + } else if (matches(pos(), '^')) { + if (matches(pos() + 1, '=')) { + type = Token::Type::kXorEqual; + advance(2); + } else { + type = Token::Type::kXor; + advance(1); + } + } else { + return {}; + } + + end_source(source); + + return Token{type, source}; +} + +std::optional Lexer::parse_keyword(std::string_view str) { + if (str == "alias") { + return Token::Type::kAlias; + } + if (str == "break") { + return Token::Type::kBreak; + } + if (str == "case") { + return Token::Type::kCase; + } + if (str == "const") { + return Token::Type::kConst; + } + if (str == "const_assert") { + return Token::Type::kConstAssert; + } + if (str == "continue") { + return Token::Type::kContinue; + } + if (str == "continuing") { + return Token::Type::kContinuing; + } + if (str == "diagnostic") { + return Token::Type::kDiagnostic; + } + if (str == "discard") { + return Token::Type::kDiscard; + } + if (str == "default") { + return Token::Type::kDefault; + } + if (str == "else") { + return Token::Type::kElse; + } + if (str == "enable") { + return Token::Type::kEnable; + } + if (str == "fallthrough") { + return Token::Type::kFallthrough; + } + if (str == "false") { + return Token::Type::kFalse; + } + if (str == "fn") { + return Token::Type::kFn; + } + if (str == "for") { + return Token::Type::kFor; + } + if (str == "if") { + return Token::Type::kIf; + } + if (str == "let") { + return Token::Type::kLet; + } + if (str == "loop") { + return Token::Type::kLoop; + } + if (str == "override") { + return Token::Type::kOverride; + } + if (str == "return") { + return Token::Type::kReturn; + } + if (str == "requires") { + return Token::Type::kRequires; + } + if (str == "struct") { + return Token::Type::kStruct; + } + if (str == "switch") { + return Token::Type::kSwitch; + } + if (str == "true") { + return Token::Type::kTrue; + } + if (str == "var") { + return Token::Type::kVar; + } + if (str == "while") { + return Token::Type::kWhile; + } + if (str == "_") { + return Token::Type::kUnderscore; + } + return std::nullopt; +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.h new file mode 100644 index 000000000..175d50566 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/lexer.h @@ -0,0 +1,134 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_PARSER_LEXER_H_ +#define SRC_TINT_LANG_WGSL_READER_PARSER_LEXER_H_ + +#include +#include + +#include "src/tint/lang/wgsl/reader/parser/token.h" + +namespace tint::wgsl::reader { + +/// Converts the input stream into a series of Tokens +class Lexer { + public: + /// Creates a new Lexer + /// @param file the source file + explicit Lexer(const Source::File* file); + ~Lexer(); + + /// @return the token list. + std::vector Lex(); + + private: + /// Returns the next token in the input stream. + /// @return Token + Token next(); + + /// Advances past blankspace and comments, if present at the current position. + /// @returns error token, EOF, or uninitialized + std::optional skip_blankspace_and_comments(); + /// Advances past a comment at the current position, if one exists. + /// Returns an error if there was an unterminated block comment, + /// or a null character was present. + /// @returns uninitialized token on success, or error + std::optional skip_comment(); + + Token build_token_from_int_if_possible(Source source, + uint32_t start, + uint32_t prefix_count, + int32_t base); + + std::optional parse_keyword(std::string_view); + + /// The try_* methods have the following in common: + /// - They assume there is at least one character to be consumed, + /// i.e. the input has not yet reached end of file. + /// - They return an initialized token when they match and consume + /// a token of the specified kind. + /// - Some can return an error token. + /// - Otherwise they return an uninitialized token when they did not + /// match a token of the specfied kind. + std::optional try_float(); + std::optional try_hex_float(); + std::optional try_hex_integer(); + std::optional try_ident(); + std::optional try_integer(); + std::optional try_punctuation(); + + Source begin_source() const; + void end_source(Source&) const; + + /// @returns view of current line + std::string_view line() const; + /// @returns position in current line + uint32_t pos() const; + /// @returns length of current line + uint32_t length() const; + /// @returns reference to character at `pos` within current line + const char& at(uint32_t pos) const; + /// @returns a point to the character just beyond the end of the current line, similar to how + /// std::end works + const char* line_end() const; + /// @returns substring view at `offset` within current line of length `count` + std::string_view substr(uint32_t offset, uint32_t count); + /// advances current position by `offset` within current line + void advance(uint32_t offset = 1); + /// sets current position to `pos` within current line + void set_pos(uint32_t pos); + /// advances current position to next line + void advance_line(); + /// @returns true if the current position contains a BOM + bool is_bom() const; + /// @returns true if the end of the input has been reached. + bool is_eof() const; + /// @returns true if the end of the current line has been reached. + bool is_eol() const; + /// @returns true if there is another character on the input and + /// it is not null. + bool is_null() const; + /// @param ch a character + /// @returns true if 'ch' is a decimal digit + bool is_digit(char ch) const; + /// @param ch a character + /// @returns true if 'ch' is a hexadecimal digit + bool is_hex(char ch) const; + /// @returns true if string at `pos` matches `substr` + bool matches(uint32_t pos, std::string_view substr); + /// @returns true if char at `pos` matches `ch` + bool matches(uint32_t pos, char ch); + /// The source file content + Source::File const* const file_; + /// The current location within the input + Source::Location location_; +}; + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_PARSER_LEXER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.cc new file mode 100644 index 000000000..252681cc4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.cc @@ -0,0 +1,3542 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reader/parser/parser.h" + +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/break_if_statement.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/invariant_attribute.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/stage_attribute.h" +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" +#include "src/tint/lang/wgsl/ast/var.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/reader/parser/classify_template_args.h" +#include "src/tint/lang/wgsl/reader/parser/lexer.h" +#include "src/tint/lang/wgsl/reserved_words.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::wgsl::reader { +namespace { + +using Void = Parser::Void; + +/// An instance of Void that can be used to signal success for functions that return Expect or +/// Maybe. +static constexpr Void kSuccess; + +template +using Expect = Parser::Expect; + +template +using Maybe = Parser::Maybe; + +/// Controls the maximum number of times we'll call into the sync() and +/// unary_expression() functions from themselves. This is to guard against stack +/// overflow when there is an excessive number of blocks. +constexpr uint32_t kMaxParseDepth = 128; + +/// The maximum number of tokens to look ahead to try and sync the +/// parser on error. +constexpr size_t const kMaxResynchronizeLookahead = 32; + +/// Enter-exit counters for block token types. +/// Used by sync_to() to skip over closing block tokens that were opened during +/// the forward scan. +struct BlockCounters { + int brace = 0; // { } + int bracket = 0; // [ ] + int paren = 0; // ( ) + + /// @return the current enter-exit depth for the given block token type. If + /// `t` is not a block token type, then 0 is always returned. + int consume(const Token& t) { + if (t.Is(Token::Type::kBraceLeft)) { + return brace++; + } + if (t.Is(Token::Type::kBraceRight)) { + return brace--; + } + if (t.Is(Token::Type::kBracketLeft)) { + return bracket++; + } + if (t.Is(Token::Type::kBracketRight)) { + return bracket--; + } + if (t.Is(Token::Type::kParenLeft)) { + return paren++; + } + if (t.Is(Token::Type::kParenRight)) { + return paren--; + } + return 0; + } +}; +} // namespace + +/// RAII helper that combines a Source on construction with the last token's +/// source when implicitly converted to `Source`. +class Parser::MultiTokenSource { + public: + /// Constructor that starts with Source at the current peek position + /// @param parser the parser + explicit MultiTokenSource(Parser* parser) + : MultiTokenSource(parser, parser->peek().source().Begin()) {} + + /// Constructor that starts with the input `start` Source + /// @param parser the parser + /// @param start the start source of the range + MultiTokenSource(Parser* parser, const tint::Source& start) : parser_(parser), start_(start) {} + + /// @returns the Source that returns the combined source from start to the current last token's + /// source. + tint::Source operator()() const { return *this; } + + /// @returns the Source that returns the combined source from start to the current last token's + /// source. + operator tint::Source() const { + auto end = parser_->last_source().End(); + if (end < start_) { + end = start_; + } + return Source::Combine(start_, end); + } + + private: + Parser* parser_; + tint::Source start_; +}; + +Parser::TypedIdentifier::TypedIdentifier() = default; + +Parser::TypedIdentifier::TypedIdentifier(const TypedIdentifier&) = default; + +Parser::TypedIdentifier::TypedIdentifier(ast::Type type_in, const ast::Identifier* name_in) + : type(type_in), name(name_in) {} + +Parser::TypedIdentifier::~TypedIdentifier() = default; + +Parser::FunctionHeader::FunctionHeader() = default; + +Parser::FunctionHeader::FunctionHeader(const FunctionHeader&) = default; + +Parser::FunctionHeader::FunctionHeader(Source src, + const ast::Identifier* n, + VectorRef p, + ast::Type ret_ty, + VectorRef ret_attrs) + : source(src), + name(n), + params(std::move(p)), + return_type(ret_ty), + return_type_attributes(std::move(ret_attrs)) {} + +Parser::FunctionHeader::~FunctionHeader() = default; + +Parser::FunctionHeader& Parser::FunctionHeader::operator=(const FunctionHeader& rhs) = default; + +Parser::Parser(Source::File const* file) : file_(file) {} + +Parser::~Parser() = default; + +Parser::Failure::Errored Parser::AddError(const Source& source, + std::string_view err, + std::string_view use) { + if (silence_diags_ == 0) { + StringStream msg; + msg << err; + if (!use.empty()) { + msg << " for " << use; + } + AddError(source, msg.str()); + } + return Failure::kErrored; +} + +Parser::Failure::Errored Parser::AddError(const Token& t, std::string_view err) { + AddError(t.source(), err); + return Failure::kErrored; +} + +Parser::Failure::Errored Parser::AddError(const Source& source, std::string_view err) { + if (silence_diags_ == 0) { + builder_.Diagnostics().AddError(source) << err; + } + return Failure::kErrored; +} + +Parser::Failure::Errored Parser::AddError(const Source& source, StyledText&& err) { + if (silence_diags_ == 0) { + builder_.Diagnostics().AddError(source) << std::move(err); + } + return Failure::kErrored; +} + +void Parser::AddNote(const Source& source, std::string_view err) { + if (silence_diags_ == 0) { + builder_.Diagnostics().AddNote(source) << err; + } +} + +void Parser::deprecated(const Source& source, std::string_view msg) { + if (silence_diags_ == 0) { + builder_.Diagnostics().AddWarning(source) << "use of deprecated language feature: " << msg; + } +} + +const Token& Parser::next() { + // If the next token is already an error or the end of file, stay there. + if (tokens_[next_token_idx_].IsEof() || tokens_[next_token_idx_].IsError()) { + return tokens_[next_token_idx_]; + } + + // Skip over any placeholder elements + while (true) { + if (!tokens_[next_token_idx_].IsPlaceholder()) { + break; + } + next_token_idx_++; + } + last_source_idx_ = next_token_idx_; + + if (!tokens_[next_token_idx_].IsEof() && !tokens_[next_token_idx_].IsError()) { + next_token_idx_++; + } + return tokens_[last_source_idx_]; +} + +const Token& Parser::peek(size_t count) { + for (size_t idx = next_token_idx_; idx < tokens_.size(); idx++) { + if (tokens_[idx].IsPlaceholder()) { + continue; + } + if (count == 0) { + return tokens_[idx]; + } + count--; + } + // Walked off the end of the token list, return last token. + return tokens_[tokens_.size() - 1]; +} + +bool Parser::peek_is(Token::Type tok, size_t idx) { + return peek(idx).Is(tok); +} + +void Parser::split_token(Token::Type lhs, Token::Type rhs) { + TINT_ASSERT(next_token_idx_ != 0) << "attempt to update placeholder at beginning of tokens"; + TINT_ASSERT(next_token_idx_ < tokens_.size()) + << "attempt to update placeholder past end of tokens"; + TINT_ASSERT(tokens_[next_token_idx_].IsPlaceholder()) + << "attempt to update non-placeholder token"; + tokens_[next_token_idx_ - 1].SetType(lhs); + tokens_[next_token_idx_].SetType(rhs); +} + +Source Parser::last_source() const { + return tokens_[last_source_idx_].source(); +} + +void Parser::InitializeLex() { + Lexer l{file_}; + tokens_ = l.Lex(); + ClassifyTemplateArguments(tokens_); +} + +bool Parser::Parse() { + InitializeLex(); + translation_unit(); + return !has_error(); +} + +// translation_unit +// : global_directive* global_decl* EOF +void Parser::translation_unit() { + bool after_global_decl = false; + while (continue_parsing()) { + auto& p = peek(); + if (p.IsEof()) { + break; + } + + auto ed = global_directive(after_global_decl); + if (!ed.matched && !ed.errored) { + auto gd = global_decl(); + if (gd.matched) { + after_global_decl = true; + } + + if (!gd.matched && !gd.errored) { + AddError(p, "unexpected token"); + } + } + + if (builder_.Diagnostics().NumErrors() >= max_errors_) { + AddError(Source{{}, p.source().file}, + "stopping after " + std::to_string(max_errors_) + " errors"); + break; + } + } +} + +// global_directive +// : diagnostic_directive +// | requires_directive +// | enable_directive +Maybe Parser::global_directive(bool have_parsed_decl) { + auto& p = peek(); + Maybe result = diagnostic_directive(); + if (!result.errored && !result.matched) { + result = enable_directive(); + } + if (!result.errored && !result.matched) { + result = requires_directive(); + } + + if (result.matched && have_parsed_decl) { + return AddError(p, "directives must come before all global declarations"); + } + return result; +} + +// diagnostic_directive +// : diagnostic diagnostic_control SEMICOLON +Maybe Parser::diagnostic_directive() { + auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe { + if (!match(Token::Type::kDiagnostic)) { + return Failure::kNoMatch; + } + + auto source = last_source(); + auto control = expect_diagnostic_control(); + if (control.errored) { + return Failure::kErrored; + } + + if (!expect("diagnostic directive", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + auto* directive = create(source, std::move(control.value)); + builder_.AST().AddDiagnosticDirective(directive); + + return kSuccess; + }); + + if (decl.errored) { + return Failure::kErrored; + } + return decl; +} + +// enable_directive : +// | 'enable' identifier (COMMA identifier)* COMMA? SEMICOLON +Maybe Parser::enable_directive() { + return sync(Token::Type::kSemicolon, [&]() -> Maybe { + MultiTokenSource decl_source(this); + if (!match(Token::Type::kEnable)) { + return Failure::kNoMatch; + } + + if (peek_is(Token::Type::kParenLeft)) { + // A common error case is writing `enable(foo);` instead of `enable foo;`. + synchronized_ = false; + return AddError(peek().source(), "enable directives don't take parenthesis"); + } + + Vector extensions; + while (continue_parsing()) { + Source ext_src = peek().source(); + auto ext = expect_enum("extension", wgsl::ParseExtension, wgsl::kExtensionStrings); + if (ext.errored) { + return Failure::kErrored; + } + extensions.Push(create(ext_src, ext.value)); + + if (!match(Token::Type::kComma)) { + break; + } + if (peek_is(Token::Type::kSemicolon)) { + break; + } + } + + if (!expect("enable directive", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + builder_.AST().AddEnable(create(decl_source(), std::move(extensions))); + return kSuccess; + }); +} + +// requires_directive +// : require identifier (COMMA identifier)* COMMA? SEMICOLON +Maybe Parser::requires_directive() { + return sync(Token::Type::kSemicolon, [&]() -> Maybe { + MultiTokenSource decl_source(this); + if (!match(Token::Type::kRequires)) { + return Failure::kNoMatch; + } + + // Match the require name. + auto& t = peek(); + if (handle_error(t)) { + // The token might itself be an error. + return Failure::kErrored; + } + + if (t.Is(Token::Type::kParenLeft)) { + // A common error case is writing `require(foo);` instead of `require foo;`. + synchronized_ = false; + return AddError(t.source(), "requires directives don't take parenthesis"); + } + + ast::Requires::LanguageFeatures features; + while (continue_parsing()) { + auto& t2 = next(); + if (handle_error(t2)) { + // The token might itself be an error. + return Failure::kErrored; + } + + // Match the require name. + if (t2.IsIdentifier()) { + auto feature = wgsl::ParseLanguageFeature(t2.to_str_view()); + if (feature == LanguageFeature::kUndefined) { + // Any identifier is a valid feature name, so we correctly handle new feature + // names getting added in the future, they just all get flagged as not + // supported. + return AddError(t2.source(), "feature '" + t2.to_str() + "' is not supported"); + } + features.Add(feature); + } else { + return AddError(t2.source(), "invalid feature name for requires"); + } + + if (!match(Token::Type::kComma)) { + break; + } + if (peek_is(Token::Type::kSemicolon)) { + break; + } + } + + if (!expect("requires directive", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + builder_.AST().AddRequires(create(decl_source(), std::move(features))); + return kSuccess; + }); +} + +// global_decl +// : SEMICOLON +// | global_variable_decl SEMICOLON +// | global_constant_decl SEMICOLON +// | type_alias_decl SEMICOLON +// | struct_decl +// | function_decl +// | const_assert_statement SEMICOLON +Maybe Parser::global_decl() { + if (match(Token::Type::kSemicolon) || match(Token::Type::kEOF)) { + return kSuccess; + } + + bool errored = false; + auto attrs = attribute_list(); + if (attrs.errored) { + errored = true; + } + if (!continue_parsing()) { + return Failure::kErrored; + } + + auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe { + auto gv = global_variable_decl(attrs.value); + if (gv.errored) { + return Failure::kErrored; + } + if (gv.matched) { + if (!expect("variable declaration", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + builder_.AST().AddGlobalVariable(gv.value); + return kSuccess; + } + + auto gc = global_constant_decl(attrs.value); + if (gc.errored) { + return Failure::kErrored; + } + if (gc.matched) { + // Avoid the cost of the string allocation for the common no-error case + if (!peek().Is(Token::Type::kSemicolon)) { + std::string kind = gc->Kind(); + if (!expect("'" + kind + "' declaration", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + } + return kSuccess; + } + + auto ta = type_alias_decl(); + if (ta.errored) { + return Failure::kErrored; + } + if (ta.matched) { + if (!expect("type alias", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + builder_.AST().AddTypeDecl(ta.value); + return kSuccess; + } + + auto assertion = const_assert_statement(); + if (assertion.errored) { + return Failure::kErrored; + } + if (assertion.matched) { + builder_.AST().AddConstAssert(assertion.value); + if (!expect("const assertion declaration", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + return kSuccess; + } + + return Failure::kNoMatch; + }); + + if (decl.errored) { + errored = true; + } + if (decl.matched) { + if (expect_attributes_consumed(attrs.value).errored) { + return Failure::kErrored; + } + return kSuccess; + } + + auto str = struct_decl(); + if (str.errored) { + errored = true; + } + if (str.matched) { + if (expect_attributes_consumed(attrs.value).errored) { + return Failure::kErrored; + } + return kSuccess; + } + + auto func = function_decl(attrs.value); + if (func.errored) { + errored = true; + } + if (func.matched) { + return kSuccess; + } + + if (errored) { + return Failure::kErrored; + } + + // Invalid syntax found - try and determine the best error message + + // We have attributes parsed, but nothing to consume them? + if (attrs.value.Length() > 0) { + return AddError(next(), "expected declaration after attributes"); + } + + // We have a statement outside of a function? + auto& t = peek(); + auto stat = without_diag([&] { return statement(); }); + if (stat.matched) { + // Attempt to jump to the next '}' - the function might have just been + // missing an opening line. + sync_to(Token::Type::kBraceRight, true); + return AddError(t, "statement found outside of function body"); + } + if (!stat.errored) { + // No match, no error - the parser might not have progressed. + // Ensure we always make _some_ forward progress. + next(); + } + + // The token might itself be an error. + if (handle_error(t)) { + return Failure::kErrored; + } + + // Exhausted all attempts to make sense of where we're at. + // Return a no-match + + return Failure::kNoMatch; +} + +// global_variable_decl +// : variable_attribute_list* variable_decl (EQUAL expression)? +Maybe Parser::global_variable_decl(AttributeList& attrs) { + MultiTokenSource decl_source(this); + auto decl = variable_decl(); + if (decl.errored) { + return Failure::kErrored; + } + if (!decl.matched) { + return Failure::kNoMatch; + } + + const ast::Expression* initializer = nullptr; + if (match(Token::Type::kEqual)) { + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError(peek(), "missing initializer for 'var' declaration"); + } + initializer = expr.value; + } + + TINT_DEFER(attrs.Clear()); + + return builder_.create(decl_source(), // source + builder_.Ident(decl->name), // symbol + decl->type, // type + decl->address_space, // address space + decl->access, // access control + initializer, // initializer + std::move(attrs)); // attributes +} + +// global_constant_decl : +// | LET optionally_typed_ident global_const_initializer +// | attribute* override optionally_typed_ident (equal expression)? +// global_const_initializer +// : EQUAL const_expr +Maybe Parser::global_constant_decl(AttributeList& attrs) { + bool is_overridable = false; + const char* use = nullptr; + MultiTokenSource decl_source(this); + Source source; + if (match(Token::Type::kConst)) { + use = "'const' declaration"; + } else if (match(Token::Type::kOverride)) { + use = "'override' declaration"; + is_overridable = true; + } else if (match(Token::Type::kLet, &source)) { + return AddError(source, "module-scope 'let' is invalid, use 'const'"); + } else { + return Failure::kNoMatch; + } + + auto decl = expect_optionally_typed_ident(use); + if (decl.errored) { + return Failure::kErrored; + } + + bool has_initializer = false; + if (is_overridable) { + has_initializer = match(Token::Type::kEqual); + } else { + if (!expect(use, Token::Type::kEqual)) { + return Failure::kErrored; + } + has_initializer = true; + } + + const ast::Expression* initializer = nullptr; + if (has_initializer) { + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError(peek(), "missing initializer for " + std::string(use)); + } + initializer = std::move(expr.value); + } + + TINT_DEFER(attrs.Clear()); + if (is_overridable) { + return builder_.Override(decl_source(), // source + decl->name, // symbol + decl->type, // type + initializer, // initializer + std::move(attrs)); // attributes + } + return builder_.GlobalConst(decl_source(), // source + decl->name, // symbol + decl->type, // type + initializer, // initializer + std::move(attrs)); // attributes +} + +// variable_decl +// : VAR variable_qualifier? optionally_typed_ident +// +// Note, the `( LESS_THAN address_space ( COMMA access_mode )? GREATER_THAN ) is pulled out into +// a `variable_qualifier` helper. +Maybe Parser::variable_decl() { + Source source; + if (!match(Token::Type::kVar, &source)) { + return Failure::kNoMatch; + } + + VariableQualifier vq; + auto explicit_vq = variable_qualifier(); + if (explicit_vq.errored) { + return Failure::kErrored; + } + if (explicit_vq.matched) { + vq = explicit_vq.value; + } + + auto decl = expect_optionally_typed_ident("variable declaration"); + if (decl.errored) { + return Failure::kErrored; + } + + return VarDeclInfo{decl->name->source, decl->name, vq.address_space, vq.access, decl->type}; +} + +Expect Parser::expect_ident_with_optional_type_specifier( + std::string_view use, + bool allow_inferred) { + auto ident = expect_ident(use); + if (ident.errored) { + return Failure::kErrored; + } + + if (allow_inferred && !peek_is(Token::Type::kColon)) { + return TypedIdentifier{ast::Type{}, ident.value}; + } + + if (!expect(use, Token::Type::kColon)) { + return Failure::kErrored; + } + + auto& t = peek(); + auto type = type_specifier(); + if (type.errored) { + return Failure::kErrored; + } + if (!type.matched) { + return AddError(t.source(), "invalid type", use); + } + + return TypedIdentifier{type.value, ident.value}; +} + +// optionally_typed_ident +// : ident ( COLON typed_decl ) ? +Expect Parser::expect_optionally_typed_ident(std::string_view use) { + return expect_ident_with_optional_type_specifier(use, /* allow_inferred */ true); +} + +// ident_with_type_specifier +// : IDENT COLON type_specifier +Expect Parser::expect_ident_with_type_specifier(std::string_view use) { + return expect_ident_with_optional_type_specifier(use, /* allow_inferred */ false); +} + +// variable_qualifier +// : _template_args_start expression (COMMA expression)? COMMA? _template_args_end +Maybe Parser::variable_qualifier() { + if (!peek_is(Token::Type::kTemplateArgsLeft) && !peek_is(Token::Type::kLessThan)) { + // Note: kLessThan will give a sensible error at expect_template_arg_block() + return Failure::kNoMatch; + } + + auto* use = "variable declaration"; + auto vq = expect_template_arg_block(use, [&]() -> Expect { + auto address_space = expect_expression("'var' address space"); + if (address_space.errored) { + return Failure::kErrored; + } + // The first expression in this condition also matches trailing comma. + if (match(Token::Type::kComma) && !peek().Is(Token::Type::kTemplateArgsRight)) { + auto access = expect_expression("'var' access mode"); + if (access.errored) { + return Failure::kErrored; + } + // Allow for trailing comma. + match(Token::Type::kComma); + return VariableQualifier{address_space.value, access.value}; + } + return VariableQualifier{address_space.value}; + }); + + if (vq.errored) { + return Failure::kErrored; + } + + return vq; +} + +// type_alias_decl +// : ALIAS IDENT EQUAL type_specifier +Maybe Parser::type_alias_decl() { + MultiTokenSource source(this); + if (!match(Token::Type::kAlias)) { + return Failure::kNoMatch; + } + + const char* use = "type alias"; + + auto name = expect_ident(use); + if (name.errored) { + return Failure::kErrored; + } + + if (!expect(use, Token::Type::kEqual)) { + return Failure::kErrored; + } + + auto type = type_specifier(); + if (type.errored) { + return Failure::kErrored; + } + if (!type.matched) { + return AddError(peek(), "invalid type alias"); + } + + return builder_.ty.alias(source(), name.value, type.value); +} + +// type_specifier +// : IDENTIFIER template_arguments? +Maybe Parser::type_specifier() { + MultiTokenSource source(this); + auto& ident = peek(); + if (!match(Token::Type::kIdentifier)) { + return Failure::kNoMatch; + } + + if (!peek_is(Token::Type::kTemplateArgsLeft)) { + return builder_.ty(builder_.Ident(source(), ident.to_str())); + } + + auto args = expect_template_arg_block("type template arguments", [&] { + return expect_expression_list("type template argument list", + Token::Type::kTemplateArgsRight); + }); + if (args.errored) { + return Failure::kErrored; + } + return builder_.ty(builder_.Ident(source(), ident.to_str(), std::move(args.value))); +} + +template +Expect Parser::expect_enum(std::string_view name, + ENUM (*parse)(std::string_view str), + Slice strings, + std::string_view use) { + auto& t = peek(); + auto ident = t.to_str(); + if (t.IsIdentifier()) { + auto val = parse(ident); + if (val != ENUM::kUndefined) { + synchronized_ = true; + next(); + return val; + } + } + + // Was the token itself an error? + if (handle_error(t)) { + return Failure::kErrored; + } + + /// Create a sensible error message + StyledText err; + err << "expected " << name; + + if (!use.empty()) { + err << " for " << use; + } + err << "\n"; + + if (strings == wgsl::kExtensionStrings && !ident.starts_with("chromium")) { + // Filter out 'chromium' prefixed extensions. We don't want to advertise experimental + // extensions to end users (unless it looks like they've actually mis-typed a chromium + // extension name) + Vector filtered; + for (auto str : strings) { + if (!str.starts_with("chromium")) { + filtered.Push(str); + } + } + tint::SuggestAlternatives(ident, filtered.Slice(), err); + } else { + tint::SuggestAlternatives(ident, strings, err); + } + + synchronized_ = false; + return AddError(t.source(), std::move(err)); +} + +Expect Parser::expect_type(std::string_view use) { + auto type = type_specifier(); + if (type.errored) { + return Failure::kErrored; + } + if (!type.matched) { + return AddError(peek().source(), "invalid type", use); + } + return type.value; +} + +// struct_decl +// : STRUCT IDENT struct_body_decl +Maybe Parser::struct_decl() { + MultiTokenSource source(this); + + if (!match(Token::Type::kStruct)) { + return Failure::kNoMatch; + } + + auto name = expect_ident("struct declaration"); + if (name.errored) { + return Failure::kErrored; + } + + auto body = expect_struct_body_decl(); + if (body.errored) { + return Failure::kErrored; + } + + return builder_.Structure(source(), name.value, std::move(body.value)); +} + +// struct_body_decl +// : BRACE_LEFT (struct_member COMMA)* struct_member COMMA? BRACE_RIGHT +Expect Parser::expect_struct_body_decl() { + return expect_brace_block("struct declaration", [&]() -> Expect { + StructMemberList members; + bool errored = false; + while (continue_parsing()) { + // Check for the end of the list. + auto& t = peek(); + if (!t.IsIdentifier() && !t.Is(Token::Type::kAttr)) { + break; + } + + auto member = expect_struct_member(); + if (member.errored) { + errored = true; + if (!sync_to(Token::Type::kComma, /* consume: */ false)) { + return Failure::kErrored; + } + } else { + members.Push(member.value); + } + + if (!match(Token::Type::kComma)) { + break; + } + } + if (errored) { + return Failure::kErrored; + } + return members; + }); +} + +// struct_member +// : attribute* ident_with_type_specifier +Expect Parser::expect_struct_member() { + auto attrs = attribute_list(); + if (attrs.errored) { + return Failure::kErrored; + } + + auto decl = expect_ident_with_type_specifier("struct member"); + if (decl.errored) { + return Failure::kErrored; + } + + return builder_.Member(decl->name->source, decl->name, decl->type, std::move(attrs.value)); +} + +// const_assert_statement +// : STATIC_ASSERT expression +Maybe Parser::const_assert_statement() { + MultiTokenSource source(this); + if (!match(Token::Type::kConstAssert)) { + return Failure::kNoMatch; + } + + auto condition = expression(); + if (condition.errored) { + return Failure::kErrored; + } + if (!condition.matched) { + return AddError(peek(), "unable to parse condition expression"); + } + + return create(source(), condition.value); +} + +// function_decl +// : function_header compound_statement +Maybe Parser::function_decl(AttributeList& attrs) { + MultiTokenSource source(this); + + auto header = function_header(); + if (header.errored) { + if (sync_to(Token::Type::kBraceLeft, /* consume: */ false)) { + // There were errors in the function header, but the parser has managed to + // resynchronize with the opening brace. As there's no outer + // synchronization token for function declarations, attempt to parse the + // function body. The AST isn't used as we've already errored, but this + // catches any errors inside the body, and can help keep the parser in + // sync. + expect_compound_statement("function body"); + } + return Failure::kErrored; + } + if (!header.matched) { + return Failure::kNoMatch; + } + + bool errored = false; + + auto body = expect_compound_statement("function body"); + if (body.errored) { + errored = true; + } + + if (errored) { + return Failure::kErrored; + } + + TINT_DEFER(attrs.Clear()); + + return builder_.Func(source, header->name, header->params, header->return_type, body.value, + std::move(attrs), header->return_type_attributes); +} + +// function_header +// : FN IDENT PAREN_LEFT param_list PAREN_RIGHT return_type_specifier_optional +// return_type_specifier_optional +// : +// | ARROW attribute_list* type_specifier +Maybe Parser::function_header() { + Source source; + if (!match(Token::Type::kFn, &source)) { + return Failure::kNoMatch; + } + + const char* use = "function declaration"; + bool errored = false; + + auto name = expect_ident(use); + if (name.errored) { + errored = true; + if (!sync_to(Token::Type::kParenLeft, /* consume: */ false)) { + return Failure::kErrored; + } + } + + auto params = expect_paren_block(use, [&] { return expect_param_list(); }); + if (params.errored) { + errored = true; + if (!synchronized_) { + return Failure::kErrored; + } + } + + ast::Type return_type; + AttributeList return_attributes; + + if (match(Token::Type::kArrow)) { + auto attrs = attribute_list(); + if (attrs.errored) { + return Failure::kErrored; + } + return_attributes = attrs.value; + + auto type = type_specifier(); + if (type.errored) { + errored = true; + } else if (!type.matched) { + return AddError(peek(), "unable to determine function return type"); + } else { + return_type = type.value; + } + } else { + return_type = builder_.ty.void_(); + } + + if (errored) { + return Failure::kErrored; + } + + return FunctionHeader{ + source, name.value, std::move(params.value), return_type, std::move(return_attributes), + }; +} + +// param_list +// : +// | (param COMMA)* param COMMA? +Expect Parser::expect_param_list() { + ParameterList ret; + while (continue_parsing()) { + // Check for the end of the list. + auto& t = peek(); + if (!t.IsIdentifier() && !t.Is(Token::Type::kAttr)) { + break; + } + + auto param = expect_param(); + if (param.errored) { + return Failure::kErrored; + } + ret.Push(param.value); + + if (!match(Token::Type::kComma)) { + break; + } + } + + return ret; +} + +// param +// : attribute_list* ident COLON type_specifier +Expect Parser::expect_param() { + auto attrs = attribute_list(); + + auto decl = expect_ident_with_type_specifier("parameter"); + if (decl.errored) { + return Failure::kErrored; + } + + return builder_.Param(decl->name->source, // source + decl->name, // symbol + decl->type, // type + std::move(attrs.value)); // attributes +} + +// compound_statement +// : attribute* BRACE_LEFT statement* BRACE_RIGHT +Expect Parser::expect_compound_statement(std::string_view use) { + auto attrs = attribute_list(); + if (attrs.errored) { + return Failure::kErrored; + } + return expect_compound_statement(attrs.value, use); +} + +// compound_statement +// : attribute* BRACE_LEFT statement* BRACE_RIGHT +Expect Parser::expect_compound_statement(AttributeList& attrs, + std::string_view use) { + MultiTokenSource source(this); + auto stmts = + expect_brace_block(use, [&]() -> Expect { return expect_statements(); }); + if (stmts.errored) { + return Failure::kErrored; + } + TINT_DEFER(attrs.Clear()); + return create(source(), stmts.value, std::move(attrs)); +} + +// paren_expression +// : PAREN_LEFT expression PAREN_RIGHT +Expect Parser::expect_paren_expression() { + return expect_paren_block("", [&]() -> Expect { + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError(peek(), "unable to parse expression"); + } + + return expr.value; + }); +} + +// statements +// : statement* +Expect Parser::expect_statements() { + bool errored = false; + StatementList stmts; + + while (continue_parsing()) { + auto stmt = statement(); + if (stmt.errored) { + errored = true; + } else if (stmt.matched) { + stmts.Push(stmt.value); + } else { + break; + } + } + + if (errored) { + return Failure::kErrored; + } + + return stmts; +} + +// statement +// : SEMICOLON +// | if_statement +// | switch_statement +// | loop_statement +// | for_statement +// | while_statement +// | compound_statement +// | non_block_statement // Note, we inject an extra rule in here for simpler parsing +Maybe Parser::statement() { + while (match(Token::Type::kSemicolon)) { + // Skip empty statements + } + + auto attrs = attribute_list(); + if (attrs.errored) { + return Failure::kErrored; + } + TINT_DEFER(expect_attributes_consumed(attrs.value)); + + // Non-block statements that error can resynchronize on semicolon. + auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); }); + if (stmt.errored) { + return Failure::kErrored; + } + if (stmt.matched) { + return stmt; + } + + auto stmt_if = if_statement(attrs.value); + if (stmt_if.errored) { + return Failure::kErrored; + } + if (stmt_if.matched) { + return stmt_if.value; + } + + auto sw = switch_statement(attrs.value); + if (sw.errored) { + return Failure::kErrored; + } + if (sw.matched) { + return sw.value; + } + + auto loop = loop_statement(attrs.value); + if (loop.errored) { + return Failure::kErrored; + } + if (loop.matched) { + return loop.value; + } + + auto stmt_for = for_statement(attrs.value); + if (stmt_for.errored) { + return Failure::kErrored; + } + if (stmt_for.matched) { + return stmt_for.value; + } + + auto stmt_while = while_statement(attrs.value); + if (stmt_while.errored) { + return Failure::kErrored; + } + if (stmt_while.matched) { + return stmt_while.value; + } + + if (peek_is(Token::Type::kBraceLeft)) { + auto body = expect_compound_statement(attrs.value, "block statement"); + if (body.errored) { + return Failure::kErrored; + } + return body.value; + } + + return Failure::kNoMatch; +} + +// non_block_statement (continued) +// : return_statement SEMICOLON +// | func_call_statement SEMICOLON +// | variable_statement SEMICOLON +// | break_statement SEMICOLON +// | continue_statement SEMICOLON +// | DISCARD SEMICOLON +// | variable_updating_statement SEMICOLON +// | const_assert_statement SEMICOLON +Maybe Parser::non_block_statement() { + auto stmt = [&]() -> Maybe { + auto ret_stmt = return_statement(); + if (ret_stmt.errored) { + return Failure::kErrored; + } + if (ret_stmt.matched) { + return ret_stmt.value; + } + + auto func = func_call_statement(); + if (func.errored) { + return Failure::kErrored; + } + if (func.matched) { + return func.value; + } + + auto var = variable_statement(); + if (var.errored) { + return Failure::kErrored; + } + if (var.matched) { + return var.value; + } + + auto b = break_statement(); + if (b.errored) { + return Failure::kErrored; + } + if (b.matched) { + return b.value; + } + + auto cont = continue_statement(); + if (cont.errored) { + return Failure::kErrored; + } + if (cont.matched) { + return cont.value; + } + + Source source; + if (match(Token::Type::kDiscard, &source)) { + return builder_.Discard(source); + } + + // Note, this covers assignment, increment and decrement + auto assign = variable_updating_statement(); + if (assign.errored) { + return Failure::kErrored; + } + if (assign.matched) { + return assign.value; + } + + auto stmt_static_assert = const_assert_statement(); + if (stmt_static_assert.errored) { + return Failure::kErrored; + } + if (stmt_static_assert.matched) { + return stmt_static_assert.value; + } + + return Failure::kNoMatch; + }(); + + if (stmt.matched && !expect(stmt->Name(), Token::Type::kSemicolon)) { + return Failure::kErrored; + } + return stmt; +} + +// return_statement +// : RETURN expression? +Maybe Parser::return_statement() { + Source source; + if (!match(Token::Type::kReturn, &source)) { + return Failure::kNoMatch; + } + + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + + return expr.matched ? builder_.Return(source, expr.value) : builder_.Return(source); +} + +// variable_statement +// : variable_decl +// | variable_decl EQUAL expression +// | LET optionally_typed_ident EQUAL expression +// | CONST optionally_typed_ident EQUAL expression +Maybe Parser::variable_statement() { + MultiTokenSource decl_source_range(this); + if (match(Token::Type::kConst)) { + auto typed_ident = expect_optionally_typed_ident("'const' declaration"); + if (typed_ident.errored) { + return Failure::kErrored; + } + + auto decl_source = decl_source_range(); + + if (!expect("'const' declaration", Token::Type::kEqual)) { + return Failure::kErrored; + } + + auto initializer = expression(); + if (initializer.errored) { + return Failure::kErrored; + } + if (!initializer.matched) { + return AddError(peek(), "missing initializer for 'const' declaration"); + } + + auto* const_ = builder_.Const(typed_ident->name->source, // source + typed_ident->name, // symbol + typed_ident->type, // type + initializer.value); // initializer + + return create(decl_source, const_); + } + + if (match(Token::Type::kLet)) { + auto typed_ident = expect_optionally_typed_ident("'let' declaration"); + if (typed_ident.errored) { + return Failure::kErrored; + } + + auto decl_source = decl_source_range(); + + if (!expect("'let' declaration", Token::Type::kEqual)) { + return Failure::kErrored; + } + + auto initializer = expression(); + if (initializer.errored) { + return Failure::kErrored; + } + if (!initializer.matched) { + return AddError(peek(), "missing initializer for 'let' declaration"); + } + + auto* let = builder_.Let(typed_ident->name->source, // source + typed_ident->name, // symbol + typed_ident->type, // type + initializer.value); // initializer + + return create(decl_source, let); + } + + auto decl = variable_decl(); + if (decl.errored) { + return Failure::kErrored; + } + if (!decl.matched) { + return Failure::kNoMatch; + } + + auto decl_source = decl_source_range(); + + const ast::Expression* initializer = nullptr; + if (match(Token::Type::kEqual)) { + auto initializer_expr = expression(); + if (initializer_expr.errored) { + return Failure::kErrored; + } + if (!initializer_expr.matched) { + return AddError(peek(), "missing initializer for 'var' declaration"); + } + + initializer = initializer_expr.value; + } + + auto* var = builder_.create(decl_source, // source + builder_.Ident(decl->name), // symbol + decl->type, // type + decl->address_space, // address space + decl->access, // access control + initializer, // initializer + tint::Empty); // attributes + + return create(var->source, var); +} + +// if_statement +// : attribute* if_clause else_if_clause* else_clause? +// if_clause: +// : IF expression compound_stmt +// else_if_clause: +// : ELSE IF expression compound_stmt +// else_clause +// : ELSE compound_statement +Maybe Parser::if_statement(AttributeList& attrs) { + // Parse if-else chains iteratively instead of recursively, to avoid + // stack-overflow for long chains of if-else statements. + + struct IfInfo { + Source source; + const ast::Expression* condition; + const ast::BlockStatement* body; + AttributeList attributes; + }; + + // Parse an if statement, capturing the source, condition, and body statement. + auto parse_if = [&]() -> Maybe { + Source source; + if (!match(Token::Type::kIf, &source)) { + return Failure::kNoMatch; + } + + auto condition = expression(); + if (condition.errored) { + return Failure::kErrored; + } + if (!condition.matched) { + return AddError(peek(), "unable to parse condition expression"); + } + + auto body = expect_compound_statement("if statement"); + if (body.errored) { + return Failure::kErrored; + } + + TINT_DEFER(attrs.Clear()); + return IfInfo{source, condition.value, body.value, std::move(attrs)}; + }; + + std::vector statements; + + // Parse the first if statement. + auto first_if = parse_if(); + if (first_if.errored) { + return Failure::kErrored; + } else if (!first_if.matched) { + return Failure::kNoMatch; + } + statements.push_back(first_if.value); + + // Parse the components of every "else {if}" in the chain. + const ast::Statement* last_stmt = nullptr; + while (continue_parsing()) { + if (!match(Token::Type::kElse)) { + break; + } + + // Try to parse an "else if". + auto else_if = parse_if(); + if (else_if.errored) { + return Failure::kErrored; + } else if (else_if.matched) { + statements.push_back(else_if.value); + continue; + } + + // If it wasn't an "else if", it must just be an "else". + auto else_body = expect_compound_statement("else statement"); + if (else_body.errored) { + return Failure::kErrored; + } + last_stmt = else_body.value; + break; + } + + // Now walk back through the statements to create their AST nodes. + for (auto itr = statements.rbegin(); itr != statements.rend(); itr++) { + last_stmt = create(itr->source, itr->condition, itr->body, last_stmt, + std::move(itr->attributes)); + } + + return last_stmt->As(); +} + +// switch_statement +// : attribute* SWITCH expression BRACKET_LEFT switch_body+ BRACKET_RIGHT +Maybe Parser::switch_statement(AttributeList& attrs) { + Source source; + if (!match(Token::Type::kSwitch, &source)) { + return Failure::kNoMatch; + } + + auto condition = expression(); + if (condition.errored) { + return Failure::kErrored; + } + if (!condition.matched) { + return AddError(peek(), "unable to parse selector expression"); + } + + auto body_attrs = attribute_list(); + if (body_attrs.errored) { + return Failure::kErrored; + } + + auto body = expect_brace_block("switch statement", [&]() -> Expect { + bool errored = false; + CaseStatementList list; + while (continue_parsing()) { + auto stmt = switch_body(); + if (stmt.errored) { + errored = true; + continue; + } + if (!stmt.matched) { + break; + } + list.Push(stmt.value); + } + if (errored) { + return Failure::kErrored; + } + return list; + }); + + if (body.errored) { + return Failure::kErrored; + } + + TINT_DEFER(attrs.Clear()); + return create(source, condition.value, body.value, std::move(attrs), + std::move(body_attrs.value)); +} + +// switch_body +// : CASE case_selectors COLON? compound_statement +// | DEFAULT COLON? compound_statement +Maybe Parser::switch_body() { + if (!peek_is(Token::Type::kCase) && !peek_is(Token::Type::kDefault)) { + return Failure::kNoMatch; + } + + auto& t = next(); + + CaseSelectorList selector_list; + if (t.Is(Token::Type::kCase)) { + auto selectors = expect_case_selectors(); + if (selectors.errored) { + return Failure::kErrored; + } + + selector_list = std::move(selectors.value); + } else { + // Push the default case selector + selector_list.Push(create(t.source())); + } + + // Consume the optional colon if present. + match(Token::Type::kColon); + + const char* use = "case statement"; + auto body = expect_compound_statement(use); + if (body.errored) { + return Failure::kErrored; + } + + return create(t.source(), selector_list, body.value); +} + +// case_selectors +// : case_selector (COMMA case_selector)* COMMA? +Expect Parser::expect_case_selectors() { + CaseSelectorList selectors; + + while (continue_parsing()) { + auto expr = case_selector(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + break; + } + selectors.Push(expr.value); + + if (!match(Token::Type::kComma)) { + break; + } + } + + if (selectors.IsEmpty()) { + return AddError(peek(), "expected case selector expression or `default`"); + } + + return selectors; +} + +// case_selector +// : DEFAULT +// | expression +Maybe Parser::case_selector() { + auto& p = peek(); + + if (match(Token::Type::kDefault)) { + return create(p.source()); + } + + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return Failure::kNoMatch; + } + return create(p.source(), expr.value); +} + +// loop_statement +// : attribute* LOOP attribute* BRACKET_LEFT statements continuing_statement? BRACKET_RIGHT +Maybe Parser::loop_statement(AttributeList& attrs) { + Source source; + if (!match(Token::Type::kLoop, &source)) { + return Failure::kNoMatch; + } + + auto body_attrs = attribute_list(); + if (body_attrs.errored) { + return Failure::kErrored; + } + + Maybe continuing(Failure::kErrored); + MultiTokenSource body_source(this); + auto body = expect_brace_block("loop", [&]() -> Maybe { + auto stmts = expect_statements(); + if (stmts.errored) { + return Failure::kErrored; + } + + continuing = continuing_statement(); + if (continuing.errored) { + return Failure::kErrored; + } + return stmts; + }); + if (body.errored) { + return Failure::kErrored; + } + + TINT_DEFER(attrs.Clear()); + return create( + source, create(body_source(), body.value, std::move(body_attrs.value)), + continuing.value, std::move(attrs)); +} + +ForHeader::ForHeader(const ast::Statement* init, + const ast::Expression* cond, + const ast::Statement* cont) + : initializer(init), condition(cond), continuing(cont) {} + +ForHeader::~ForHeader() = default; + +// (variable_statement | variable_updating_statement | func_call_statement)? +Maybe Parser::for_header_initializer() { + auto call = func_call_statement(); + if (call.errored) { + return Failure::kErrored; + } + if (call.matched) { + return call.value; + } + + auto var = variable_statement(); + if (var.errored) { + return Failure::kErrored; + } + if (var.matched) { + return var.value; + } + + auto assign = variable_updating_statement(); + if (assign.errored) { + return Failure::kErrored; + } + if (assign.matched) { + return assign.value; + } + + return Failure::kNoMatch; +} + +// (variable_updating_statement | func_call_statement)? +Maybe Parser::for_header_continuing() { + auto call_stmt = func_call_statement(); + if (call_stmt.errored) { + return Failure::kErrored; + } + if (call_stmt.matched) { + return call_stmt.value; + } + + auto assign = variable_updating_statement(); + if (assign.errored) { + return Failure::kErrored; + } + if (assign.matched) { + return assign.value; + } + + return Failure::kNoMatch; +} + +// for_header +// : for_header_initializer? SEMICOLON expression? SEMICOLON for_header_continuing? +Expect> Parser::expect_for_header() { + auto initializer = for_header_initializer(); + if (initializer.errored) { + return Failure::kErrored; + } + + if (!expect("initializer in for loop", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + auto condition = expression(); + if (condition.errored) { + return Failure::kErrored; + } + + if (!expect("condition in for loop", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + auto continuing = for_header_continuing(); + if (continuing.errored) { + return Failure::kErrored; + } + + return std::make_unique(initializer.value, condition.value, continuing.value); +} + +// for_statement +// : FOR PAREN_LEFT for_header PAREN_RIGHT compound_statement +Maybe Parser::for_statement(AttributeList& attrs) { + Source source; + if (!match(Token::Type::kFor, &source)) { + return Failure::kNoMatch; + } + + auto header = expect_paren_block("for loop", [&] { return expect_for_header(); }); + if (header.errored) { + return Failure::kErrored; + } + + auto body = expect_compound_statement("for loop"); + if (body.errored) { + return Failure::kErrored; + } + + TINT_DEFER(attrs.Clear()); + return create(source, header->initializer, header->condition, + header->continuing, body.value, std::move(attrs)); +} + +// while_statement +// : attribute* WHILE expression compound_statement +Maybe Parser::while_statement(AttributeList& attrs) { + Source source; + if (!match(Token::Type::kWhile, &source)) { + return Failure::kNoMatch; + } + + auto condition = expression(); + if (condition.errored) { + return Failure::kErrored; + } + if (!condition.matched) { + return AddError(peek(), "unable to parse while condition expression"); + } + + auto body = expect_compound_statement("while loop"); + if (body.errored) { + return Failure::kErrored; + } + + TINT_DEFER(attrs.Clear()); + return create(source, condition.value, body.value, std::move(attrs)); +} + +// func_call_statement +// : IDENT argument_expression_list +Maybe Parser::func_call_statement() { + auto& t = peek(); + auto& t2 = peek(1); + if (!t.IsIdentifier() || !t2.Is(Token::Type::kParenLeft)) { + return Failure::kNoMatch; + } + + next(); // Consume the first peek + + auto params = expect_argument_expression_list("function call"); + if (params.errored) { + return Failure::kErrored; + } + + return builder_.CallStmt( + t.source(), + builder_.Call(t.source(), builder_.Expr(t.source(), t.to_str()), std::move(params.value))); +} + +// break_statement +// : BREAK +Maybe Parser::break_statement() { + Source source; + if (!match(Token::Type::kBreak, &source)) { + return Failure::kNoMatch; + } + + return create(source); +} + +// continue_statement +// : CONTINUE +Maybe Parser::continue_statement() { + Source source; + if (!match(Token::Type::kContinue, &source)) { + return Failure::kNoMatch; + } + + return create(source); +} + +// break_if_statement: +// 'break' 'if' expression semicolon +Maybe Parser::break_if_statement() { + auto& t1 = peek(); + auto& t2 = peek(1); + + // Match both the `break` and `if` at the same time. + if (!t1.Is(Token::Type::kBreak) || !t2.Is(Token::Type::kIf)) { + return Failure::kNoMatch; + } + next(); // Consume the peek + next(); // Consume the peek + + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError(t1, "expected expression for `break-if`"); + } + if (!expect("`break-if` statement", Token::Type::kSemicolon)) { + return Failure::kErrored; + } + + return create(t1.source(), expr.value); +} + +// continuing_compound_statement: +// attribute* BRACE_LEFT statement* break_if_statement? BRACE_RIGHT +Maybe Parser::continuing_compound_statement() { + auto attrs = attribute_list(); + if (attrs.errored) { + return Failure::kErrored; + } + + MultiTokenSource source(this); + auto body = expect_brace_block("", [&]() -> Expect { + StatementList stmts; + + while (continue_parsing()) { + // Need to skip empty statements otherwise we can end up in the `statement` code below, + // then we skip the `;` and parse a `break-if` as a `break`. + while (match(Token::Type::kSemicolon)) { + // Skip empty statements + } + + // Note, break-if has to parse before statements because statements includes `break` + auto break_if = break_if_statement(); + if (break_if.errored) { + return Failure::kErrored; + } + if (break_if.matched) { + stmts.Push(break_if.value); + continue; + } + + auto stmt = statement(); + if (stmt.errored) { + return Failure::kErrored; + } + if (!stmt.matched) { + break; + } + stmts.Push(stmt.value); + } + + return stmts; + }); + if (body.errored) { + return Failure::kErrored; + } + + return create(source(), body.value, std::move(attrs.value)); +} + +// continuing_statement +// : CONTINUING continuing_compound_statement +Maybe Parser::continuing_statement() { + if (!match(Token::Type::kContinuing)) { + return create(Source{}, tint::Empty, tint::Empty); + } + + return continuing_compound_statement(); +} + +// primary_expression +// : const_literal +// | IDENT argument_expression_list? +// | paren_expression +// +// Note, PAREN_LEFT ( expression ( COMMA expression ) * COMMA? )? PAREN_RIGHT is replaced +// with `argument_expression_list`. +Maybe Parser::primary_expression() { + auto lit = const_literal(); + if (lit.errored) { + return Failure::kErrored; + } + if (lit.matched) { + return lit.value; + } + + auto& t = peek(); + if (t.IsIdentifier()) { + MultiTokenSource source(this); + next(); + + const ast::Identifier* ident = nullptr; + + if (peek_is(Token::Type::kTemplateArgsLeft)) { + auto tmpl_args = expect_template_arg_block("template arguments", [&] { + return expect_expression_list("template argument list", + Token::Type::kTemplateArgsRight); + }); + ident = builder_.Ident(source(), t.to_str(), std::move(tmpl_args.value)); + } else { + ident = builder_.Ident(source(), t.to_str()); + } + + if (peek_is(Token::Type::kParenLeft)) { + auto params = expect_argument_expression_list("function call"); + if (params.errored) { + return Failure::kErrored; + } + + return builder_.Call(source(), ident, std::move(params.value)); + } + + return builder_.Expr(ident); + } + + if (t.Is(Token::Type::kParenLeft)) { + auto paren = expect_paren_expression(); + if (paren.errored) { + return Failure::kErrored; + } + + return paren.value; + } + + return Failure::kNoMatch; +} + +// component_or_swizzle_specifier +// : +// | BRACE_LEFT expression BRACE_RIGHT component_or_swizzle_specifier? +// | PERIOD member_ident component_or_swizzle_specifier? +// | PERIOD swizzle_name component_or_swizzle_specifier? +Maybe Parser::component_or_swizzle_specifier( + const ast::Expression* prefix) { + MultiTokenSource source(this, prefix->source); + + while (continue_parsing()) { + if (match(Token::Type::kBracketLeft)) { + auto res = sync(Token::Type::kBracketRight, [&]() -> Maybe { + auto param = expression(); + if (param.errored) { + return Failure::kErrored; + } + if (!param.matched) { + return AddError(peek(), "unable to parse expression inside []"); + } + + if (!expect("index accessor", Token::Type::kBracketRight)) { + return Failure::kErrored; + } + + return create(source(), prefix, param.value); + }); + + if (res.errored) { + return res; + } + prefix = res.value; + continue; + } + + if (match(Token::Type::kPeriod)) { + auto ident = expect_ident("member accessor"); + if (ident.errored) { + return Failure::kErrored; + } + + prefix = builder_.MemberAccessor(source(), prefix, ident.value); + continue; + } + + return prefix; + } + + return Failure::kErrored; +} + +// argument_expression_list +// : PAREN_LEFT ((expression COMMA)* expression COMMA?)? PAREN_RIGHT +Expect Parser::expect_argument_expression_list(std::string_view use) { + return expect_paren_block(use, [&]() -> Expect { // + auto list = expression_list(use, Token::Type::kParenRight); + if (list.errored) { + return Failure::kErrored; + } + return list.value; + }); +} + +// bitwise_expression.post.unary_expression +// : AND unary_expression (AND unary_expression)* +// | OR unary_expression (OR unary_expression)* +// | XOR unary_expression (XOR unary_expression)* +Maybe Parser::bitwise_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source) { + MultiTokenSource source(this, lhs_source); + auto& t = peek(); + + std::optional op; + switch (t.type()) { + case Token::Type::kAnd: + op = core::BinaryOp::kAnd; + break; + case Token::Type::kOr: + op = core::BinaryOp::kOr; + break; + case Token::Type::kXor: + op = core::BinaryOp::kXor; + break; + default: + return Failure::kNoMatch; + } + next(); // Consume t + + while (continue_parsing()) { + auto rhs = unary_expression(); + if (rhs.errored) { + return Failure::kErrored; + } + if (!rhs.matched) { + return AddError(peek(), std::string("unable to parse right side of ") + + std::string(t.to_name()) + " expression"); + } + + lhs = create(source(), *op, lhs, rhs.value); + + if (!match(t.type())) { + return lhs; + } + } + return Failure::kErrored; +} + +// multiplicative_operator +// : FORWARD_SLASH +// | MODULO +// | STAR +Maybe Parser::multiplicative_operator() { + if (match(Token::Type::kForwardSlash)) { + return core::BinaryOp::kDivide; + } + if (match(Token::Type::kMod)) { + return core::BinaryOp::kModulo; + } + if (match(Token::Type::kStar)) { + return core::BinaryOp::kMultiply; + } + + return Failure::kNoMatch; +} + +// multiplicative_expression.post.unary_expression +// : (multiplicative_operator unary_expression)* +Expect Parser::expect_multiplicative_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source) { + MultiTokenSource source(this, lhs_source); + while (continue_parsing()) { + auto& t = peek(); + + auto op = multiplicative_operator(); + if (op.errored) { + return Failure::kErrored; + } + if (!op.matched) { + return lhs; + } + + auto rhs = unary_expression(); + if (rhs.errored) { + return Failure::kErrored; + } + if (!rhs.matched) { + return AddError(peek(), std::string("unable to parse right side of ") + + std::string(t.to_name()) + " expression"); + } + + lhs = create(source(), op.value, lhs, rhs.value); + } + return Failure::kErrored; +} + +// additive_operator +// : MINUS +// | PLUS +// +// Note, this also splits a `--` token. This is currently safe as the only way to get into +// here is through additive expression and rules for where `--` are allowed are very restrictive. +Maybe Parser::additive_operator() { + if (match(Token::Type::kPlus)) { + return core::BinaryOp::kAdd; + } + + auto& t = peek(); + if (t.Is(Token::Type::kMinusMinus)) { + next(); + split_token(Token::Type::kMinus, Token::Type::kMinus); + } else if (t.Is(Token::Type::kMinus)) { + next(); + } else { + return Failure::kNoMatch; + } + + return core::BinaryOp::kSubtract; +} + +// additive_expression.pos.unary_expression +// : (additive_operator unary_expression expect_multiplicative_expression.post.unary_expression)* +// +// This is `( additive_operator unary_expression ( multiplicative_operator unary_expression )* )*` +// split apart. +Expect Parser::expect_additive_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source) { + MultiTokenSource source(this, lhs_source); + while (continue_parsing()) { + auto& t = peek(); + + auto op = additive_operator(); + if (op.errored) { + return Failure::kErrored; + } + if (!op.matched) { + return lhs; + } + + auto unary = unary_expression(); + if (unary.errored) { + return Failure::kErrored; + } + if (!unary.matched) { + return AddError(peek(), std::string("unable to parse right side of ") + + std::string(t.to_name()) + " expression"); + } + + // The multiplicative binds tighter, so pass the unary into that and build that expression + // before creating the additive expression. + auto rhs = expect_multiplicative_expression_post_unary_expression(unary.value, lhs_source); + if (rhs.errored) { + return Failure::kErrored; + } + + lhs = create(source(), op.value, lhs, rhs.value); + } + return Failure::kErrored; +} + +// math_expression.post.unary_expression +// : multiplicative_expression.post.unary_expression additive_expression.post.unary_expression +// +// This is `( multiplicative_operator unary_expression )* ( additive_operator unary_expression ( +// multiplicative_operator unary_expression )* )*` split apart. +Expect Parser::expect_math_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source) { + MultiTokenSource source(this, lhs_source); + + auto rhs = expect_multiplicative_expression_post_unary_expression(lhs, source); + if (rhs.errored) { + return Failure::kErrored; + } + + return expect_additive_expression_post_unary_expression(rhs.value, source()); +} + +// shift_expression +// : unary_expression shift_expression.post.unary_expression +Maybe Parser::shift_expression() { + MultiTokenSource source(this); + auto lhs = unary_expression(); + if (lhs.errored) { + return Failure::kErrored; + } + if (!lhs.matched) { + return Failure::kNoMatch; + } + return expect_shift_expression_post_unary_expression(lhs.value, source); +} + +// shift_expression.post.unary_expression +// : math_expression.post.unary_expression? +// | SHIFT_LEFT unary_expression +// | SHIFT_RIGHT unary_expression +// +// Note, add the `math_expression.post.unary_expression` is added here to make +// implementation simpler. +Expect Parser::expect_shift_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source) { + MultiTokenSource source(this, lhs_source); + + auto& t = peek(); + if (match(Token::Type::kShiftLeft) || match(Token::Type::kShiftRight)) { + std::string name; + std::optional op; + if (t.Is(Token::Type::kShiftLeft)) { + op = core::BinaryOp::kShiftLeft; + name = "<<"; + } else if (t.Is(Token::Type::kShiftRight)) { + op = core::BinaryOp::kShiftRight; + name = ">>"; + } + + auto& rhs_start = peek(); + auto rhs = unary_expression(); + if (rhs.errored) { + return Failure::kErrored; + } + if (!rhs.matched) { + return AddError(rhs_start, + std::string("unable to parse right side of ") + name + " expression"); + } + return create(source(), *op, lhs, rhs.value); + } + + return expect_math_expression_post_unary_expression(lhs, source); +} + +// relational_expression +// : unary_expression relational_expression.post.unary_expression +Maybe Parser::relational_expression() { + MultiTokenSource source(this); + auto lhs = unary_expression(); + if (lhs.errored) { + return Failure::kErrored; + } + if (!lhs.matched) { + return Failure::kNoMatch; + } + return expect_relational_expression_post_unary_expression(lhs.value, source); +} + +// relational_expression.post.unary_expression +// : shift_expression.post.unary_expression +// | shift_expression.post.unary_expression EQUAL_EQUAL shift_expression +// | shift_expression.post.unary_expression GREATER_THAN shift_expression +// | shift_expression.post.unary_expression GREATER_THAN_EQUAL shift_expression +// | shift_expression.post.unary_expression LESS_THAN shift_expression +// | shift_expression.post.unary_expression LESS_THAN_EQUAL shift_expression +// | shift_expression.post.unary_expression NOT_EQUAL shift_expression +// +// Note, a `shift_expression` element was added to simplify many of the right sides +Expect Parser::expect_relational_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source) { + MultiTokenSource source(this, lhs_source); + + auto lhs_result = expect_shift_expression_post_unary_expression(lhs, source); + if (lhs_result.errored) { + return Failure::kErrored; + } + lhs = lhs_result.value; + + auto& tok_op = peek(); + + std::optional op; + switch (tok_op.type()) { + case Token::Type::kLessThan: + op = core::BinaryOp::kLessThan; + break; + case Token::Type::kGreaterThan: + op = core::BinaryOp::kGreaterThan; + break; + case Token::Type::kLessThanEqual: + op = core::BinaryOp::kLessThanEqual; + break; + case Token::Type::kGreaterThanEqual: + op = core::BinaryOp::kGreaterThanEqual; + break; + case Token::Type::kEqualEqual: + op = core::BinaryOp::kEqual; + break; + case Token::Type::kNotEqual: + op = core::BinaryOp::kNotEqual; + break; + default: + return lhs; + } + + next(); // consume tok_op + + auto& tok_rhs = peek(); + auto rhs = shift_expression(); + if (rhs.errored) { + return Failure::kErrored; + } + if (!rhs.matched) { + return AddError(tok_rhs, std::string("unable to parse right side of ") + + std::string(tok_op.to_name()) + " expression"); + } + + return create(source(), *op, lhs, rhs.value); +} + +Expect Parser::expect_expression(std::string_view use) { + auto& t = peek(); + auto expr = expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (expr.matched) { + return expr.value; + } + return AddError(t, "expected expression for " + std::string(use)); +} + +Maybe Parser::expression_list(std::string_view use, + Token::Type terminator) { + if (peek_is(terminator)) { + return Failure::kNoMatch; + } + auto list = expect_expression_list(use, terminator); + if (list.errored) { + return Failure::kErrored; + } + return list.value; +} + +Expect Parser::expect_expression_list(std::string_view use, + Token::Type terminator) { + Parser::ExpressionList exprs; + while (continue_parsing()) { + auto expr = expect_expression(use); + if (expr.errored) { + return Failure::kErrored; + } + exprs.Push(expr.value); + if (peek_is(terminator)) { + break; + } + + // Check if the next token is a template start, which was likely intended as a less-than. + if (expect_next_not_template_list(expr->source).errored) { + return Failure::kErrored; // expect_next_not_template_list() raised an error. + } + if (!match(Token::Type::kComma)) { + // Next expression is not a terminator or comma, so this is a parse error. + + // Check if last parsed expression was a templated identifier, which was likely indented + // as a less-than / greater-than. + if (expect_not_templated_ident_expr(expr.value).errored) { + return Failure::kErrored; // expect_not_templated_ident_expr() raised an error. + } + + // Emit the expected ',' error + expect(use, Token::Type::kComma); + return Failure::kErrored; + } + if (peek_is(terminator)) { + break; + } + } + return exprs; +} + +// expression +// : unary_expression bitwise_expression.post.unary_expression +// | unary_expression relational_expression.post.unary_expression +// | unary_expression relational_expression.post.unary_expression and_and +// relational_expression ( and_and relational_expression )* +// | unary_expression relational_expression.post.unary_expression or_or +// relational_expression ( or_or relational_expression )* +// +// Note, a `relational_expression` element was added to simplify many of the right sides +Maybe Parser::expression() { + MultiTokenSource source(this); + Source first_op; + auto expr = [&]() -> Maybe { + auto lhs = unary_expression(); + if (lhs.errored) { + return Failure::kErrored; + } + if (!lhs.matched) { + return Failure::kNoMatch; + } + + first_op = peek().source(); + + auto bitwise = bitwise_expression_post_unary_expression(lhs.value, source); + if (bitwise.errored) { + return Failure::kErrored; + } + if (bitwise.matched) { + return bitwise.value; + } + + auto relational = expect_relational_expression_post_unary_expression(lhs.value, source); + if (relational.errored) { + return Failure::kErrored; + } + auto* ret = relational.value; + + auto& t = peek(); + if (t.Is(Token::Type::kAndAnd) || t.Is(Token::Type::kOrOr)) { + core::BinaryOp op; + if (t.Is(Token::Type::kAndAnd)) { + op = core::BinaryOp::kLogicalAnd; + } else if (t.Is(Token::Type::kOrOr)) { + op = core::BinaryOp::kLogicalOr; + } + + while (continue_parsing()) { + auto& n = peek(); + if (!n.Is(t.type())) { + break; + } + next(); + + auto rhs = relational_expression(); + if (rhs.errored) { + return Failure::kErrored; + } + if (!rhs.matched) { + return AddError(peek(), std::string("unable to parse right side of ") + + std::string(t.to_name()) + " expression"); + } + + ret = create(source(), op, ret, rhs.value); + } + } + return ret; + }(); + + if (expr.matched) { + // Note, expression is greedy an will consume all the operators of the same type + // so, `a & a & a` would all be consumed above. If you see any binary operator + // after this then it _must_ be a different one, and hence an error. + if (auto* lhs = expr->As()) { + if (auto& n = peek(); n.IsBinaryOperator()) { + AddError(Source::Combine(first_op, n.source()), + std::string("mixing '") + ast::Operator(lhs->op) + "' and '" + + std::string(n.to_name()) + "' requires parenthesis"); + return Failure::kErrored; + } + } + } + + return expr; +} + +// singular_expression +// : primary_expression postfix_expr +Maybe Parser::singular_expression() { + auto prefix = primary_expression(); + if (prefix.errored) { + return Failure::kErrored; + } + if (!prefix.matched) { + return Failure::kNoMatch; + } + + return component_or_swizzle_specifier(prefix.value); +} + +// unary_expression +// : singular_expression +// | MINUS unary_expression +// | BANG unary_expression +// | TILDE unary_expression +// | STAR unary_expression +// | AND unary_expression +// +// The `primary_expression component_or_swizzle_specifier ?` is moved out into a +// `singular_expression` +Maybe Parser::unary_expression() { + MultiTokenSource source(this); + + auto& t = peek(); + + // Note that an valid unary Negation expression starts with MINUS can be nested by another + // Negation unary expression, results in the form of (--e). The two MINUS might be tokenized as + // a single kMinusMinus, while kMinusMinus should only be used in a variable updating statement. + // The token should be split and the expression should be parsed as (-(-e)). + // There is no unary expression (+e) so (++e) is not a valid unary expression and kPlusPlus is + // unexpected here. Special casing kPlusPlus to generate a more specific error message. + if (peek_is(Token::Type::kPlusPlus)) { + return AddError(peek(0).source(), + "prefix increment and decrement operators are not supported"); + } + + core::UnaryOp op; + if (t.Is(Token::Type::kMinusMinus)) { + // Split the kMinusMinus token into two kMinus tokens. + next(); + split_token(Token::Type::kMinus, Token::Type::kMinus); + op = core::UnaryOp::kNegation; + } else if (match(Token::Type::kMinus)) { + op = core::UnaryOp::kNegation; + } else if (match(Token::Type::kBang)) { + op = core::UnaryOp::kNot; + } else if (match(Token::Type::kTilde)) { + op = core::UnaryOp::kComplement; + } else if (match(Token::Type::kStar)) { + op = core::UnaryOp::kIndirection; + } else if (match(Token::Type::kAnd)) { + op = core::UnaryOp::kAddressOf; + } else { + return singular_expression(); + } + + if (parse_depth_ >= kMaxParseDepth) { + // We've hit a maximum parser recursive depth. + // We can't call into unary_expression() as we might stack overflow. + // Instead, report an error + AddError(peek(), "maximum parser recursive depth reached"); + return Failure::kErrored; + } + + ++parse_depth_; + auto expr = unary_expression(); + --parse_depth_; + + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError( + peek(), "unable to parse right side of " + std::string(t.to_name()) + " expression"); + } + + return create(source(), op, expr.value); +} + +// compound_assignment_operator +// : plus_equal +// | minus_equal +// | times_equal +// | division_equal +// | modulo_equal +// | and_equal +// | or_equal +// | xor_equal +// | shift_right_equal +// | shift_left_equal +Maybe Parser::compound_assignment_operator() { + std::optional compound_op; + if (peek_is(Token::Type::kPlusEqual)) { + compound_op = core::BinaryOp::kAdd; + } else if (peek_is(Token::Type::kMinusEqual)) { + compound_op = core::BinaryOp::kSubtract; + } else if (peek_is(Token::Type::kTimesEqual)) { + compound_op = core::BinaryOp::kMultiply; + } else if (peek_is(Token::Type::kDivisionEqual)) { + compound_op = core::BinaryOp::kDivide; + } else if (peek_is(Token::Type::kModuloEqual)) { + compound_op = core::BinaryOp::kModulo; + } else if (peek_is(Token::Type::kAndEqual)) { + compound_op = core::BinaryOp::kAnd; + } else if (peek_is(Token::Type::kOrEqual)) { + compound_op = core::BinaryOp::kOr; + } else if (peek_is(Token::Type::kXorEqual)) { + compound_op = core::BinaryOp::kXor; + } else if (peek_is(Token::Type::kShiftLeftEqual)) { + compound_op = core::BinaryOp::kShiftLeft; + } else if (peek_is(Token::Type::kShiftRightEqual)) { + compound_op = core::BinaryOp::kShiftRight; + } + if (compound_op) { + next(); + return *compound_op; + } + return Failure::kNoMatch; +} + +// core_lhs_expression +// : ident +// | PAREN_LEFT lhs_expression PAREN_RIGHT +Maybe Parser::core_lhs_expression() { + auto& t = peek(); + if (t.IsIdentifier()) { + next(); + + return builder_.Expr(t.source(), t.to_str()); + } + + if (peek_is(Token::Type::kParenLeft)) { + return expect_paren_block("", [&]() -> Expect { + auto expr = lhs_expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError(t, "invalid expression"); + } + return expr.value; + }); + } + + return Failure::kNoMatch; +} + +// lhs_expression +// : core_lhs_expression component_or_swizzle_specifier ? +// | AND lhs_expression +// | STAR lhs_expression +Maybe Parser::lhs_expression() { + auto core_expr = core_lhs_expression(); + if (core_expr.errored) { + return Failure::kErrored; + } + if (core_expr.matched) { + return component_or_swizzle_specifier(core_expr.value); + } + + // Gather up all the `*`, `&` and `&&` tokens into a list and create all of the unary ops at + // once instead of recursing. This handles the case where the fuzzer decides >8k `*`s would be + // fun. + struct LHSData { + Source source; + core::UnaryOp op; + }; + Vector ops; + while (true) { + auto& t = peek(); + if (!t.Is(Token::Type::kAndAnd) && !t.Is(Token::Type::kAnd) && !t.Is(Token::Type::kStar)) { + break; + } + next(); // consume the peek + + if (t.Is(Token::Type::kAndAnd)) { + // The first `&` is consumed as part of the `&&`, so we only push one of the two `&`s. + split_token(Token::Type::kAnd, Token::Type::kAnd); + ops.Push({t.source(), core::UnaryOp::kAddressOf}); + } else if (t.Is(Token::Type::kAnd)) { + ops.Push({t.source(), core::UnaryOp::kAddressOf}); + } else if (t.Is(Token::Type::kStar)) { + ops.Push({t.source(), core::UnaryOp::kIndirection}); + } + } + if (ops.IsEmpty()) { + return Failure::kNoMatch; + } + + auto& t = peek(); + auto expr = lhs_expression(); + if (expr.errored) { + return Failure::kErrored; + } + if (!expr.matched) { + return AddError(t, "missing expression"); + } + + const ast::Expression* ret = expr.value; + // Consume the ops in reverse order so we have the correct AST ordering. + for (auto& info : tint::Reverse(ops)) { + ret = create(info.source, info.op, ret); + } + return ret; +} + +// variable_updating_statement +// : lhs_expression ( EQUAL | compound_assignment_operator ) expression +// | lhs_expression MINUS_MINUS +// | lhs_expression PLUS_PLUS +// | UNDERSCORE EQUAL expression +// +// Note, this is a simplification of the recursive grammar statement with the `lhs_expression` +// substituted back into the expression. +Maybe Parser::variable_updating_statement() { + auto& t = peek(); + + // tint:295 - Test for `ident COLON` - this is invalid grammar, and without + // special casing will error as "missing = for assignment", which is less + // helpful than this error message: + if (peek_is(Token::Type::kIdentifier) && peek_is(Token::Type::kColon, 1)) { + return AddError(peek(0).source(), "expected 'var' for variable declaration"); + } + + // Prefix increment/decrement `++a`/`--a` is invalid grammar, and without + // special casing will return unmatched and no error message. + if (peek_is(Token::Type::kPlusPlus) || peek_is(Token::Type::kMinusMinus)) { + return AddError(peek(0).source(), + "prefix increment and decrement operators are not supported"); + } + + Source source; + const ast::Expression* lhs = nullptr; + std::optional compound_op; + if (peek_is(Token::Type::kUnderscore)) { + next(); // Consume the peek. + + if (!expect("assignment", Token::Type::kEqual)) { + return Failure::kErrored; + } + source = last_source(); + + lhs = create(t.source()); + + } else { + auto lhs_result = lhs_expression(); + if (lhs_result.errored) { + return Failure::kErrored; + } + if (!lhs_result.matched) { + return Failure::kNoMatch; + } + + lhs = lhs_result.value; + + // Handle increment and decrement statements. + if (match(Token::Type::kPlusPlus)) { + return create(last_source(), lhs, true); + } + if (match(Token::Type::kMinusMinus)) { + return create(last_source(), lhs, false); + } + + source = peek().source(); + auto compound_op_result = compound_assignment_operator(); + if (compound_op_result.errored) { + return Failure::kErrored; + } + if (compound_op_result.matched) { + compound_op = compound_op_result.value; + } else { + if (!expect("assignment", Token::Type::kEqual)) { + return Failure::kErrored; + } + } + } + + auto rhs = expression(); + if (rhs.errored) { + return Failure::kErrored; + } + if (!rhs.matched) { + return AddError(peek(), "unable to parse right side of assignment"); + } + + if (compound_op) { + return create(source, lhs, rhs.value, *compound_op); + } + return create(source, lhs, rhs.value); +} + +// const_literal +// : INT_LITERAL +// | FLOAT_LITERAL +// | bool_literal +// +// bool_literal +// : TRUE +// | FALSE +Maybe Parser::const_literal() { + auto& t = peek(); + if (match(Token::Type::kIntLiteral)) { + return create(t.source(), t.to_i64(), + ast::IntLiteralExpression::Suffix::kNone); + } + if (match(Token::Type::kIntLiteral_I)) { + return create(t.source(), t.to_i64(), + ast::IntLiteralExpression::Suffix::kI); + } + if (match(Token::Type::kIntLiteral_U)) { + return create(t.source(), t.to_i64(), + ast::IntLiteralExpression::Suffix::kU); + } + if (match(Token::Type::kFloatLiteral)) { + return create(t.source(), t.to_f64(), + ast::FloatLiteralExpression::Suffix::kNone); + } + if (match(Token::Type::kFloatLiteral_F)) { + return create(t.source(), t.to_f64(), + ast::FloatLiteralExpression::Suffix::kF); + } + if (match(Token::Type::kFloatLiteral_H)) { + return create(t.source(), t.to_f64(), + ast::FloatLiteralExpression::Suffix::kH); + } + if (match(Token::Type::kTrue)) { + return create(t.source(), true); + } + if (match(Token::Type::kFalse)) { + return create(t.source(), false); + } + if (handle_error(t)) { + return Failure::kErrored; + } + return Failure::kNoMatch; +} + +Maybe Parser::attribute_list() { + bool errored = false; + AttributeList attrs; + + while (continue_parsing()) { + if (match(Token::Type::kAttr)) { + if (auto attr = expect_attribute(); attr.errored) { + errored = true; + } else { + attrs.Push(attr.value); + } + } else { + break; + } + } + + if (errored) { + return Failure::kErrored; + } + + if (attrs.IsEmpty()) { + return Failure::kNoMatch; + } + + return attrs; +} + +Expect Parser::expect_attribute() { + auto& t = peek(); + auto attr = attribute(); + if (attr.errored) { + return Failure::kErrored; + } + if (attr.matched) { + return attr.value; + } + return AddError(t, "expected attribute"); +} + +// attribute +// : ATTR identifier ( PAREN_LEFT expression ( COMMA expression )? COMMA? PAREN_RIGHT )? +Maybe Parser::attribute() { + // Note, the ATTR is matched by the called `attribute_list` in this case, so it is not matched + // here and this has to be an attribute. + auto& t = peek(); + + if (match(Token::Type::kConst)) { + return AddError(t.source(), "const attribute may not appear in shaders"); + } + if (match(Token::Type::kDiagnostic)) { + auto control = expect_diagnostic_control(); + if (control.errored) { + return Failure::kErrored; + } + return create(t.source(), std::move(control.value)); + } + + auto attr = expect_enum("attribute", core::ParseAttribute, core::kAttributeStrings); + if (attr.errored) { + return Failure::kErrored; + } + + uint32_t min = 1; + uint32_t max = 1; + switch (attr.value) { + case core::Attribute::kCompute: + case core::Attribute::kFragment: + case core::Attribute::kInvariant: + case core::Attribute::kMustUse: + case core::Attribute::kVertex: + min = 0; + max = 0; + break; + case core::Attribute::kInterpolate: + max = 2; + break; + case core::Attribute::kWorkgroupSize: + max = 3; + break; + default: + break; + } + + // builtin_attr : + // '@' 'builtin' '(' builtin_value_name ',' ? ')' + // | '@' 'builtin' '(' builtin_value_name ',' builtin_depth_mode_name ',' ? ')' + if (attr.value == core::Attribute::kBuiltin) { + return expect_paren_block( + "builtin attribute", [&]() -> Expect { + auto name = expect_enum("builtin value name", core::ParseBuiltinValue, + core::kBuiltinValueStrings); + if (name.errored) { + return Failure::kErrored; + } + if (!match(Token::Type::kComma) || peek().Is(Token::Type::kParenRight)) { + return builder_.Builtin(t.source(), name.value); + } + + auto depth_mode_name = + expect_enum("builtin depth mode name", core::ParseBuiltinDepthMode, + core::kBuiltinDepthModeStrings); + if (depth_mode_name.errored) { + return Failure::kErrored; + } + match(Token::Type::kComma); + + return builder_.Builtin(t.source(), name.value, depth_mode_name.value); + }); + } + + // interpolate_attr : + // '@' 'interpolate' '(' interpolate_type_name ',' ? ')' + // | '@' 'interpolate' '(' interpolate_type_name ',' interpolate_sampling_name ',' ? ')' + if (attr.value == core::Attribute::kInterpolate) { + return expect_paren_block( + "interpolate attribute", [&]() -> Expect { + auto type_name = + expect_enum("interpolation type name", core::ParseInterpolationType, + core::kInterpolationTypeStrings); + if (type_name.errored) { + return Failure::kErrored; + } + if (!match(Token::Type::kComma) || peek().Is(Token::Type::kParenRight)) { + return builder_.Interpolate(t.source(), type_name.value); + } + + auto sampling_name = + expect_enum("interpolation sampling name", core::ParseInterpolationSampling, + core::kInterpolationSamplingStrings); + if (sampling_name.errored) { + return Failure::kErrored; + } + match(Token::Type::kComma); + + return builder_.Interpolate(t.source(), type_name.value, sampling_name.value); + }); + } + + Vector args; + + // Handle no parameter items which should have no parens + if (min == 0) { + auto& t2 = peek(); + if (match(Token::Type::kParenLeft)) { + return AddError(t2.source(), t.to_str() + " attribute doesn't take parenthesis"); + } + } else { + auto res = expect_paren_block(t.to_str() + " attribute", [&]() -> Expect { + while (continue_parsing()) { + if (peek().Is(Token::Type::kParenRight)) { + break; + } + + auto expr = expect_expression(t.to_str()); + if (expr.errored) { + return Failure::kErrored; + } + args.Push(expr.value); + + if (!match(Token::Type::kComma)) { + break; + } + } + return true; + }); + if (res.errored) { + return Failure::kErrored; + } + + if (args.IsEmpty() || args.Length() < min) { + return AddError(t.source(), + t.to_str() + " expects" + (min != max ? " at least " : " ") + + std::to_string(min) + " argument" + (min != 1 ? "s" : "")); + } + if (args.Length() > max) { + return AddError(t.source(), t.to_str() + " expects" + (min != max ? " at most " : " ") + + std::to_string(max) + " argument" + + (max != 1 ? "s" : "") + ", got " + + std::to_string(args.Length())); + } + } + + switch (attr.value) { + case core::Attribute::kAlign: + return create(t.source(), args[0]); + case core::Attribute::kBinding: + return create(t.source(), args[0]); + case core::Attribute::kBlendSrc: + return create(t.source(), args[0]); + case core::Attribute::kColor: + return create(t.source(), args[0]); + case core::Attribute::kCompute: + return create(t.source(), ast::PipelineStage::kCompute); + case core::Attribute::kFragment: + return create(t.source(), ast::PipelineStage::kFragment); + case core::Attribute::kGroup: + return create(t.source(), args[0]); + case core::Attribute::kId: + return create(t.source(), args[0]); + case core::Attribute::kInputAttachmentIndex: + return create(t.source(), args[0]); + case core::Attribute::kInvariant: + return create(t.source()); + case core::Attribute::kLocation: + return builder_.Location(t.source(), args[0]); + case core::Attribute::kMustUse: + return create(t.source()); + case core::Attribute::kSize: + return builder_.MemberSize(t.source(), args[0]); + case core::Attribute::kVertex: + return create(t.source(), ast::PipelineStage::kVertex); + case core::Attribute::kWorkgroupSize: + return create(t.source(), args[0], + args.Length() > 1 ? args[1] : nullptr, + args.Length() > 2 ? args[2] : nullptr); + case core::Attribute::kSubgroupSize: + return create(t.source(), args[0]); + default: + return Failure::kNoMatch; + } +} + +Expect Parser::expect_attributes_consumed(VectorRef in) { + if (in.IsEmpty()) { + return kSuccess; + } + AddError(in[0]->source, "unexpected attributes"); + return Failure::kErrored; +} + +Expect Parser::expect_next_not_template_list(const Source& lhs_source) { + Source end; + if (!match(Token::Type::kTemplateArgsLeft, &end)) { + return kSuccess; + } + + // Try to find end of template + for (size_t i = 0; i < 32; i++) { + if (auto& t = peek(i); t.type() == Token::Type::kTemplateArgsRight) { + end = t.source(); + } + } + Source template_source = lhs_source; + template_source.range.end = end.range.end; + AddError(template_source, "parsed as template list"); + + if (auto rhs = expression(); rhs.matched) { + Source lt_source = lhs_source; + lt_source.range.end = rhs->source.range.end; + AddNote(lt_source, + "if this is intended to be a less-than expression then wrap in parentheses"); + } + return Failure::kErrored; +} + +Expect Parser::expect_not_templated_ident_expr(const ast::Expression* expr) { + auto* ident_expr = expr->As(); + if (!ident_expr) { + return kSuccess; + } + auto* ident = ident_expr->identifier->As(); + if (!ident) { + return kSuccess; + } + + AddError(ident->source, "parsed as template list"); + + if (auto rhs = expression(); rhs.matched) { + Source gt_source = ident->arguments.Back()->source; + gt_source.range.end = rhs->source.range.end; + AddNote(gt_source, + "if this is intended to be a greater-than expression then wrap in parentheses"); + } + return Failure::kErrored; +} + +// severity_control_name +// : 'error' +// | 'warning' +// | 'info' +// | 'off' +Expect Parser::expect_severity_control_name() { + return expect_enum("severity control", wgsl::ParseDiagnosticSeverity, + wgsl::kDiagnosticSeverityStrings); +} + +// diagnostic_control +// : PAREN_LEFT severity_control_name COMMA diagnostic_rule_name COMMA ? PAREN_RIGHT +Expect Parser::expect_diagnostic_control() { + return expect_paren_block("diagnostic control", [&]() -> Expect { + auto severity_control = expect_severity_control_name(); + if (severity_control.errored) { + return Failure::kErrored; + } + + if (!expect("diagnostic control", Token::Type::kComma)) { + return Failure::kErrored; + } + + auto rule_name = expect_diagnostic_rule_name(); + if (rule_name.errored) { + return Failure::kErrored; + } + match(Token::Type::kComma); + + return ast::DiagnosticControl(severity_control.value, rule_name.value); + }); +} + +// diagnostic_rule_name : +// | diagnostic_name_token +// | diagnostic_name_token '.' diagnostic_name_token +Expect Parser::expect_diagnostic_rule_name() { + if (peek_is(Token::Type::kPeriod, 1)) { + auto category = expect_ident("", "diagnostic rule category"); + if (category.errored) { + return Failure::kErrored; + } + if (!expect("diagnostic rule", Token::Type::kPeriod)) { + return Failure::kErrored; + } + auto name = expect_ident("", "diagnostic rule name"); + if (name.errored) { + return Failure::kErrored; + } + return builder_.DiagnosticRuleName(category.value, name.value); + } + auto name = expect_ident("", "diagnostic rule name"); + if (name.errored) { + return Failure::kErrored; + } + return builder_.DiagnosticRuleName(name.value); +} + +bool Parser::match(Token::Type tok, Source* source /*= nullptr*/) { + auto& t = peek(); + + if (source != nullptr) { + *source = t.source(); + } + + if (t.Is(tok)) { + next(); + return true; + } + return false; +} + +bool Parser::expect(std::string_view use, Token::Type tok) { + auto& t = peek(); + if (t.Is(tok)) { + next(); + synchronized_ = true; + return true; + } + + // Special case to split `>>` and `>=` tokens if we are looking for a `>`. + if (tok == Token::Type::kGreaterThan && + (t.Is(Token::Type::kShiftRight) || t.Is(Token::Type::kGreaterThanEqual))) { + next(); + + // Push the second character to the token queue. + if (t.Is(Token::Type::kShiftRight)) { + split_token(Token::Type::kGreaterThan, Token::Type::kGreaterThan); + } else if (t.Is(Token::Type::kGreaterThanEqual)) { + split_token(Token::Type::kGreaterThan, Token::Type::kEqual); + } + + synchronized_ = true; + return true; + } + + // Error cases + synchronized_ = false; + if (handle_error(t)) { + return false; + } + + StringStream err; + if (tok == Token::Type::kTemplateArgsLeft && t.type() == Token::Type::kLessThan) { + err << "missing closing '>'"; + } else { + err << "expected '" << Token::TypeToName(tok) << "'"; + } + if (!use.empty()) { + err << " for " << use; + } + AddError(t, err.str()); + return false; +} + +Expect Parser::expect_sint(std::string_view use, Source* source /* = nullptr */) { + auto& t = peek(); + if (source) { + *source = t.source(); + } + if (!t.Is(Token::Type::kIntLiteral) && !t.Is(Token::Type::kIntLiteral_I)) { + return AddError(t.source(), "expected signed integer literal", use); + } + + int64_t val = t.to_i64(); + if ((val > std::numeric_limits::max()) || + (val < std::numeric_limits::min())) { + // TODO(crbug.com/tint/1504): Test this when abstract int is implemented + return AddError(t.source(), "value overflows i32", use); + } + + next(); + return static_cast(t.to_i64()); +} + +Expect Parser::expect_positive_sint(std::string_view use) { + Source source; + auto sint = expect_sint(use, &source); + if (sint.errored) { + return Failure::kErrored; + } + + if (sint.value < 0) { + return AddError(source, std::string(use) + " must be positive"); + } + + return static_cast(sint.value); +} + +Expect Parser::expect_nonzero_positive_sint(std::string_view use) { + Source source; + auto sint = expect_sint(use, &source); + if (sint.errored) { + return Failure::kErrored; + } + + if (sint.value <= 0) { + return AddError(source, std::string(use) + " must be greater than 0"); + } + + return static_cast(sint.value); +} + +Expect Parser::expect_ident(std::string_view use, + std::string_view kind /* = "identifier" */) { + auto& t = peek(); + if (t.IsIdentifier()) { + synchronized_ = true; + next(); + + if (IsReserved(t.to_str_view())) { + return AddError(t.source(), "'" + t.to_str() + "' is a reserved keyword"); + } + + return builder_.Ident(t.source(), t.to_str()); + } + if (handle_error(t)) { + return Failure::kErrored; + } + synchronized_ = false; + return AddError(t.source(), "expected " + std::string(kind), use); +} + +template +T Parser::expect_block(Token::Type start, Token::Type end, std::string_view use, F&& body) { + if (!expect(use, start)) { + return Failure::kErrored; + } + + return sync(end, [&]() -> T { + auto res = body(); + + if (res.errored) { + return Failure::kErrored; + } + + if (!expect(use, end)) { + return Failure::kErrored; + } + + return res; + }); +} + +template +T Parser::expect_paren_block(std::string_view use, F&& body) { + return expect_block(Token::Type::kParenLeft, Token::Type::kParenRight, use, + std::forward(body)); +} + +template +T Parser::expect_brace_block(std::string_view use, F&& body) { + return expect_block(Token::Type::kBraceLeft, Token::Type::kBraceRight, use, + std::forward(body)); +} + +template +T Parser::expect_lt_gt_block(std::string_view use, F&& body) { + return expect_block(Token::Type::kLessThan, Token::Type::kGreaterThan, use, + std::forward(body)); +} + +template +T Parser::expect_template_arg_block(std::string_view use, F&& body) { + return expect_block(Token::Type::kTemplateArgsLeft, Token::Type::kTemplateArgsRight, use, + std::forward(body)); +} + +template +T Parser::sync(Token::Type tok, F&& body) { + if (parse_depth_ >= kMaxParseDepth) { + // We've hit a maximum parser recursive depth. + // We can't call into body() as we might stack overflow. + // Instead, report an error... + AddError(peek(), "maximum parser recursive depth reached"); + // ...and try to resynchronize. If we cannot resynchronize to `tok` then + // synchronized_ is set to false, and the parser knows that forward progress + // is not being made. + sync_to(tok, /* consume: */ true); + return Failure::kErrored; + } + + sync_tokens_.push_back(tok); + + ++parse_depth_; + auto result = body(); + --parse_depth_; + + TINT_ASSERT(sync_tokens_.back() == tok) << "sync_tokens is out of sync"; + + sync_tokens_.pop_back(); + + if (result.errored) { + sync_to(tok, /* consume: */ true); + } + + return result; +} + +bool Parser::sync_to(Token::Type tok, bool consume) { + // Clear the synchronized state - gets set to true again on success. + synchronized_ = false; + + BlockCounters counters; + + for (size_t i = 0; i < kMaxResynchronizeLookahead; i++) { + auto& t = peek(i); + if (counters.consume(t) > 0) { + continue; // Nested block + } + if (!t.Is(tok) && !is_sync_token(t)) { + continue; // Not a synchronization point + } + + // Synchronization point found. + + // Skip any tokens we don't understand, bringing us to just before the + // resync point. + while (i-- > 0) { + next(); + } + + // Is this synchronization token |tok|? + if (t.Is(tok)) { + if (consume) { + next(); + } + synchronized_ = true; + return true; + } + break; + } + + return false; +} + +bool Parser::is_sync_token(const Token& t) const { + for (auto r : sync_tokens_) { + if (t.Is(r)) { + return true; + } + } + return false; +} + +bool Parser::handle_error(const Token& t) { + // The token might itself be an error. + if (t.IsError()) { + synchronized_ = false; + AddError(t.source(), t.to_str()); + return true; + } + return false; +} + +template +T Parser::without_diag(F&& body) { + silence_diags_++; + auto result = body(); + silence_diags_--; + return result; +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.h new file mode 100644 index 000000000..ad2497798 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/parser.h @@ -0,0 +1,927 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_PARSER_PARSER_H_ +#define SRC_TINT_LANG_WGSL_READER_PARSER_PARSER_H_ + +#include +#include +#include +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/reader/parser/detail.h" +#include "src/tint/lang/wgsl/reader/parser/token.h" +#include "src/tint/lang/wgsl/resolver/resolve.h" +#include "src/tint/utils/diagnostic/formatter.h" +#include "src/tint/utils/text/styled_text.h" + +namespace tint::ast { +class BreakStatement; +class CallStatement; +class ContinueStatement; +class IfStatement; +class LoopStatement; +class ReturnStatement; +class SwitchStatement; +class VariableDeclStatement; +} // namespace tint::ast + +namespace tint::wgsl::reader { + +class Lexer; + +/// Struct holding information for a for loop +struct ForHeader { + /// Constructor + /// @param init the initializer statement + /// @param cond the condition statement + /// @param cont the continuing statement + ForHeader(const ast::Statement* init, const ast::Expression* cond, const ast::Statement* cont); + + ~ForHeader(); + + /// The for loop initializer + const ast::Statement* initializer = nullptr; + /// The for loop condition + const ast::Expression* condition = nullptr; + /// The for loop continuing statement + const ast::Statement* continuing = nullptr; +}; + +/// Parser for WGSL source data +class Parser { + /// Failure holds enumerator values used for the constructing an Expect and + /// Match in an errored state. + struct Failure { + enum Errored { kErrored }; + enum NoMatch { kNoMatch }; + }; + + public: + /// Pre-determined small vector sizes for AST pointers + //! @cond Doxygen_Suppress + using AttributeList = Vector; + using CaseSelectorList = Vector; + using CaseStatementList = Vector; + using ExpressionList = Vector; + using ParameterList = Vector; + using StatementList = Vector; + using StructMemberList = Vector; + //! @endcond + + /// Empty structure used by functions that do not return a value, but need to signal success / + /// error with Expect or Maybe. + struct Void {}; + + /// Expect is the return type of the parser methods that are expected to + /// return a parsed value of type T, unless there was an parse error. + /// In the case of a parse error the called method will have called + /// AddError() and #errored will be set to true. + template + struct Expect { + /// An alias to the templated type T. + using type = T; + + /// Don't allow an Expect to take a nullptr. + inline Expect(std::nullptr_t) = delete; // NOLINT + + /// Constructor for a successful parse. + /// @param val the result value of the parse + template + inline Expect(U&& val) // NOLINT + : value(std::forward(val)) {} + + /// Constructor for parse error. + inline Expect(Failure::Errored) : errored(true) {} // NOLINT + + /// Copy constructor + inline Expect(const Expect&) = default; + /// Move constructor + inline Expect(Expect&&) = default; + /// Assignment operator + /// @return this Expect + inline Expect& operator=(const Expect&) = default; + /// Assignment move operator + /// @return this Expect + inline Expect& operator=(Expect&&) = default; + + /// @return a pointer to the returned value. If T is a pointer or + /// 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::type operator->() { + TINT_ASSERT(!errored); + return detail::OperatorArrow::ptr(value); + } + + /// The expected value of a successful parse. + /// Zero-initialized when there was a parse error. + T value{}; + /// True if there was a error parsing. + bool errored = false; + }; + + /// Maybe is the return type of the parser methods that attempts to match a + /// grammar and return a parsed value of type T, or may parse part of the + /// grammar and then hit a parse error. + /// In the case of a successful grammar match, the Maybe will have #matched + /// set to true. + /// In the case of a parse error the called method will have called + /// AddError() and the Maybe will have #errored set to true. + template + struct Maybe { + inline Maybe(std::nullptr_t) = delete; // NOLINT + + /// Constructor for a successful parse. + /// @param val the result value of the parse + template + inline Maybe(U&& val) // NOLINT + : value(std::forward(val)), matched(true) {} + + /// Constructor for parse error state. + inline Maybe(Failure::Errored) : errored(true) {} // NOLINT + + /// Constructor for the no-match state. + inline Maybe(Failure::NoMatch) {} // NOLINT + + /// Constructor from an Expect. + /// @param e the Expect to copy this Maybe from + template + inline Maybe(const Expect& e) // NOLINT + : value(e.value), errored(e.errored), matched(!e.errored) {} + + /// Move from an Expect. + /// @param e the Expect to move this Maybe from + template + inline Maybe(Expect&& e) // NOLINT + : value(std::move(e.value)), errored(e.errored), matched(!e.errored) {} + + /// Copy constructor + inline Maybe(const Maybe&) = default; + /// Move constructor + inline Maybe(Maybe&&) = default; + /// Assignment operator + /// @return this Maybe + inline Maybe& operator=(const Maybe&) = default; + /// Assignment move operator + /// @return this Maybe + inline Maybe& operator=(Maybe&&) = default; + + /// @return a pointer to the returned value. If T is a pointer or + /// 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::type operator->() { + TINT_ASSERT(!errored); + return detail::OperatorArrow::ptr(value); + } + + /// The value of a successful parse. + /// Zero-initialized when there was a parse error. + T value{}; + /// True if there was a error parsing. + bool errored = false; + /// True if there was a error parsing. + bool matched = false; + }; + + /// TypedIdentifier holds a parsed identifier and type. Returned by + /// variable_ident_decl(). + struct TypedIdentifier { + /// Constructor + TypedIdentifier(); + /// Copy constructor + /// @param other the FunctionHeader to copy + TypedIdentifier(const TypedIdentifier& other); + /// Constructor + /// @param type_in parsed type + /// @param name_in parsed identifier + TypedIdentifier(ast::Type type_in, const ast::Identifier* name_in); + /// Destructor + ~TypedIdentifier(); + + /// Parsed type. type.expr be nullptr for inferred types. + ast::Type type; + /// Parsed identifier. + const ast::Identifier* name = nullptr; + }; + + /// FunctionHeader contains the parsed information for a function header. + struct FunctionHeader { + /// Constructor + FunctionHeader(); + /// Copy constructor + /// @param other the FunctionHeader to copy + FunctionHeader(const FunctionHeader& other); + /// Constructor + /// @param src parsed header source + /// @param n function name + /// @param p function parameters + /// @param ret_ty function return type + /// @param ret_attrs return type attributes + FunctionHeader(Source src, + const ast::Identifier* n, + VectorRef p, + ast::Type ret_ty, + VectorRef ret_attrs); + /// Destructor + ~FunctionHeader(); + /// Assignment operator + /// @param other the FunctionHeader to copy + /// @returns this FunctionHeader + FunctionHeader& operator=(const FunctionHeader& other); + + /// Parsed header source + Source source; + /// Function name + const ast::Identifier* name; + /// Function parameters + Vector params; + /// Function return type + ast::Type return_type; + /// Function return type attributes + AttributeList return_type_attributes; + }; + + /// VarDeclInfo contains the parsed information for variable declaration. + struct VarDeclInfo { + /// Variable declaration source + Source source; + /// Variable name + const ast::Identifier* name = nullptr; + /// Variable address space + const ast::Expression* address_space = nullptr; + /// Variable access control + const ast::Expression* access = nullptr; + /// Variable type + ast::Type type; + }; + + /// VariableQualifier contains the parsed information for a variable qualifier + struct VariableQualifier { + /// The variable's address space + const ast::Expression* address_space = nullptr; + /// The variable's access control + const ast::Expression* access = nullptr; + }; + + /// MatrixDimensions contains the column and row information for a matrix + struct MatrixDimensions { + /// The number of columns + uint32_t columns = 0; + /// The number of rows + uint32_t rows = 0; + }; + + /// Creates a new parser using the given file + /// @param file the input source file to parse + explicit Parser(Source::File const* file); + ~Parser(); + + /// Reads tokens from the source file. This will be called automatically + /// by |parse|. + void InitializeLex(); + + /// Run the parser + /// @returns true if the parse was successful, false otherwise. + bool Parse(); + + /// set_max_diagnostics sets the maximum number of reported errors before + /// aborting parsing. + /// @param limit the new maximum number of errors + void set_max_errors(size_t limit) { max_errors_ = limit; } + + /// @return the number of maximum number of reported errors before aborting + /// parsing. + size_t get_max_errors() const { return max_errors_; } + + /// @returns true if an error was encountered. + bool has_error() const { return builder_.Diagnostics().ContainsErrors(); } + + /// @returns the parser error string + std::string error() const { + diag::Formatter formatter{{false, false, false, false}}; + return formatter.Format(builder_.Diagnostics()).Plain(); + } + + /// @returns the Program. The program builder in the parser will be reset + /// after this. + Program program() { return resolver::Resolve(builder_); } + + /// @returns the program builder. + ProgramBuilder& builder() { return builder_; } + + /// @returns the next token + const Token& next(); + /// Peeks ahead and returns the token at `idx` ahead of the current position + /// @param idx the index of the token to return + /// @returns the token `idx` positions ahead without advancing + const Token& peek(size_t idx = 0); + /// Peeks ahead and returns true if the token at `idx` ahead of the current + /// position is |tok| + /// @param idx the index of the token to return + /// @param tok the token to look for + /// @returns true if the token `idx` positions ahead is |tok| + bool peek_is(Token::Type tok, size_t idx = 0); + /// @returns the last source location that was returned by `next()` + Source last_source() const; + /// Appends an error at `t` with the message `msg` + /// @param t the token to associate the error with + /// @param msg the error message + /// @return `Failure::Errored::kError` so that you can combine an AddError() + /// call and return on the same line. + Failure::Errored AddError(const Token& t, std::string_view msg); + /// Appends an error raised when parsing `use` at `t` with the message + /// `msg` + /// @param source the source to associate the error with + /// @param msg the error message + /// @param use a description of what was being parsed when the error was + /// raised. + /// @return `Failure::Errored::kError` so that you can combine an AddError() + /// call and return on the same line. + Failure::Errored AddError(const Source& source, std::string_view msg, std::string_view use); + /// Appends an error at `source` with the message `msg` + /// @param source the source to associate the error with + /// @param msg the error message + /// @return `Failure::Errored::kError` so that you can combine an AddError() + /// call and return on the same line. + Failure::Errored AddError(const Source& source, std::string_view msg); + /// Appends an error at `source` with the message `msg` + /// @param source the source to associate the error with + /// @param msg the error message + /// @return `Failure::Errored::kError` so that you can combine an AddError() + /// call and return on the same line. + Failure::Errored AddError(const Source& source, StyledText&& msg); + /// Appends a note at `source` with the message `msg` + /// @param source the source to associate the error with + /// @param msg the note message + void AddNote(const Source& source, std::string_view msg); + /// Appends a deprecated-language-feature warning at `source` with the message + /// `msg` + /// @param source the source to associate the error with + /// @param msg the warning message + void deprecated(const Source& source, std::string_view msg); + /// Parses the `translation_unit` grammar element + void translation_unit(); + /// Parses the `global_directive` grammar element, erroring on parse failure. + /// @param has_parsed_decl flag indicating if the parser has consumed a global declaration. + /// @return true on parse success, otherwise an error or no-match. + Maybe global_directive(bool has_parsed_decl); + /// Parses the `diagnostic_directive` grammar element, erroring on parse failure. + /// @return true on parse success, otherwise an error or no-match. + Maybe diagnostic_directive(); + /// Parses the `enable_directive` grammar element, erroring on parse failure. + /// @return true on parse success, otherwise an error or no-match. + Maybe enable_directive(); + /// Parses the `requires_directive` grammar element, erroring on parse failure. + /// @return true on parse success, otherwise an error or no-match. + Maybe requires_directive(); + /// Parses the `global_decl` grammar element, erroring on parse failure. + /// @return true on parse success, otherwise an error or no-match. + Maybe global_decl(); + /// Parses a `global_variable_decl` grammar element with the initial + /// `variable_attribute_list*` provided as `attrs` + /// @returns the variable parsed or nullptr + /// @param attrs the list of attributes for the variable declaration. If attributes are consumed + /// by the declaration, then this vector is cleared before returning. + Maybe global_variable_decl(AttributeList& attrs); + /// Parses a `global_constant_decl` grammar element with the initial + /// `variable_attribute_list*` provided as `attrs` + /// @returns the const object or nullptr + /// @param attrs the list of attributes for the constant declaration. If attributes are consumed + /// by the declaration, then this vector is cleared before returning. + Maybe global_constant_decl(AttributeList& attrs); + /// Parses a `variable_decl` grammar element + /// @returns the parsed variable declaration info + Maybe variable_decl(); + /// Helper for parsing ident with an optional type declaration. Should not be called directly, + /// use the specific version below. + /// @param use a description of what was being parsed if an error was raised. + /// @param allow_inferred allow the identifier to be parsed without a type + /// @returns the parsed identifier, and possibly type, or empty otherwise + Expect expect_ident_with_optional_type_specifier(std::string_view use, + bool allow_inferred); + /// Parses a `ident` or a `variable_ident_decl` grammar element, erroring on parse failure. + /// @param use a description of what was being parsed if an error was raised. + /// @returns the identifier or empty otherwise. + Expect expect_optionally_typed_ident(std::string_view use); + /// Parses a `variable_ident_decl` grammar element, erroring on parse failure. + /// @param use a description of what was being parsed if an error was raised. + /// @returns the identifier and type parsed or empty otherwise + Expect expect_ident_with_type_specifier(std::string_view use); + /// Parses a `variable_qualifier` grammar element + /// @returns the variable qualifier information + Maybe variable_qualifier(); + /// Parses a `type_alias_decl` grammar element + /// @returns the type alias or nullptr on error + Maybe type_alias_decl(); + /// Parses a `type_specifier` grammar element + /// @returns the parsed Type or nullptr if none matched. + Maybe type_specifier(); + /// Parses a `struct_decl` grammar element. + /// @returns the struct type or nullptr on error + Maybe struct_decl(); + /// Parses a `struct_body_decl` grammar element, erroring on parse failure. + /// @returns the struct members + Expect expect_struct_body_decl(); + /// Parses a `struct_member` grammar element, erroring on parse failure. + /// @returns the struct member or nullptr + Expect expect_struct_member(); + /// Parses a `function_decl` grammar element with the initial + /// `function_attribute_decl*` provided as `attrs`. + /// @param attrs the list of attributes for the function declaration. If attributes are consumed + /// by the declaration, then this vector is cleared before returning. + /// @returns the parsed function, nullptr otherwise + Maybe function_decl(AttributeList& attrs); + /// Parses a `const_assert_statement` grammar element + /// @returns returns the const assert, if it matched. + Maybe const_assert_statement(); + /// Parses a `function_header` grammar element + /// @returns the parsed function header + Maybe function_header(); + /// Parses a `param_list` grammar element, erroring on parse failure. + /// @returns the parsed variables + Expect expect_param_list(); + /// Parses a `param` grammar element, erroring on parse failure. + /// @returns the parsed variable + Expect expect_param(); + /// Parses a `pipeline_stage` grammar element, erroring if the next token does + /// not match a stage name. + /// @returns the pipeline stage. + Expect expect_pipeline_stage(); + /// Parses a `compound_statement` grammar element, erroring on parse failure. + /// @param use a description of what was being parsed if an error was raised + /// @returns the parsed statements + Expect expect_compound_statement(std::string_view use); + /// Parses a `compound_statement` grammar element, with the attribute list provided as `attrs`. + /// @param attrs the list of attributes for the statement + /// @param use a description of what was being parsed if an error was raised + /// @returns the parsed statements + Expect expect_compound_statement(AttributeList& attrs, + std::string_view use); + /// Parses a `paren_expression` grammar element, erroring on parse failure. + /// @returns the parsed element or nullptr + Expect expect_paren_expression(); + /// Parses a `statements` grammar element + /// @returns the statements parsed + Expect expect_statements(); + /// Parses a `statement` grammar element + /// @returns the parsed statement or nullptr + Maybe statement(); + /// Parses a `break_statement` grammar element + /// @returns the parsed statement or nullptr + Maybe break_statement(); + /// Parses a `return_statement` grammar element + /// @returns the parsed statement or nullptr + Maybe return_statement(); + /// Parses a `continue_statement` grammar element + /// @returns the parsed statement or nullptr + Maybe continue_statement(); + /// Parses a `variable_statement` grammar element + /// @returns the parsed variable or nullptr + Maybe variable_statement(); + /// Parses a `if_statement` grammar element, with the attribute list provided as `attrs`. + /// @param attrs the list of attributes for the statement + /// @returns the parsed statement or nullptr + Maybe if_statement(AttributeList& attrs); + /// Parses a `switch_statement` grammar element + /// @param attrs the list of attributes for the statement + /// @returns the parsed statement or nullptr + Maybe switch_statement(AttributeList& attrs); + /// Parses a `switch_body` grammar element + /// @returns the parsed statement or nullptr + Maybe switch_body(); + /// Parses a `case_selectors` grammar element + /// @returns the list of literals + Expect expect_case_selectors(); + /// Parses a `case_selector` grammar element + /// @returns the selector + Maybe case_selector(); + /// Parses a `func_call_statement` grammar element + /// @returns the parsed function call or nullptr + Maybe func_call_statement(); + /// Parses a `loop_statement` grammar element, with the attribute list provided as `attrs`. + /// @param attrs the list of attributes for the statement + /// @returns the parsed loop or nullptr + Maybe loop_statement(AttributeList& attrs); + /// Parses a `for_header` grammar element, erroring on parse failure. + /// @returns the parsed for header or nullptr + Expect> expect_for_header(); + /// Parses a `for_statement` grammar element, with the attribute list provided as `attrs`. + /// @param attrs the list of attributes for the statement + /// @returns the parsed for loop or nullptr + Maybe for_statement(AttributeList& attrs); + /// Parses a `while_statement` grammar element, with the attribute list provided as `attrs`. + /// @param attrs the list of attributes for the statement + /// @returns the parsed while loop or nullptr + Maybe while_statement(AttributeList& attrs); + /// Parses a `break_if_statement` grammar element + /// @returns the parsed statement or nullptr + Maybe break_if_statement(); + /// Parses a `continuing_compound_statement` grammar element + /// @returns the parsed statements + Maybe continuing_compound_statement(); + /// Parses a `continuing_statement` grammar element + /// @returns the parsed statements + Maybe continuing_statement(); + /// Parses a `const_literal` grammar element + /// @returns the const literal parsed or nullptr if none found + Maybe const_literal(); + /// Parses a `primary_expression` grammar element + /// @returns the parsed expression or nullptr + Maybe primary_expression(); + /// Parses a `argument_expression_list` grammar element, erroring on parse + /// failure. + /// @param use a description of what was being parsed if an error was raised + /// @returns the list of arguments + Expect expect_argument_expression_list(std::string_view use); + /// Parses the recursive portion of the component_or_swizzle_specifier + /// @param prefix the left side of the expression + /// @returns the parsed expression or nullptr + Maybe component_or_swizzle_specifier(const ast::Expression* prefix); + /// Parses a `singular_expression` grammar elment + /// @returns the parsed expression or nullptr + Maybe singular_expression(); + /// Parses a `unary_expression` grammar element + /// @returns the parsed expression or nullptr + Maybe unary_expression(); + /// Parses the `expression` grammar rule + /// @returns the parsed expression or nullptr + Maybe expression(); + /// Parses the `expression` grammar rule + /// @param use the use of the expression + /// @returns the parsed expression or error + Expect expect_expression(std::string_view use); + /// Parses a comma separated expression list + /// @param use the use of the expression list + /// @param terminator the terminating token for the list + /// @returns the parsed expression list or error + Maybe expression_list(std::string_view use, Token::Type terminator); + /// Parses a comma separated expression list, with at least one expression + /// @param use the use of the expression list + /// @param terminator the terminating token for the list + /// @returns the parsed expression list or error + Expect expect_expression_list(std::string_view use, + Token::Type terminator); + /// Parses the `bitwise_expression.post.unary_expression` grammar element + /// @param lhs the left side of the expression + /// @param lhs_source the source span for the left side of the expression + /// @returns the parsed expression or nullptr + Maybe bitwise_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source); + /// Parse the `multiplicative_operator` grammar element + /// @returns the parsed operator if successful + Maybe multiplicative_operator(); + /// Parses multiplicative elements + /// @param lhs the left side of the expression + /// @param lhs_source the source span for the left side of the expression + /// @returns the parsed expression or `lhs` if no match + Expect expect_multiplicative_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source); + /// Parses additive elements + /// @param lhs the left side of the expression + /// @param lhs_source the source span for the left side of the expression + /// @returns the parsed expression or `lhs` if no match + Expect expect_additive_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source); + /// Parses math elements + /// @param lhs the left side of the expression + /// @param lhs_source the source span for the left side of the expression + /// @returns the parsed expression or `lhs` if no match + Expect expect_math_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source); + /// Parses a `unary_expression shift.post.unary_expression` + /// @returns the parsed expression or nullptr + Maybe shift_expression(); + /// Parses a `shift_expression.post.unary_expression` grammar element + /// @param lhs the left side of the expression + /// @param lhs_source the source span for the left side of the expression + /// @returns the parsed expression or `lhs` if no match + Expect expect_shift_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source); + /// Parses a `unary_expression relational_expression.post.unary_expression` + /// @returns the parsed expression or nullptr + Maybe relational_expression(); + /// Parses a `relational_expression.post.unary_expression` grammar element + /// @param lhs the left side of the expression + /// @param lhs_source the source span for the left side of the expression + /// @returns the parsed expression or `lhs` if no match + Expect expect_relational_expression_post_unary_expression( + const ast::Expression* lhs, + const Source& lhs_source); + /// Parse the `additive_operator` grammar element + /// @returns the parsed operator if successful + Maybe additive_operator(); + /// Parses a `compound_assignment_operator` grammar element + /// @returns the parsed compound assignment operator + Maybe compound_assignment_operator(); + /// Parses a `core_lhs_expression` grammar element + /// @returns the parsed expression or a non-kMatched failure + Maybe core_lhs_expression(); + /// Parses a `lhs_expression` grammar element + /// @returns the parsed expression or a non-kMatched failure + Maybe lhs_expression(); + /// Parses a `variable_updating_statement` grammar element + /// @returns the parsed assignment or nullptr + Maybe variable_updating_statement(); + /// Parses one or more attribute lists. + /// @return the parsed attribute list, or an empty list on error. + Maybe attribute_list(); + /// Parses a single attribute of the following types: + /// * `struct_attribute` + /// * `struct_member_attribute` + /// * `array_attribute` + /// * `variable_attribute` + /// * `global_const_attribute` + /// * `function_attribute` + /// @return the parsed attribute, or nullptr. + Maybe attribute(); + /// Parses a single attribute, reporting an error if the next token does not + /// represent a attribute. + /// @see #attribute for the full list of attributes this method parses. + /// @return the parsed attribute. + Expect expect_attribute(); + /// Parses a severity_control_name grammar element. + /// @return the parsed severity control name. + Expect expect_severity_control_name(); + /// Parses a diagnostic_control grammar element. + /// @return the parsed diagnostic control. + Expect expect_diagnostic_control(); + /// Parses a diagnostic_rule_name grammar element. + /// @return the parsed diagnostic rule name. + Expect expect_diagnostic_rule_name(); + + /// Splits a peekable token into to parts filling in the peekable fields. + /// @param lhs the token to set in the current position + /// @param rhs the token to set in the placeholder + void split_token(Token::Type lhs, Token::Type rhs); + + private: + /// ReturnType resolves to the return type for the function or lambda F. + template + using ReturnType = typename std::invoke_result::type; + + /// ResultType resolves to `T` for a `RESULT` of type Expect. + template + using ResultType = typename RESULT::type; + + /// @returns true and consumes the next token if it equals `tok` + /// @param source if not nullptr, the next token's source is written to this + /// pointer, regardless of success or error + bool match(Token::Type tok, Source* source = nullptr); + /// Errors if the next token is not equal to `tok` + /// Consumes the next token on match. + /// expect() also updates #synchronized_, setting it to `true` if the next + /// token is equal to `tok`, otherwise `false`. + /// @param use a description of what was being parsed if an error was raised. + /// @param tok the token to test against + /// @returns true if the next token equals `tok` + bool expect(std::string_view use, Token::Type tok); + /// Parses a signed integer from the next token in the stream, erroring if the + /// next token is not a signed integer. + /// Consumes the next token on match. + /// @param use a description of what was being parsed if an error was raised + /// @returns the parsed integer. + /// @param source if not nullptr, the next token's source is written to this + /// pointer, regardless of success or error + Expect expect_sint(std::string_view use, Source* source = nullptr); + /// Parses a signed integer from the next token in the stream, erroring if + /// the next token is not a signed integer or is negative. + /// Consumes the next token if it is a signed integer (not necessarily + /// negative). + /// @param use a description of what was being parsed if an error was raised + /// @returns the parsed integer. + Expect expect_positive_sint(std::string_view use); + /// Parses a non-zero signed integer from the next token in the stream, + /// erroring if the next token is not a signed integer or is less than 1. + /// Consumes the next token if it is a signed integer (not necessarily + /// >= 1). + /// @param use a description of what was being parsed if an error was raised + /// @returns the parsed integer. + Expect expect_nonzero_positive_sint(std::string_view use); + /// Errors if the next token is not an identifier. + /// Consumes the next token on match. + /// @param use a description of what was being parsed if an error was raised + /// @param kind a string describing the kind of identifier. + /// Examples: "identifier", "diagnostic name" + /// @returns the parsed identifier. + Expect expect_ident(std::string_view use, + std::string_view kind = "identifier"); + /// Parses a lexical block starting with the token `start` and ending with + /// the token `end`. `body` is called to parse the lexical block body + /// between the `start` and `end` tokens. If the `start` or `end` tokens + /// are not matched then an error is generated and a zero-initialized `T` is + /// returned. If `body` raises an error while parsing then a zero-initialized + /// `T` is returned. + /// @param start the token that begins the lexical block + /// @param end the token that ends the lexical block + /// @param use a description of what was being parsed if an error was raised + /// @param body a function or lambda that is called to parse the lexical block + /// body, with the signature: `Expect()` or `Maybe()`. + /// @return the value returned by `body` if no errors are raised, otherwise + /// an Expect with error state. + template > + T expect_block(Token::Type start, Token::Type end, std::string_view use, F&& body); + /// A convenience function that calls expect_block() passing + /// `Token::Type::kParenLeft` and `Token::Type::kParenRight` for the `start` + /// and `end` arguments, respectively. + /// @param use a description of what was being parsed if an error was raised + /// @param body a function or lambda that is called to parse the lexical block + /// body, with the signature: `Expect()` or `Maybe()`. + /// @return the value returned by `body` if no errors are raised, otherwise + /// an Expect with error state. + template > + T expect_paren_block(std::string_view use, F&& body); + /// A convenience function that calls `expect_block` passing + /// `Token::Type::kBraceLeft` and `Token::Type::kBraceRight` for the `start` + /// and `end` arguments, respectively. + /// @param use a description of what was being parsed if an error was raised + /// @param body a function or lambda that is called to parse the lexical block + /// body, with the signature: `Expect()` or `Maybe()`. + /// @return the value returned by `body` if no errors are raised, otherwise + /// an Expect with error state. + template > + T expect_brace_block(std::string_view use, F&& body); + /// A convenience function that calls `expect_block` passing + /// `Token::Type::kLessThan` and `Token::Type::kGreaterThan` for the `start` + /// and `end` arguments, respectively. + /// @param use a description of what was being parsed if an error was raised + /// @param body a function or lambda that is called to parse the lexical block + /// body, with the signature: `Expect()` or `Maybe()`. + /// @return the value returned by `body` if no errors are raised, otherwise + /// an Expect with error state. + template > + T expect_lt_gt_block(std::string_view use, F&& body); + /// A convenience function that calls `expect_block` passing + /// `Token::Type::kTemplateArgsLeft` and `Token::Type::kTemplateArgsRight` for the `start` and + /// `end` arguments, respectively. + /// @param use a description of what was being parsed if an error was raised + /// @param body a function or lambda that is called to parse the lexical block body, with the + /// signature: `Expect()` or `Maybe()`. + /// @return the value returned by `body` if no errors are raised, otherwise an Expect with error + /// state. + template > + T expect_template_arg_block(std::string_view use, F&& body); + + /// sync() calls the function `func`, and attempts to resynchronize the + /// parser to the next found resynchronization token if `func` fails. If the + /// next found resynchronization token is `tok`, then sync will also consume + /// `tok`. + /// + /// sync() will transiently add `tok` to the parser's stack of + /// synchronization tokens for the duration of the call to `func`. Once @p + /// func returns, + /// `tok` is removed from the stack of resynchronization tokens. sync calls + /// may be nested, and so the number of resynchronization tokens is equal to + /// the number of sync() calls in the current stack frame. + /// + /// sync() updates #synchronized_, setting it to `true` if the next + /// resynchronization token found was `tok`, otherwise `false`. + /// + /// @param tok the token to attempt to synchronize the parser to if `func` + /// fails. + /// @param func a function or lambda with the signature: `Expect()` or + /// `Maybe()`. + /// @return the value returned by `func` + template > + T sync(Token::Type tok, F&& func); + /// sync_to() attempts to resynchronize the parser to the next found + /// resynchronization token or `tok` (whichever comes first). + /// + /// Synchronization tokens are transiently defined by calls to sync(). + /// + /// sync_to() updates #synchronized_, setting it to `true` if a + /// resynchronization token was found and it was `tok`, otherwise `false`. + /// + /// @param tok the token to attempt to synchronize the parser to. + /// @param consume if true and the next found resynchronization token is + /// `tok` then sync_to() will also consume `tok`. + /// @return the state of #synchronized_. + /// @see sync(). + bool sync_to(Token::Type tok, bool consume); + /// @return true if `t` is in the stack of resynchronization tokens. + /// @see sync(). + bool is_sync_token(const Token& t) const; + + /// If `t` is an error token, then `synchronized_` is set to false and the + /// token's error is appended to the builder's diagnostics. If `t` is not an + /// error token, then this function does nothing and false is returned. + /// @returns true if `t` is an error, otherwise false. + bool handle_error(const Token& t); + + /// @returns true if #synchronized_ is true and the number of reported errors + /// is less than #max_errors_. + bool continue_parsing() { + return synchronized_ && builder_.Diagnostics().NumErrors() < max_errors_; + } + + /// without_diag() calls the function `func` muting any diagnostics found while executing the + /// function. This can be used to silence spew when attempting to resynchronize the parser. + /// @param func a function or lambda with the signature: `Expect()` or + /// `Maybe()`. + /// @return the value returned by `func` + template > + T without_diag(F&& func); + + /// Reports an error if the attribute list `list` is not empty. + /// Used to ensure that all attributes are consumed. + Expect expect_attributes_consumed(VectorRef list); + + /// Raises an error if the next token is the start of a template list. + /// Used to hint to the user that the parser interpreted the following as a templated identifier + /// expression: + /// + /// ``` + /// a < b, c > + /// ^~~~~~~~ + /// ``` + Expect expect_next_not_template_list(const Source& lhs_source); + + /// Raises an error if the parsed expression is a templated identifier expression + /// Used to hint to the user that the parser intepreted the following as a templated identifier + /// expression: + /// + /// ``` + /// a < b, c > d + /// ^^^^^^^^^^ + /// expr + /// ``` + Expect expect_not_templated_ident_expr(const ast::Expression* expr); + + /// Parses the given enum, providing sensible error messages if the next token does not match + /// any of the enum values. + /// @param name the name of the enumerator + /// @param parse the optimized function used to parse the enum + /// @param strings the list of possible strings in the enum + /// @param use an optional description of what was being parsed if an error was raised. + template + Expect expect_enum(std::string_view name, + ENUM (*parse)(std::string_view str), + Slice strings, + std::string_view use = ""); + + Expect expect_type(std::string_view use); + + Maybe non_block_statement(); + Maybe for_header_initializer(); + Maybe for_header_continuing(); + + class MultiTokenSource; + + /// Creates a new `ast::Node` owned by the Module. When the Module is + /// destructed, the `ast::Node` will also be destructed. + /// @param args the arguments to pass to the constructor + /// @returns the node pointer + template + T* create(ARGS&&... args) { + return builder_.create(std::forward(args)...); + } + + Source::File const* const file_; + std::vector tokens_; + size_t next_token_idx_ = 0; + size_t last_source_idx_ = 0; + bool synchronized_ = true; + uint32_t parse_depth_ = 0; + std::vector sync_tokens_; + int silence_diags_ = 0; + ProgramBuilder builder_; + size_t max_errors_ = 25; +}; + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_PARSER_PARSER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.cc new file mode 100644 index 000000000..9aef695c0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.cc @@ -0,0 +1,290 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reader/parser/token.h" + +namespace tint::wgsl::reader { + +// static +std::string_view Token::TypeToName(Type type) { + switch (type) { + case Token::Type::kError: + return "error"; + case Token::Type::kEOF: + return "end of file"; + case Token::Type::kIdentifier: + return "identifier"; + case Token::Type::kFloatLiteral: + return "abstract float literal"; + case Token::Type::kFloatLiteral_F: + return "'f'-suffixed float literal"; + case Token::Type::kFloatLiteral_H: + return "'h'-suffixed float literal"; + case Token::Type::kIntLiteral: + return "abstract integer literal"; + case Token::Type::kIntLiteral_I: + return "'i'-suffixed integer literal"; + case Token::Type::kIntLiteral_U: + return "'u'-suffixed integer literal"; + case Token::Type::kPlaceholder: + return "placeholder"; + case Token::Type::kUninitialized: + return "uninitialized"; + + case Token::Type::kAnd: + return "&"; + case Token::Type::kAndAnd: + return "&&"; + case Token::Type::kArrow: + return "->"; + case Token::Type::kAttr: + return "@"; + case Token::Type::kForwardSlash: + return "/"; + case Token::Type::kBang: + return "!"; + case Token::Type::kBracketLeft: + return "["; + case Token::Type::kBracketRight: + return "]"; + case Token::Type::kBraceLeft: + return "{"; + case Token::Type::kBraceRight: + return "}"; + case Token::Type::kColon: + return ":"; + case Token::Type::kComma: + return ","; + case Token::Type::kEqual: + return "="; + case Token::Type::kEqualEqual: + return "=="; + case Token::Type::kTemplateArgsRight: + case Token::Type::kGreaterThan: + return ">"; + case Token::Type::kGreaterThanEqual: + return ">="; + case Token::Type::kShiftRight: + return ">>"; + case Token::Type::kTemplateArgsLeft: + case Token::Type::kLessThan: + return "<"; + case Token::Type::kLessThanEqual: + return "<="; + case Token::Type::kShiftLeft: + return "<<"; + case Token::Type::kMod: + return "%"; + case Token::Type::kNotEqual: + return "!="; + case Token::Type::kMinus: + return "-"; + case Token::Type::kMinusMinus: + return "--"; + case Token::Type::kPeriod: + return "."; + case Token::Type::kPlus: + return "+"; + case Token::Type::kPlusPlus: + return "++"; + case Token::Type::kOr: + return "|"; + case Token::Type::kOrOr: + return "||"; + case Token::Type::kParenLeft: + return "("; + case Token::Type::kParenRight: + return ")"; + case Token::Type::kSemicolon: + return ";"; + case Token::Type::kStar: + return "*"; + case Token::Type::kTilde: + return "~"; + case Token::Type::kUnderscore: + return "_"; + case Token::Type::kXor: + return "^"; + case Token::Type::kPlusEqual: + return "+="; + case Token::Type::kMinusEqual: + return "-="; + case Token::Type::kTimesEqual: + return "*="; + case Token::Type::kDivisionEqual: + return "/="; + case Token::Type::kModuloEqual: + return "%="; + case Token::Type::kAndEqual: + return "&="; + case Token::Type::kOrEqual: + return "|="; + case Token::Type::kXorEqual: + return "^="; + case Token::Type::kShiftLeftEqual: + return "<<="; + case Token::Type::kShiftRightEqual: + return ">>="; + + case Token::Type::kAlias: + return "alias"; + case Token::Type::kBreak: + return "break"; + case Token::Type::kCase: + return "case"; + case Token::Type::kConst: + return "const"; + case Token::Type::kConstAssert: + return "const_assert"; + case Token::Type::kContinue: + return "continue"; + case Token::Type::kContinuing: + return "continuing"; + case Token::Type::kDiagnostic: + return "diagnostic"; + case Token::Type::kDiscard: + return "discard"; + case Token::Type::kDefault: + return "default"; + case Token::Type::kElse: + return "else"; + case Token::Type::kEnable: + return "enable"; + case Token::Type::kFallthrough: + return "fallthrough"; + case Token::Type::kFalse: + return "false"; + case Token::Type::kFn: + return "fn"; + case Token::Type::kFor: + return "for"; + case Token::Type::kIf: + return "if"; + case Token::Type::kLet: + return "let"; + case Token::Type::kLoop: + return "loop"; + case Token::Type::kOverride: + return "override"; + case Token::Type::kReturn: + return "return"; + case Token::Type::kRequires: + return "requires"; + case Token::Type::kStruct: + return "struct"; + case Token::Type::kSwitch: + return "switch"; + case Token::Type::kTrue: + return "true"; + case Token::Type::kVar: + return "var"; + case Token::Type::kWhile: + return "while"; + } + + return ""; +} + +Token::Token() : type_(Type::kUninitialized) {} + +Token::Token(Type type, const Source& source, std::string_view view) + : type_(type), source_(source), value_(view) {} + +Token::Token(Type type, const Source& source, const std::string& str) + : type_(type), source_(source), value_(str) {} + +Token::Token(Type type, const Source& source, const char* str) + : type_(type), source_(source), value_(std::string_view(str)) {} + +Token::Token(Type type, const Source& source, int64_t val) + : type_(type), source_(source), value_(val) {} + +Token::Token(Type type, const Source& source, double val) + : type_(type), source_(source), value_(val) {} + +Token::Token(Type type, const Source& source) : type_(type), source_(source) {} + +Token::Token(Token&&) = default; + +Token::~Token() = default; + +bool Token::operator==(std::string_view ident) const { + if (type_ != Type::kIdentifier) { + return false; + } + if (auto* view = std::get_if(&value_)) { + return *view == ident; + } + return std::get(value_) == ident; +} + +std::string Token::to_str() const { + switch (type_) { + case Type::kFloatLiteral: + return std::to_string(std::get(value_)); + case Type::kFloatLiteral_F: + return std::to_string(std::get(value_)) + "f"; + case Type::kFloatLiteral_H: + return std::to_string(std::get(value_)) + "h"; + case Type::kIntLiteral: + return std::to_string(std::get(value_)); + case Type::kIntLiteral_I: + return std::to_string(std::get(value_)) + "i"; + case Type::kIntLiteral_U: + return std::to_string(std::get(value_)) + "u"; + case Type::kIdentifier: + case Type::kError: + if (auto* view = std::get_if(&value_)) { + return std::string(*view); + } + return std::get(value_); + default: + return ""; + } +} + +std::string_view Token::to_str_view() const { + if (type_ != Type::kIdentifier) { + return {}; + } + + if (auto* view = std::get_if(&value_)) { + return *view; + } + auto& s = std::get(value_); + return {s.data(), s.length()}; +} + +double Token::to_f64() const { + return std::get(value_); +} + +int64_t Token::to_i64() const { + return std::get(value_); +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.h new file mode 100644 index 000000000..e6b1d21c6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/parser/token.h @@ -0,0 +1,382 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_PARSER_TOKEN_H_ +#define SRC_TINT_LANG_WGSL_READER_PARSER_TOKEN_H_ + +#include +#include +#include + +#include "src/tint/utils/diagnostic/source.h" + +namespace tint::wgsl::reader { + +/// Stores tokens generated by the Lexer +class Token { + public: + /// The type of the parsed token + enum class Type { + /// Error result + kError = -2, + /// Uninitialized token + kUninitialized = 0, + /// Placeholder token which maybe filled in later + kPlaceholder = 1, + /// End of input string reached + kEOF, + + /// An identifier + kIdentifier, + /// A float literal with no suffix + kFloatLiteral, + /// A float literal with an 'f' suffix + kFloatLiteral_F, + /// A float literal with an 'h' suffix + kFloatLiteral_H, + /// An integer literal with no suffix + kIntLiteral, + /// An integer literal with an 'i' suffix + kIntLiteral_I, + /// An integer literal with a 'u' suffix + kIntLiteral_U, + + /// A '&' + kAnd, + /// A '&&' + kAndAnd, + /// A '->' + kArrow, + /// A '@' + kAttr, + /// A '/' + kForwardSlash, + /// A '!' + kBang, + /// A '[' + kBracketLeft, + /// A ']' + kBracketRight, + /// A '{' + kBraceLeft, + /// A '}' + kBraceRight, + /// A ':' + kColon, + /// A ',' + kComma, + /// A '=' + kEqual, + /// A '==' + kEqualEqual, + /// A '>' (post template-args classification) + kTemplateArgsRight, + /// A '>' + kGreaterThan, + /// A '>=' + kGreaterThanEqual, + /// A '>>' + kShiftRight, + /// A '<' (post template-args classification) + kTemplateArgsLeft, + /// A '<' + kLessThan, + /// A '<=' + kLessThanEqual, + /// A '<<' + kShiftLeft, + /// A '%' + kMod, + /// A '-' + kMinus, + /// A '--' + kMinusMinus, + /// A '!=' + kNotEqual, + /// A '.' + kPeriod, + /// A '+' + kPlus, + /// A '++' + kPlusPlus, + /// A '|' + kOr, + /// A '||' + kOrOr, + /// A '(' + kParenLeft, + /// A ')' + kParenRight, + /// A ';' + kSemicolon, + /// A '*' + kStar, + /// A '~' + kTilde, + /// A '_' + kUnderscore, + /// A '^' + kXor, + /// A '+=' + kPlusEqual, + /// A '-=' + kMinusEqual, + /// A '*=' + kTimesEqual, + /// A '/=' + kDivisionEqual, + /// A '%=' + kModuloEqual, + /// A '&=' + kAndEqual, + /// A '|=' + kOrEqual, + /// A '^=' + kXorEqual, + /// A '>>=' + kShiftRightEqual, + /// A '<<=' + kShiftLeftEqual, + + /// A 'alias' + kAlias, + /// A 'break' + kBreak, + /// A 'case' + kCase, + /// A 'const' + kConst, + /// A 'const_assert' + kConstAssert, + /// A 'continue' + kContinue, + /// A 'continuing' + kContinuing, + /// A 'default' + kDefault, + /// A 'diagnostic' + kDiagnostic, + /// A 'discard' + kDiscard, + /// A 'else' + kElse, + /// A 'enable' + kEnable, + /// A 'fallthrough' + // Note, this isn't a keyword, but a reserved word. We match it as a keyword in order to + // provide better diagnostics in case a `fallthrough` is added to a case body. + kFallthrough, + /// A 'false' + kFalse, + /// A 'fn' + kFn, + // A 'for' + kFor, + /// A 'if' + kIf, + /// A 'let' + kLet, + /// A 'loop' + kLoop, + /// A 'override' + kOverride, + /// A 'requires' + kRequires, + /// A 'return' + kReturn, + /// A 'struct' + kStruct, + /// A 'switch' + kSwitch, + /// A 'true' + kTrue, + /// A 'var' + kVar, + /// A 'while' + kWhile, + }; + + /// Converts a token type to a name + /// @param type the type to convert + /// @returns the token type as as string + static std::string_view TypeToName(Type type); + + /// Creates an uninitialized token + Token(); + /// Create a Token + /// @param type the Token::Type of the token + /// @param source the source of the token + Token(Type type, const Source& source); + + /// Create a string Token + /// @param type the Token::Type of the token + /// @param source the source of the token + /// @param view the source string view for the token + Token(Type type, const Source& source, std::string_view view); + /// Create a string Token + /// @param type the Token::Type of the token + /// @param source the source of the token + /// @param str the source string for the token + Token(Type type, const Source& source, const std::string& str); + /// Create a string Token + /// @param type the Token::Type of the token + /// @param source the source of the token + /// @param str the source string for the token + Token(Type type, const Source& source, const char* str); + /// Create a integer Token of the given type + /// @param type the Token::Type of the token + /// @param source the source of the token + /// @param val the source unsigned for the token + Token(Type type, const Source& source, int64_t val); + /// Create a double Token + /// @param type the Token::Type of the token + /// @param source the source of the token + /// @param val the source double for the token + Token(Type type, const Source& source, double val); + /// Move constructor + Token(Token&&); + ~Token(); + + /// Equality operator with an identifier + /// @param ident the identifier string + /// @return true if this token is an identifier and is equal to ident. + bool operator==(std::string_view ident) const; + + /// Sets the token to the given type + /// @param type the type to set + void SetType(Token::Type type) { type_ = type; } + + /// Returns true if the token is of the given type + /// @param t the type to check against. + /// @returns true if the token is of type `t` + bool Is(Type t) const { return type_ == t; } + + /// @returns true if the token is uninitialized + bool IsUninitialized() const { return type_ == Type::kUninitialized; } + /// @returns true if the token is a placeholder + bool IsPlaceholder() const { return type_ == Type::kPlaceholder; } + /// @returns true if the token is EOF + bool IsEof() const { return type_ == Type::kEOF; } + /// @returns true if the token is Error + bool IsError() const { return type_ == Type::kError; } + /// @returns true if the token is an identifier + bool IsIdentifier() const { return type_ == Type::kIdentifier; } + /// @returns true if the token is a literal + bool IsLiteral() const { + return type_ == Type::kIntLiteral || type_ == Type::kIntLiteral_I || + type_ == Type::kIntLiteral_U || type_ == Type::kFalse || type_ == Type::kTrue || + type_ == Type::kFloatLiteral || type_ == Type::kFloatLiteral_F || + type_ == Type::kFloatLiteral_H; + } + + /// @returns the number of placeholder tokens required to follow the token, in order to provide + /// space for token splitting. + size_t NumPlaceholders() const { + switch (type_) { + case Type::kShiftRightEqual: + return 2; + case Type::kShiftRight: + case Type::kGreaterThanEqual: + case Type::kAndAnd: + case Type::kMinusMinus: + return 1; + default: + return 0; + } + } + + /// @returns true if the token is a binary operator + bool IsBinaryOperator() const { + switch (type_) { + case Type::kAnd: + case Type::kAndAnd: + case Type::kEqualEqual: + case Type::kForwardSlash: + case Type::kGreaterThan: + case Type::kGreaterThanEqual: + case Type::kLessThan: + case Type::kLessThanEqual: + case Type::kMinus: + case Type::kMod: + case Type::kNotEqual: + case Type::kOr: + case Type::kOrOr: + case Type::kPlus: + case Type::kShiftLeft: + case Type::kShiftRight: + case Type::kStar: + case Type::kXor: + return true; + default: + return false; + } + } + + /// @returns the source information for this token + Source source() const { return source_; } + + /// @returns the type of the token + Type type() const { return type_; } + + /// Returns the string value of the token + /// @return std::string + std::string to_str() const; + /// Returns the string view of the token + /// @return std::string_view + /// @note if the token is not an identifier, an empty string_view will be returned. + std::string_view to_str_view() const; + /// Returns the float value of the token. 0 is returned if the token does not + /// contain a float value. + /// @return double + double to_f64() const; + /// Returns the int64_t value of the token. 0 is returned if the token does + /// not contain an integer value. + /// @return int64_t + int64_t to_i64() const; + + /// @returns the token type as string + std::string_view to_name() const { return Token::TypeToName(type_); } + + private: + /// The Token::Type of the token + Type type_ = Type::kError; + /// The source where the token appeared + Source source_; + /// The value represented by the token + std::variant value_; +}; + +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Token::Type type) { + out << Token::TypeToName(type); + return out; +} + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_PARSER_TOKEN_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc new file mode 100644 index 000000000..0c1ad6a82 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc @@ -0,0 +1,1408 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h" + +#include +#include + +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/type/array_count.h" +#include "src/tint/lang/core/ir/value.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/wgsl/ast/accessor_expression.h" +#include "src/tint/lang/wgsl/ast/alias.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/binary_expression.h" +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/break_if_statement.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/compound_assignment_statement.h" +#include "src/tint/lang/wgsl/ast/const.h" +#include "src/tint/lang/wgsl/ast/const_assert.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/diagnostic_directive.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/enable.h" +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" +#include "src/tint/lang/wgsl/ast/function.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/identifier_expression.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h" +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/invariant_attribute.h" +#include "src/tint/lang/wgsl/ast/let.h" +#include "src/tint/lang/wgsl/ast/literal_expression.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/member_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/override.h" +#include "src/tint/lang/wgsl/ast/phony_expression.h" +#include "src/tint/lang/wgsl/ast/requires.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/statement.h" +#include "src/tint/lang/wgsl/ast/struct.h" +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" +#include "src/tint/lang/wgsl/ast/var.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/while_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/ir/builtin_call.h" +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/sem/array_count.h" +#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h" +#include "src/tint/lang/wgsl/sem/builtin_fn.h" +#include "src/tint/lang/wgsl/sem/call.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/index_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/load.h" +#include "src/tint/lang/wgsl/sem/member_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/module.h" +#include "src/tint/lang/wgsl/sem/switch_statement.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/lang/wgsl/sem/value_constructor.h" +#include "src/tint/lang/wgsl/sem/value_conversion.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/containers/scope_stack.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/macros/scoped_assignment.h" +#include "src/tint/utils/rtti/switch.h" + +using namespace tint::core::number_suffixes; // NOLINT +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::wgsl::reader { +namespace { + +using ResultType = diag::Result; + +/// Impl is the private-implementation of FromProgram(). +class Impl { + public: + /// Constructor + /// @param program the program to convert to IR + explicit Impl(const Program& program) : program_(program) {} + + /// Builds an IR module from the program passed to the constructor. + /// @return the IR module or an error. + ResultType Build() { return EmitModule(); } + + private: + enum class ControlFlags { kNone, kExcludeSwitch }; + + // The input Program + const Program& program_; + + /// The IR module being built + core::ir::Module mod; + + /// The IR builder being used by the impl. + core::ir::Builder builder_{mod}; + + // The clone context used to clone data from #program_ + core::constant::CloneContext clone_ctx_{ + /* type_ctx */ core::type::CloneContext{ + /* src */ {&program_.Symbols()}, + /* dst */ {&builder_.ir.symbols, &builder_.ir.Types()}, + }, + /* dst */ {builder_.ir.constant_values}, + }; + + /// The stack of flow control instructions. + Vector control_stack_; + + struct VectorRefElementAccess { + core::ir::Value* vector = nullptr; + core::ir::Value* index = nullptr; + }; + + using ValueOrVecElAccess = std::variant; + + /// The current block for expressions. + core::ir::Block* current_block_ = nullptr; + + /// The current function being processed. + core::ir::Function* current_function_ = nullptr; + + /// The current stack of scopes being processed. + ScopeStack scopes_; + + /// The diagnostic that have been raised. + diag::List diagnostics_; + + class StackScope { + public: + explicit StackScope(Impl* impl) : impl_(impl) { impl->scopes_.Push(); } + + ~StackScope() { impl_->scopes_.Pop(); } + + protected: + Impl* impl_; + }; + + class ControlStackScope : public StackScope { + public: + ControlStackScope(Impl* impl, core::ir::ControlInstruction* b) : StackScope(impl) { + impl_->control_stack_.Push(b); + } + + ~ControlStackScope() { impl_->control_stack_.Pop(); } + }; + + diag::Diagnostic& AddError(const Source& source) { return diagnostics_.AddError(source); } + + bool NeedTerminator() { + return (current_block_ != nullptr) && (current_block_->Terminator() == nullptr); + } + + void SetTerminator(core::ir::Terminator* terminator) { + TINT_ASSERT(current_block_); + TINT_ASSERT(!current_block_->Terminator()); + + current_block_->Append(terminator); + current_block_ = nullptr; + } + + core::ir::Instruction* FindEnclosingControl(ControlFlags flags) { + for (auto it = control_stack_.rbegin(); it != control_stack_.rend(); ++it) { + if ((*it)->Is()) { + return *it; + } + if (flags == ControlFlags::kExcludeSwitch) { + continue; + } + if ((*it)->Is()) { + return *it; + } + } + return nullptr; + } + + ResultType EmitModule() { + auto* sem = program_.Sem().Module(); + + for (auto* decl : sem->DependencyOrderedDeclarations()) { + tint::Switch( + decl, // + [&](const ast::Struct*) { + // Will be encoded into the `type::Struct` when used. We will then hoist all + // used structs up to module scope when converting IR. + }, + [&](const ast::Alias*) { + // Folded away and doesn't appear in the IR. + }, + [&](const ast::Variable* var) { + // Setup the current block to be the root block for the module. The builder + // will handle creating it if it doesn't exist already. + TINT_SCOPED_ASSIGNMENT(current_block_, mod.root_block); + EmitVariable(var); + }, + [&](const ast::Function* func) { EmitFunction(func); }, + [&](const ast::Enable*) { + // TODO(dsinclair): Implement? I think these need to be passed along so further + // stages know what is enabled. + }, + [&](const ast::ConstAssert*) { + // Evaluated by the resolver, drop from the IR. + }, + [&](const ast::DiagnosticDirective*) { + // Ignored for now. + }, // + [&](const ast::Requires*) { + // Ignored for now. + }, // + TINT_ICE_ON_NO_MATCH); + } + + if (diagnostics_.ContainsErrors()) { + return diag::Failure{std::move(diagnostics_)}; + } + + return std::move(mod); + } + + void EmitFunction(const ast::Function* ast_func) { + // The flow stack should have been emptied when the previous function finished building. + TINT_ASSERT(control_stack_.IsEmpty()); + + const auto* sem = program_.Sem().Get(ast_func); + + auto* ir_func = builder_.Function(ast_func->name->symbol.NameView(), + sem->ReturnType()->Clone(clone_ctx_.type_ctx)); + current_function_ = ir_func; + scopes_.Set(ast_func->name->symbol, ir_func); + + if (ast_func->IsEntryPoint()) { + switch (ast_func->PipelineStage()) { + case ast::PipelineStage::kVertex: + ir_func->SetStage(core::ir::Function::PipelineStage::kVertex); + break; + case ast::PipelineStage::kFragment: + ir_func->SetStage(core::ir::Function::PipelineStage::kFragment); + break; + case ast::PipelineStage::kCompute: { + ir_func->SetStage(core::ir::Function::PipelineStage::kCompute); + + auto attr = ast::GetAttribute(ast_func->attributes); + TINT_ASSERT(attr) << "Missing workgroup attribute for compute entry point."; + + TINT_SCOPED_ASSIGNMENT(current_block_, mod.root_block); + + // The x size is always required (y, z are optional). + auto value_x = EmitValueExpression(attr->x); + bool is_unsigned = value_x->Type()->IsUnsignedIntegerScalar(); + + auto* one_const = is_unsigned ? builder_.Constant(1_u) : builder_.Constant(1_i); + + ir_func->SetWorkgroupSize(value_x, + attr->y ? EmitValueExpression(attr->y) : one_const, + attr->z ? EmitValueExpression(attr->z) : one_const); + + const auto subgroup_attr = + ast::GetAttribute(ast_func->attributes); + if (subgroup_attr) { + auto* subgroup_size = EmitValueExpression(subgroup_attr->subgroup_size); + ir_func->SetSubgroupSize(subgroup_size); + } + + break; + } + default: { + TINT_ICE() << "Invalid pipeline stage"; + } + } + + for (auto* attr : ast_func->return_type_attributes) { + tint::Switch( + attr, // + [&](const ast::InterpolateAttribute* interp) { + ir_func->SetReturnInterpolation(interp->interpolation); + }, + [&](const ast::InvariantAttribute*) { ir_func->SetReturnInvariant(true); }, + [&](const ast::BuiltinAttribute* b) { + ir_func->SetReturnBuiltin(b->builtin); + ir_func->SetReturnDepthMode(b->depth_mode); + }); + } + ir_func->SetReturnLocation(sem->ReturnLocation()); + } + + scopes_.Push(); + TINT_DEFER(scopes_.Pop()); + + Vector params; + for (auto* p : ast_func->params) { + const auto* param_sem = program_.Sem().Get(p)->As(); + auto* ty = RemapOverrideSizedArrayIfNeeded(param_sem->Type()); + auto* param = builder_.FunctionParam(p->name->symbol.NameView(), ty); + + for (auto* attr : p->attributes) { + tint::Switch( + attr, // + [&](const ast::InterpolateAttribute* interp) { + param->SetInterpolation(interp->interpolation); + }, + [&](const ast::InvariantAttribute*) { param->SetInvariant(true); }, + [&](const ast::BuiltinAttribute* b) { param->SetBuiltin(b->builtin); }); + + param->SetLocation(param_sem->Attributes().location); + param->SetColor(param_sem->Attributes().color); + } + + scopes_.Set(p->name->symbol, param); + params.Push(param); + } + ir_func->SetParams(params); + + TINT_SCOPED_ASSIGNMENT(current_block_, ir_func->Block()); + EmitBlock(ast_func->body); + + // Add a terminator if one was not already created. + if (NeedTerminator()) { + if (!program_.Sem().Get(ast_func->body)->Behaviors().Contains(sem::Behavior::kNext)) { + SetTerminator(builder_.Unreachable()); + } else { + SetTerminator(builder_.Return(current_function_)); + } + } + + TINT_ASSERT(control_stack_.IsEmpty()); + current_block_ = nullptr; + current_function_ = nullptr; + } + + void EmitStatements(VectorRef stmts) { + for (auto* s : stmts) { + EmitStatement(s); + + if (auto* sem = program_.Sem().Get(s); + sem && !sem->Behaviors().Contains(sem::Behavior::kNext)) { + break; // Unreachable statement. + } + } + } + + void EmitStatement(const ast::Statement* stmt) { + tint::Switch( + stmt, // + [&](const ast::AssignmentStatement* a) { EmitAssignment(a); }, + [&](const ast::BlockStatement* b) { EmitBlock(b); }, + [&](const ast::BreakStatement* b) { EmitBreak(b); }, + [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); }, + [&](const ast::CallStatement* c) { EmitCall(c); }, + [&](const ast::CompoundAssignmentStatement* c) { EmitCompoundAssignment(c); }, + [&](const ast::ContinueStatement* c) { EmitContinue(c); }, + [&](const ast::DiscardStatement* d) { EmitDiscard(d); }, + [&](const ast::IfStatement* i) { EmitIf(i); }, + [&](const ast::LoopStatement* l) { EmitLoop(l); }, + [&](const ast::ForLoopStatement* l) { EmitForLoop(l); }, + [&](const ast::WhileStatement* l) { EmitWhile(l); }, + [&](const ast::ReturnStatement* r) { EmitReturn(r); }, + [&](const ast::SwitchStatement* s) { EmitSwitch(s); }, + [&](const ast::VariableDeclStatement* v) { EmitVariable(v->variable); }, + [&](const ast::IncrementDecrementStatement* i) { EmitIncrementDecrement(i); }, + [&](const ast::ConstAssert*) { + // Not emitted + }, // + TINT_ICE_ON_NO_MATCH); + } + + void EmitAssignment(const ast::AssignmentStatement* stmt) { + // If assigning to a phony, and the expression evaluation stage is runtime or override, just + // generate the RHS and we're done. Note that, because this isn't used, a subsequent + // transform could remove it due to it being dead code. This could then change the interface + // for the program (i.e. a global var no longer used). If that happens we have to either fix + // this to store to a phony value, or make sure we pull the interface before doing the dead + // code elimination. + if (stmt->lhs->Is()) { + const auto* sem = program_.Sem().GetVal(stmt->rhs); + switch (sem->Stage()) { + case core::EvaluationStage::kRuntime: + case core::EvaluationStage::kOverride: { + auto* value = EmitValueExpression(stmt->rhs); + auto* result = value->As(); + // Overrides need to be referenced if they are to be retained in single entry + // point in the case of phony assignment. + if (!result || result->Instruction()->Block() == mod.root_block) { + current_block_->Append(builder_.Let(value)); + } + } break; + case core::EvaluationStage::kNotEvaluated: + case core::EvaluationStage::kConstant: + // Don't emit. + break; + } + return; + } + + auto lhs = EmitExpression(stmt->lhs); + + auto rhs = EmitValueExpression(stmt->rhs); + if (!rhs) { + return; + } + + auto b = builder_.Append(current_block_); + if (auto* v = std::get_if(&lhs)) { + b.Store(*v, rhs); + } else if (auto ref = std::get_if(&lhs)) { + b.StoreVectorElement(ref->vector, ref->index, rhs); + } + } + + void EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) { + auto lhs = EmitExpression(stmt->lhs); + + auto* one = program_.TypeOf(stmt->lhs)->UnwrapRef()->IsSignedIntegerScalar() + ? builder_.Constant(1_i) + : builder_.Constant(1_u); + + EmitCompoundAssignment(lhs, one, + stmt->increment ? core::BinaryOp::kAdd : core::BinaryOp::kSubtract); + } + + void EmitCompoundAssignment(const ast::CompoundAssignmentStatement* stmt) { + auto lhs = EmitExpression(stmt->lhs); + + auto rhs = EmitValueExpression(stmt->rhs); + if (!rhs) { + return; + } + + EmitCompoundAssignment(lhs, rhs, stmt->op); + } + + void EmitCompoundAssignment(ValueOrVecElAccess lhs, core::ir::Value* rhs, core::BinaryOp op) { + auto b = builder_.Append(current_block_); + if (auto* v = std::get_if(&lhs)) { + auto* load = b.Load(*v); + auto* inst = current_block_->Append(BinaryOp(load->Result(), rhs, op)); + b.Store(*v, inst); + } else if (auto ref = std::get_if(&lhs)) { + auto* load = b.LoadVectorElement(ref->vector, ref->index); + auto* inst = b.Append(BinaryOp(load->Result(), rhs, op)); + b.StoreVectorElement(ref->vector, ref->index, inst); + } + } + + void EmitBlock(const ast::BlockStatement* block) { + scopes_.Push(); + TINT_DEFER(scopes_.Pop()); + + // Note, this doesn't need to emit a Block as the current block should be sufficient as the + // blocks all get flattened. Each flow control node will inject the basic blocks it + // requires. + EmitStatements(block->statements); + } + + void EmitIf(const ast::IfStatement* stmt) { + // Emit the if condition into the end of the preceding block + auto reg = EmitValueExpression(stmt->condition); + if (!reg) { + return; + } + auto* if_inst = builder_.If(reg); + current_block_->Append(if_inst); + + { + ControlStackScope scope(this, if_inst); + + { + TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True()); + EmitBlock(stmt->body); + + // If the true block did not terminate, then emit an exit_if + if (NeedTerminator()) { + SetTerminator(builder_.ExitIf(if_inst)); + } + } + + if (stmt->else_statement) { + TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False()); + EmitStatement(stmt->else_statement); + + // If the false block did not terminate, then emit an exit_if + if (NeedTerminator()) { + SetTerminator(builder_.ExitIf(if_inst)); + } + } + } + } + + void EmitLoop(const ast::LoopStatement* stmt) { + auto* loop_inst = builder_.Loop(); + current_block_->Append(loop_inst); + + // Note: The loop doesn't use EmitBlock because it needs the scope stack to not get popped + // until after the continuing block. + + ControlStackScope scope(this, loop_inst); + + auto& body_behaviors = program_.Sem().Get(stmt->body)->Behaviors(); + { + 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 + // or mark the end of the block as unreachable. + if (NeedTerminator()) { + if (body_behaviors.Contains(sem::Behavior::kNext)) { + SetTerminator(builder_.Continue(loop_inst)); + } else { + SetTerminator(builder_.Unreachable()); + } + } + } + + // Emit a continuing block if it is reachable. + if (body_behaviors.Contains(sem::Behavior::kNext) || + body_behaviors.Contains(sem::Behavior::kContinue)) { + 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 terminate already + if (NeedTerminator()) { + SetTerminator(builder_.NextIteration(loop_inst)); + } + } + } + + void EmitWhile(const ast::WhileStatement* stmt) { + 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 + { + TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Continuing()); + SetTerminator(builder_.NextIteration(loop_inst)); + } + + { + TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Body()); + + // Emit the while condition into the Start().target of the loop + auto reg = EmitValueExpression(stmt->condition); + if (!reg) { + return; + } + + // Create an `if (cond) {} else {break;}` control flow + auto* if_inst = builder_.If(reg); + current_block_->Append(if_inst); + + { + TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True()); + SetTerminator(builder_.ExitIf(if_inst)); + } + + { + TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False()); + SetTerminator(builder_.ExitLoop(loop_inst)); + } + + EmitStatements(stmt->body->statements); + + // The current block didn't `break`, `return` or `continue`, go to the continuing block. + if (NeedTerminator()) { + SetTerminator(builder_.Continue(loop_inst)); + } + } + } + + void EmitForLoop(const ast::ForLoopStatement* stmt) { + auto* loop_inst = builder_.Loop(); + current_block_->Append(loop_inst); + + ControlStackScope scope(this, loop_inst); + + if (stmt->initializer) { + TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Initializer()); + + // Emit the for initializer before branching to the loop body + EmitStatement(stmt->initializer); + + if (NeedTerminator()) { + SetTerminator(builder_.NextIteration(loop_inst)); + } + } + + TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Body()); + + if (stmt->condition) { + // Emit the condition into the target target of the loop body + auto reg = EmitValueExpression(stmt->condition); + if (!reg) { + return; + } + + // Create an `if (cond) {} else {break;}` control flow + auto* if_inst = builder_.If(reg); + current_block_->Append(if_inst); + + { + TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->True()); + SetTerminator(builder_.ExitIf(if_inst)); + } + + { + TINT_SCOPED_ASSIGNMENT(current_block_, if_inst->False()); + SetTerminator(builder_.ExitLoop(loop_inst)); + } + } + + EmitBlock(stmt->body); + if (NeedTerminator()) { + SetTerminator(builder_.Continue(loop_inst)); + } + + if (stmt->continuing) { + TINT_SCOPED_ASSIGNMENT(current_block_, loop_inst->Continuing()); + EmitStatement(stmt->continuing); + SetTerminator(builder_.NextIteration(loop_inst)); + } + } + + void EmitSwitch(const ast::SwitchStatement* stmt) { + // Emit the condition into the preceding block + auto reg = EmitValueExpression(stmt->condition); + if (!reg) { + return; + } + auto* switch_inst = builder_.Switch(reg); + current_block_->Append(switch_inst); + + ControlStackScope scope(this, switch_inst); + + const auto* sem = program_.Sem().Get(stmt); + for (const auto* c : sem->Cases()) { + Vector selectors; + for (const auto* selector : c->Selectors()) { + if (selector->IsDefault()) { + selectors.Push(nullptr); + } else { + selectors.Push(builder_.Constant(selector->Value()->Clone(clone_ctx_))); + } + } + + TINT_SCOPED_ASSIGNMENT(current_block_, builder_.Case(switch_inst, selectors)); + EmitBlock(c->Body()->Declaration()); + + if (NeedTerminator()) { + SetTerminator(builder_.ExitSwitch(switch_inst)); + } + } + } + + void EmitReturn(const ast::ReturnStatement* stmt) { + core::ir::Value* ret_value = nullptr; + if (stmt->value) { + auto ret = EmitValueExpression(stmt->value); + if (!ret) { + return; + } + ret_value = ret; + } + if (ret_value) { + SetTerminator(builder_.Return(current_function_, ret_value)); + } else { + SetTerminator(builder_.Return(current_function_)); + } + } + + void EmitBreak(const ast::BreakStatement*) { + auto* current_control = FindEnclosingControl(ControlFlags::kNone); + TINT_ASSERT(current_control); + + if (auto* c = current_control->As()) { + SetTerminator(builder_.ExitLoop(c)); + } else if (auto* s = current_control->As()) { + SetTerminator(builder_.ExitSwitch(s)); + } else { + TINT_UNREACHABLE(); + } + } + + void EmitContinue(const ast::ContinueStatement*) { + auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch); + TINT_ASSERT(current_control); + + if (auto* c = current_control->As()) { + SetTerminator(builder_.Continue(c)); + } else { + TINT_UNREACHABLE(); + } + } + + // Discard is being treated as an instruction. The semantics in WGSL is demote_to_helper, so + // the code has to continue as before it just predicates writes. If WGSL grows some kind of + // terminating discard that would probably make sense as a Block but would then require + // figuring out the multi-level exit that is triggered. + void EmitDiscard(const ast::DiscardStatement*) { current_block_->Append(builder_.Discard()); } + + void EmitBreakIf(const ast::BreakIfStatement* stmt) { + auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch); + + // Emit the break-if condition into the end of the preceding block + auto cond = EmitValueExpression(stmt->condition); + if (!cond) { + return; + } + SetTerminator(builder_.BreakIf(current_control->As(), cond)); + } + + ValueOrVecElAccess EmitExpression(const ast::Expression* root) { + struct Emitter { + explicit Emitter(Impl& i) : impl(i) {} + + ValueOrVecElAccess Emit(const ast::Expression* root) { + // Process the root expression. This will likely add tasks. + Process(root); + + // Execute all the tasks until all expressions have been resolved. + while (!tasks.IsEmpty()) { + auto task = tasks.Pop(); + task(); + } + + // Get the resolved root expression. + return Get(root); + } + + private: + Impl& impl; + Vector blocks; + Vector, 64> tasks; + Hashmap bindings_; + + void Bind(const ast::Expression* expr, core::ir::Value* value) { + // If this expression maps to sem::Load, insert a load instruction to get the result + if (impl.program_.Sem().Get(expr)) { + auto* load = impl.builder_.Load(value); + impl.current_block_->Append(load); + value = load->Result(); + } + bindings_.Add(expr, value); + } + + void Bind(const ast::Expression* expr, const VectorRefElementAccess& access) { + // If this expression maps to sem::Load, insert a load instruction to get the result + if (impl.program_.Sem().Get(expr)) { + auto* load = impl.builder_.LoadVectorElement(access.vector, access.index); + impl.current_block_->Append(load); + bindings_.Add(expr, load->Result()); + } else { + bindings_.Add(expr, access); + } + } + + ValueOrVecElAccess Get(const ast::Expression* expr) { + auto val = bindings_.Get(expr); + if (!val) { + return nullptr; + } + return *val; + } + + core::ir::Value* GetValue(const ast::Expression* expr) { + auto res = Get(expr); + if (auto** val = std::get_if(&res)) { + return *val; + } + TINT_ICE() << "expression did not resolve to a value"; + } + + void PushBlock(core::ir::Block* block) { + blocks.Push(impl.current_block_); + impl.current_block_ = block; + } + + void PopBlock() { impl.current_block_ = blocks.Pop(); } + + core::ir::Value* EmitConstant(const ast::Expression* expr) { + if (auto* sem = impl.program_.Sem().GetVal(expr)) { + if (auto* v = sem->ConstantValue()) { + if (auto* cv = v->Clone(impl.clone_ctx_)) { + auto* val = impl.builder_.Constant(cv); + bindings_.Add(expr, val); + return val; + } + } + } + return nullptr; + } + + void EmitAccess(const ast::AccessorExpression* expr) { + if (auto vec_access = AsVectorRefElementAccess(expr)) { + Bind(expr, vec_access.value()); + return; + } + + auto* obj = GetValue(expr->object); + if (!obj) { + TINT_UNREACHABLE() << "no object result"; + } + + auto* sem = impl.program_.Sem().Get(expr)->Unwrap(); + + // The access result type should match the source result type. If the source is a + // pointer, we generate a pointer. + const core::type::Type* ty = + sem->Type()->UnwrapRef()->Clone(impl.clone_ctx_.type_ctx); + if (auto* ptr = obj->Type()->As(); + ptr && !ty->Is()) { + ty = impl.builder_.ir.Types().ptr(ptr->AddressSpace(), ty, ptr->Access()); + } + + auto index = tint::Switch( + sem, + [&](const sem::IndexAccessorExpression* idx) -> core::ir::Value* { + if (auto* v = idx->Index()->ConstantValue()) { + if (auto* cv = v->Clone(impl.clone_ctx_)) { + return impl.builder_.Constant(cv); + } + TINT_UNREACHABLE() << "constant clone failed"; + } + return GetValue(idx->Index()->Declaration()); + }, + [&](const sem::StructMemberAccess* access) -> core::ir::Value* { + return impl.builder_.Constant(u32((access->Member()->Index()))); + }, + [&](const sem::Swizzle* swizzle) -> core::ir::Value* { + auto& indices = swizzle->Indices(); + + // A single element swizzle is just treated as an accessor. + if (indices.Length() == 1) { + return impl.builder_.Constant(u32(indices[0])); + } + auto* val = impl.builder_.Swizzle(ty, obj, std::move(indices)); + impl.current_block_->Append(val); + Bind(expr, val->Result()); + return nullptr; + }, // + TINT_ICE_ON_NO_MATCH); + + if (!index) { + return; + } + + // If the object is an unnamed value (a subexpression, not a let) and is the result + // of another access, then we can just append the index to that access. + if (!impl.mod.NameOf(obj).IsValid()) { + if (auto* inst_res = obj->As()) { + if (auto* access = inst_res->Instruction()->As()) { + access->AddIndex(index); + access->Result()->SetType(ty); + bindings_.Remove(expr->object); + // Move the access after the index expression. + if (impl.current_block_->Back() != access) { + impl.current_block_->Remove(access); + impl.current_block_->Append(access); + } + Bind(expr, access->Result()); + return; + } + } + } + + // Create a new access + auto* access = impl.builder_.Access(ty, obj, index); + impl.current_block_->Append(access); + Bind(expr, access->Result()); + } + + void EmitBinary(const ast::BinaryExpression* b) { + auto lhs = GetValue(b->lhs); + if (!lhs) { + return; + } + auto rhs = GetValue(b->rhs); + if (!rhs) { + return; + } + auto* inst = impl.BinaryOp(lhs, rhs, b->op); + if (!inst) { + return; + } + impl.current_block_->Append(inst); + Bind(b, inst->Result()); + } + + void EmitUnary(const ast::UnaryOpExpression* expr) { + auto val = GetValue(expr->expr); + if (!val) { + return; + } + core::ir::Instruction* inst = nullptr; + switch (expr->op) { + case core::UnaryOp::kAddressOf: + case core::UnaryOp::kIndirection: + // 'address-of' and 'indirection' just fold away and we propagate the + // pointer. + Bind(expr, val); + return; + case core::UnaryOp::kComplement: { + inst = impl.builder_.Complement(val); + break; + } + case core::UnaryOp::kNegation: { + inst = impl.builder_.Negation(val); + break; + } + case core::UnaryOp::kNot: { + inst = impl.builder_.Not(val); + break; + } + } + impl.current_block_->Append(inst); + Bind(expr, inst->Result()); + } + + void EmitCall(const ast::CallExpression* expr) { + // If this is a materialized semantic node, just use the constant value. + if (auto* mat = impl.program_.Sem().Get(expr)) { + if (mat->ConstantValue()) { + auto* cv = mat->ConstantValue()->Clone(impl.clone_ctx_); + if (!cv) { + impl.AddError(expr->source) << "failed to get constant value for call " + << expr->TypeInfo().name; + return; + } + Bind(expr, impl.builder_.Constant(cv)); + return; + } + } + Vector args; + args.Reserve(expr->args.Length()); + // Emit the arguments + for (const auto* arg : expr->args) { + auto value = GetValue(arg); + if (!value) { + impl.AddError(arg->source) << "failed to convert arguments"; + return; + } + args.Push(value); + } + auto* sem = impl.program_.Sem().Get(expr); + if (!sem) { + impl.AddError(expr->source) + << "failed to get semantic information for call " << expr->TypeInfo().name; + return; + } + auto* ty = sem->Target()->ReturnType()->Clone(impl.clone_ctx_.type_ctx); + core::ir::Instruction* inst = nullptr; + // If this is a builtin function, emit the specific builtin value + if (auto* b = sem->Target()->As()) { + if (b->Fn() == wgsl::BuiltinFn::kBitcast) { + inst = impl.builder_.Bitcast(ty, args[0]); + } else { + auto* call = + impl.builder_.Call(ty, b->Fn(), std::move(args)); + + // Set explicit template parameters if present. + if (b->Overload().num_explicit_templates > 0) { + auto* tmpl = expr->target->identifier->As(); + TINT_ASSERT(tmpl); + Vector explicit_types; + for (uint32_t i = 0; i < b->Overload().num_explicit_templates; i++) { + auto* tmpl_sem = impl.program_.Sem().Get(tmpl->arguments[i]); + auto* tmpl_ty = tmpl_sem->As(); + TINT_ASSERT(tmpl_ty); + auto* cloned_ty = tmpl_ty->Type()->Clone(impl.clone_ctx_.type_ctx); + explicit_types.Push(cloned_ty); + } + call->SetExplicitTemplateParams(std::move(explicit_types)); + } + + inst = call; + } + } else if (sem->Target()->As()) { + inst = impl.builder_.Construct(ty, std::move(args)); + } else if (sem->Target()->Is()) { + inst = impl.builder_.Convert(ty, args[0]); + } else if (expr->target->identifier->Is()) { + TINT_UNIMPLEMENTED() << "missing templated ident support"; + } else { + // Not a builtin and not a templated call, so this is a user function. + inst = impl.builder_.Call(ty, + impl.scopes_.Get(expr->target->identifier->symbol) + ->As(), + std::move(args)); + } + if (inst == nullptr) { + return; + } + impl.current_block_->Append(inst); + Bind(expr, inst->Result()); + } + + void EmitIdentifier(const ast::IdentifierExpression* i) { + auto* v = impl.scopes_.Get(i->identifier->symbol); + if (DAWN_UNLIKELY(!v)) { + impl.AddError(i->source) + << "unable to find identifier " << i->identifier->symbol.Name(); + return; + } + Bind(i, v); + } + + void EmitLiteral(const ast::LiteralExpression* lit) { + auto* sem = impl.program_.Sem().Get(lit); + if (!sem) { + impl.AddError(lit->source) + << "failed to get semantic information for node " << lit->TypeInfo().name; + return; + } + auto* cv = sem->ConstantValue()->Clone(impl.clone_ctx_); + if (!cv) { + impl.AddError(lit->source) + << "failed to get constant value for node " << lit->TypeInfo().name; + return; + } + auto* val = impl.builder_.Constant(cv); + Bind(lit, val); + } + + std::optional AsVectorRefElementAccess( + const ast::Expression* expr) { + return AsVectorRefElementAccess( + impl.program_.Sem().Get(expr)->UnwrapLoad()); + } + + std::optional AsVectorRefElementAccess( + const sem::ValueExpression* expr) { + auto* access = As(expr); + if (!access) { + return std::nullopt; + } + + auto* memory_view = access->Object()->Type()->As(); + if (!memory_view) { + return std::nullopt; + } + + if (!memory_view->StoreType()->Is()) { + return std::nullopt; + } + return tint::Switch( + access, + [&](const sem::Swizzle* s) -> std::optional { + if (auto vec = GetValue(access->Object()->Declaration())) { + return VectorRefElementAccess{ + vec, impl.builder_.Constant(u32(s->Indices()[0]))}; + } + return std::nullopt; + }, + [&](const sem::IndexAccessorExpression* i) + -> std::optional { + if (auto vec = GetValue(access->Object()->Declaration())) { + if (auto idx = GetValue(i->Index()->Declaration())) { + return VectorRefElementAccess{vec, idx}; + } + } + return std::nullopt; + }); + } + + void BeginShortCircuit(const ast::BinaryExpression* expr) { + auto lhs = GetValue(expr->lhs); + if (!lhs) { + return; + } + + const auto* lhs_sem = impl.program_.Sem().GetVal(expr->lhs); + const auto* rhs_sem = impl.program_.Sem().GetVal(expr->rhs); + + const bool is_const_eval = lhs_sem->Stage() <= core::EvaluationStage::kOverride && + rhs_sem->Stage() <= core::EvaluationStage::kOverride; + + auto& b = impl.builder_; + core::ir::If* if_inst = nullptr; + if (is_const_eval) { + if_inst = b.ConstExprIf(lhs); + } else { + if_inst = b.If(lhs); + } + + impl.current_block_->Append(if_inst); + + auto* result = b.InstructionResult(b.ir.Types().bool_()); + if_inst->SetResult(result); + + if (expr->op == core::BinaryOp::kLogicalAnd) { + if_inst->False()->Append(b.ExitIf(if_inst, b.Constant(false))); + PushBlock(if_inst->True()); + } else { + if_inst->True()->Append(b.ExitIf(if_inst, b.Constant(true))); + PushBlock(if_inst->False()); + } + + Bind(expr, result); + } + + void EndShortCircuit(const ast::BinaryExpression* b) { + auto res = GetValue(b); + auto* src = res->As()->Instruction(); + auto* if_ = src->As(); + TINT_ASSERT(if_); + auto rhs = GetValue(b->rhs); + if (!rhs) { + return; + } + impl.current_block_->Append(impl.builder_.ExitIf(if_, rhs)); + PopBlock(); + } + + void Process(const ast::Expression* expr) { + if (EmitConstant(expr)) { + // If this is a value that has been const-eval'd, then no need to traverse + // deeper. + return; + } + + tint::Switch( + expr, // + [&](const ast::BinaryExpression* e) { + if (e->op == core::BinaryOp::kLogicalAnd || + e->op == core::BinaryOp::kLogicalOr) { + tasks.Push([this, e] { EndShortCircuit(e); }); + tasks.Push([this, e] { Process(e->rhs); }); + tasks.Push([this, e] { BeginShortCircuit(e); }); + tasks.Push([this, e] { Process(e->lhs); }); + } else { + tasks.Push([this, e] { EmitBinary(e); }); + tasks.Push([this, e] { Process(e->rhs); }); + tasks.Push([this, e] { Process(e->lhs); }); + } + }, + [&](const ast::IndexAccessorExpression* e) { + tasks.Push([this, e] { EmitAccess(e); }); + tasks.Push([this, e] { Process(e->index); }); + tasks.Push([this, e] { Process(e->object); }); + }, + [&](const ast::MemberAccessorExpression* e) { + tasks.Push([this, e] { EmitAccess(e); }); + tasks.Push([this, e] { Process(e->object); }); + }, + [&](const ast::UnaryOpExpression* e) { + tasks.Push([this, e] { EmitUnary(e); }); + tasks.Push([this, e] { Process(e->expr); }); + }, + [&](const ast::CallExpression* e) { + tasks.Push([this, e] { EmitCall(e); }); + for (auto* arg : tint::Reverse(e->args)) { + tasks.Push([this, arg] { Process(arg); }); + } + }, + [&](const ast::LiteralExpression* e) { EmitLiteral(e); }, + [&](const ast::IdentifierExpression* e) { EmitIdentifier(e); }, // + TINT_ICE_ON_NO_MATCH); + } + }; + + return Emitter(*this).Emit(root); + } + + core::ir::Value* EmitValueExpression(const ast::Expression* root) { + auto res = EmitExpression(root); + if (auto** val = std::get_if(&res)) { + builder_.ir.SetSource(*val, root->source); + return *val; + } + TINT_ICE() << "expression did not resolve to a value"; + } + + void EmitCall(const ast::CallStatement* stmt) { (void)EmitValueExpression(stmt->expr); } + + void EmitVariable(const ast::Variable* var) { + auto* sem = program_.Sem().Get(var); + + return tint::Switch( // + var, + [&](const ast::Var* v) { + auto* ref = sem->Type()->As(); + auto* store_ty = RemapOverrideSizedArrayIfNeeded(ref->StoreType()); + auto* ty = builder_.ir.Types().Get(ref->AddressSpace(), + store_ty, ref->Access()); + + auto* val = builder_.Var(ty); + if (v->initializer) { + auto init = EmitValueExpression(v->initializer); + if (!init) { + return; + } + val->SetInitializer(init); + } + current_block_->Append(val); + + if (auto* gv = sem->As(); gv) { + if (var->HasBindingPoint()) { + val->SetBindingPoint(gv->Attributes().binding_point->group, + gv->Attributes().binding_point->binding); + } + if (var->HasInputAttachmentIndex()) { + val->SetInputAttachmentIndex( + gv->Attributes().input_attachment_index.value()); + } + } + + // Store the declaration so we can get the instruction to store too + scopes_.Set(v->name->symbol, val->Result()); + + // Record the original name and source of the var + builder_.ir.SetName(val, v->name->symbol.Name()); + builder_.ir.SetSource(val, v->source); + }, + [&](const ast::Let* l) { + auto init = EmitValueExpression(l->initializer); + if (!init) { + return; + } + + // If we've emitted a texture or a sampler to the let then we have + // `texture_and_sampler_let` enabled and we want to just strip the let and use the + // originating value. + if (init->Type()->IsAnyOf()) { + scopes_.Set(l->name->symbol, init); + return; + } + + auto* let = current_block_->Append(builder_.Let(l->name->symbol.Name(), init)); + + // Store the results of the initialization + scopes_.Set(l->name->symbol, let->Result()); + builder_.ir.SetSource(let, l->source); + }, + [&](const ast::Override* o) { + auto* o_sem = program_.Sem().Get(o); + auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx); + + auto* override = builder_.Override(ty); + if (o->initializer) { + auto init = EmitValueExpression(o->initializer); + if (!init) { + return; + } + override->SetInitializer(init); + } + current_block_->Append(override); + + TINT_ASSERT(o_sem->Attributes().override_id.has_value()); + override->SetOverrideId(o_sem->Attributes().override_id.value()); + + // Store the declaration so we can get the instruction to store too + scopes_.Set(o->name->symbol, override->Result()); + + // Record the original name and source of the var + builder_.ir.SetName(override, o->name->symbol.Name()); + builder_.ir.SetSource(override, o->source); + }, + [&](const ast::Const*) { + // Skip. This should be handled by const-eval already, so the const will be a + // `core::constant::` value at the usage sites. Can just ignore the `const` variable + // as it should never be used. + }, + TINT_ICE_ON_NO_MATCH); + } + + core::ir::CoreBinary* BinaryOp(core::ir::Value* lhs, core::ir::Value* rhs, core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kAnd: + return builder_.And(lhs, rhs); + case core::BinaryOp::kOr: + return builder_.Or(lhs, rhs); + case core::BinaryOp::kXor: + return builder_.Xor(lhs, rhs); + case core::BinaryOp::kEqual: + return builder_.Equal(lhs, rhs); + case core::BinaryOp::kNotEqual: + return builder_.NotEqual(lhs, rhs); + case core::BinaryOp::kLessThan: + return builder_.LessThan(lhs, rhs); + case core::BinaryOp::kGreaterThan: + return builder_.GreaterThan(lhs, rhs); + case core::BinaryOp::kLessThanEqual: + return builder_.LessThanEqual(lhs, rhs); + case core::BinaryOp::kGreaterThanEqual: + return builder_.GreaterThanEqual(lhs, rhs); + case core::BinaryOp::kShiftLeft: + return builder_.ShiftLeft(lhs, rhs); + case core::BinaryOp::kShiftRight: + return builder_.ShiftRight(lhs, rhs); + case core::BinaryOp::kAdd: + return builder_.Add(lhs, rhs); + case core::BinaryOp::kSubtract: + return builder_.Subtract(lhs, rhs); + case core::BinaryOp::kMultiply: + return builder_.Multiply(lhs, rhs); + case core::BinaryOp::kDivide: + return builder_.Divide(lhs, rhs); + case core::BinaryOp::kModulo: + return builder_.Modulo(lhs, rhs); + case core::BinaryOp::kLogicalAnd: + case core::BinaryOp::kLogicalOr: + TINT_ICE() << "short circuit op should have already been handled"; + } + TINT_UNREACHABLE(); + } + + const core::type::Type* RemapOverrideSizedArrayIfNeeded(const core::type::Type* ty) { + // Check that we have an override-sized array, or a pointer to one. + const auto* ary = ty->UnwrapPtr()->As(); + if (!ary || + !ary->Count() + ->IsAnyOf()) { + return ty->Clone(clone_ctx_.type_ctx); + } + + // If the array has an override count, we need to remap it to a value array count. + core::ir::Value* count = tint::Switch( + ary->Count(), // + [&](const sem::UnnamedOverrideArrayCount* u) { + return EmitValueExpression(u->expr->Declaration()); + }, + [&](const sem::NamedOverrideArrayCount* n) { + return scopes_.Get(n->variable->Declaration()->name->symbol); + }, + TINT_ICE_ON_NO_MATCH); + + auto* ary_count = builder_.ir.Types().Get(count); + const core::type::Type* remapped_ty = builder_.ir.Types().Get( + ary->ElemType()->Clone(clone_ctx_.type_ctx), ary_count, ary->Size()); + + // If the original type was a pointer, wrap the remapped array in a pointer too. + if (auto* ptr = ty->As()) { + remapped_ty = builder_.ir.Types().ptr(ptr->AddressSpace(), remapped_ty, ptr->Access()); + } + + return remapped_ty; + } +}; + +} // namespace + +Result ProgramToIR(const Program& program) { + if (!program.IsValid()) { + return Failure{program.Diagnostics().Str()}; + } + + Impl b(program); + auto r = b.Build(); + if (r != Success) { + diag::List err = std::move(r.Failure().reason); + err.AddNote(Source{}) << "AST:\n" + Program::printer(program); + return Failure{err.Str()}; + } + + return r.Move(); +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h new file mode 100644 index 000000000..0a5ec1ab9 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_PROGRAM_TO_IR_PROGRAM_TO_IR_H_ +#define SRC_TINT_LANG_WGSL_READER_PROGRAM_TO_IR_PROGRAM_TO_IR_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/result.h" + +// Forward Declarations +namespace tint { +class Program; +} // namespace tint + +namespace tint::wgsl::reader { + +/// Builds a WGSL-dialect core::ir::Module from the given Program +/// @param program the Program to use. +/// @returns the WGSL-dialect IR module. +/// +/// @note this assumes the `program.IsValid()`, and has had const-eval done so +/// any abstract values have been calculated and converted into the relevant +/// concrete types. +Result ProgramToIR(const Program& program); + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_PROGRAM_TO_IR_PROGRAM_TO_IR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/reader.cc b/3rdparty/dawn/src/tint/lang/wgsl/reader/reader.cc new file mode 100644 index 000000000..f19044f87 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/reader.cc @@ -0,0 +1,80 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reader/reader.h" + +#include +#include + +#include "src/tint/lang/wgsl/reader/lower/lower.h" +#include "src/tint/lang/wgsl/reader/parser/parser.h" +#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h" +#include "src/tint/lang/wgsl/resolver/resolve.h" + +namespace tint::wgsl::reader { + +Program Parse(const Source::File* file, const Options& options) { + if (DAWN_UNLIKELY(file->content.data.size() > + static_cast(std::numeric_limits::max()))) { + ProgramBuilder b; + b.Diagnostics().AddError(tint::Source{}) << "WGSL source must be 0xffffffff bytes or fewer"; + return Program(std::move(b)); + } + Parser parser(file); + parser.Parse(); + return resolver::Resolve(parser.builder(), options.allowed_features); +} + +Result WgslToIR(const Source::File* file, const Options& options) { + Program program = Parse(file, options); + return ProgramToLoweredIR(program); +} + +Result ProgramToLoweredIR(const Program& program, + InternalCompilerErrorCallback ice_callback) { + TINT_CHECK_RESULT_UNWRAP(ir, ProgramToIR(program)); + ir.ice_callback = ice_callback; + + // Lower from WGSL-dialect to core-dialect + TINT_CHECK_RESULT(Lower(ir)); + + return ir; +} + +bool IsUnsupportedByIR(const ast::Enable* enable) { + for (auto ext : enable->extensions) { + switch (ext->name) { + case tint::wgsl::Extension::kChromiumExperimentalFramebufferFetch: + return true; + default: + break; + } + } + return false; +} + +} // namespace tint::wgsl::reader diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reader/reader.h b/3rdparty/dawn/src/tint/lang/wgsl/reader/reader.h new file mode 100644 index 000000000..682441c94 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reader/reader.h @@ -0,0 +1,75 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_READER_READER_H_ +#define SRC_TINT_LANG_WGSL_READER_READER_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/reader/options.h" +#include "src/tint/utils/result.h" + +namespace tint::ast { +class Enable; +} // namespace tint::ast + +namespace tint::wgsl::reader { + +/// Parses the WGSL source, returning the parsed program. +/// If the source fails to parse then the returned +/// `program.Diagnostics.ContainsErrors()` will be true, and the +/// `program.Diagnostics()` will describe the error. +/// @param file the source file +/// @param options the configuration options to use when parsing WGSL +/// @returns the parsed program +Program Parse(const Source::File* file, const Options& options = {}); + +/// Parse a WGSL program from source, and return an IR module. +/// @param file the input WGSL file +/// @param options the configuration options to use when parsing WGSL +/// @returns the resulting IR module, or failure +Result WgslToIR(const Source::File* file, const Options& options = {}); + +/// Builds a core-dialect core::ir::Module from the given Program +/// @param program the Program to use. +/// @param ice_callback the callback to use for any ICE produced while processing the IR module +/// @returns the core-dialect IR module. +/// +/// @note this assumes the `program.IsValid()`, and has had const-eval done so +/// any abstract values have been calculated and converted into the relevant +/// concrete types. +Result ProgramToLoweredIR( + const Program& program, + InternalCompilerErrorCallback ice_callback = std::nullopt); + +/// Allows for checking if an extension is currently supported/unsupported by IR +/// before trying to convert to it. +bool IsUnsupportedByIR(const ast::Enable* enable); + +} // namespace tint::wgsl::reader + +#endif // SRC_TINT_LANG_WGSL_READER_READER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reserved_words.cc b/3rdparty/dawn/src/tint/lang/wgsl/reserved_words.cc new file mode 100644 index 000000000..fce67d1d5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reserved_words.cc @@ -0,0 +1,95 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/reserved_words.h" + +#include "src/tint/lang/core/enums.h" + +namespace tint::wgsl { + +bool IsReserved(std::string_view s) { + return s == "NULL" || s == "Self" || s == "abstract" || s == "active" || s == "alignas" || + s == "alignof" || s == "as" || s == "asm" || s == "asm_fragment" || s == "async" || + s == "attribute" || s == "auto" || s == "await" || s == "become" || s == "cast" || + s == "catch" || s == "class" || s == "co_await" || s == "co_return" || s == "co_yield" || + s == "coherent" || s == "column_major" || s == "common" || s == "compile" || + s == "compile_fragment" || s == "concept" || s == "const_cast" || s == "consteval" || + s == "constexpr" || s == "constinit" || s == "crate" || s == "debugger" || + s == "decltype" || s == "delete" || s == "demote" || s == "demote_to_helper" || + s == "do" || s == "dynamic_cast" || s == "enum" || s == "explicit" || s == "export" || + s == "extends" || s == "extern" || s == "external" || s == "fallthrough" || + s == "filter" || s == "final" || s == "finally" || s == "friend" || s == "from" || + s == "fxgroup" || s == "get" || s == "goto" || s == "groupshared" || s == "highp" || + s == "impl" || s == "implements" || s == "import" || s == "inline" || + s == "instanceof" || s == "interface" || s == "layout" || s == "lowp" || s == "macro" || + s == "macro_rules" || s == "match" || s == "mediump" || s == "meta" || s == "mod" || + s == "module" || s == "move" || s == "mut" || s == "mutable" || s == "namespace" || + s == "new" || s == "nil" || s == "noexcept" || s == "noinline" || + s == "nointerpolation" || s == "non_coherent" || s == "noncoherent" || + s == "noperspective" || s == "null" || s == "nullptr" || s == "of" || s == "operator" || + s == "package" || s == "packoffset" || s == "partition" || s == "pass" || s == "patch" || + s == "pixelfragment" || s == "precise" || s == "precision" || s == "premerge" || + s == "priv" || s == "protected" || s == "pub" || s == "public" || s == "readonly" || + s == "ref" || s == "regardless" || s == "register" || s == "reinterpret_cast" || + s == "require" || s == "resource" || s == "restrict" || s == "self" || s == "set" || + s == "shared" || s == "sizeof" || s == "smooth" || s == "snorm" || s == "static" || + s == "static_assert" || s == "static_cast" || s == "std" || s == "subroutine" || + s == "super" || s == "target" || s == "template" || s == "this" || s == "thread_local" || + s == "throw" || s == "trait" || s == "try" || s == "type" || s == "typedef" || + s == "typeid" || s == "typename" || s == "typeof" || s == "union" || s == "unless" || + s == "unorm" || s == "unsafe" || s == "unsized" || s == "use" || s == "using" || + s == "varying" || s == "virtual" || s == "volatile" || s == "wgsl" || s == "where" || + s == "with" || s == "writeonly" || s == "yield"; +} + +bool IsKeyword(std::string_view s) { + return s == "alias" || s == "break" || s == "case" || s == "const" || s == "const_assert" || + s == "continue" || s == "continuing" || s == "default" || s == "diagnostic" || + s == "discard" || s == "else" || s == "enable" || s == "false" || s == "fn" || + s == "for" || s == "if" || s == "let" || s == "loop" || s == "override" || + s == "requires" || s == "return" || s == "struct" || s == "switch" || s == "true" || + s == "var" || s == "while"; +} + +bool IsEnumName(std::string_view s) { + if (core::ParseAccess(s) != core::Access::kUndefined) { + return true; + } + if (core::ParseAddressSpace(s) != core::AddressSpace::kUndefined) { + return true; + } + if (core::ParseTexelFormat(s) != core::TexelFormat::kUndefined) { + return true; + } + return false; +} + +bool IsTypeName(std::string_view s) { + return s == "void" || core::ParseBuiltinType(s) != core::BuiltinType::kUndefined; +} + +} // namespace tint::wgsl diff --git a/3rdparty/dawn/src/tint/lang/wgsl/reserved_words.h b/3rdparty/dawn/src/tint/lang/wgsl/reserved_words.h new file mode 100644 index 000000000..a8d4d5b92 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/reserved_words.h @@ -0,0 +1,52 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESERVED_WORDS_H_ +#define SRC_TINT_LANG_WGSL_RESERVED_WORDS_H_ + +#include + +namespace tint::wgsl { + +// https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords +bool IsReserved(std::string_view s); + +/// @param str the string to check +/// @returns true if `str` is a keyword in WGSL +bool IsKeyword(std::string_view str); + +/// @param str the string to check +/// @returns true if `str` is a WGSL enum name. +bool IsEnumName(std::string_view str); + +/// @param str the string to check +/// @returns true if `str` is a WGSL type name. +bool IsTypeName(std::string_view str); + +} // namespace tint::wgsl + +#endif // SRC_TINT_LANG_WGSL_RESERVED_WORDS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.cc new file mode 100644 index 000000000..0400b512a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.cc @@ -0,0 +1,856 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/dependency_graph.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/ast/alias.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/blend_src_attribute.h" +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/break_if_statement.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/color_attribute.h" +#include "src/tint/lang/wgsl/ast/compound_assignment_statement.h" +#include "src/tint/lang/wgsl/ast/const.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/diagnostic_attribute.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/invariant_attribute.h" +#include "src/tint/lang/wgsl/ast/let.h" +#include "src/tint/lang/wgsl/ast/location_attribute.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/must_use_attribute.h" +#include "src/tint/lang/wgsl/ast/override.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/stage_attribute.h" +#include "src/tint/lang/wgsl/ast/struct.h" +#include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h" +#include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h" +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/ast/traverse_expressions.h" +#include "src/tint/lang/wgsl/ast/var.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/while_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/sem/builtin_fn.h" +#include "src/tint/utils/containers/map.h" +#include "src/tint/utils/containers/scope_stack.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/macros/scoped_assignment.h" +#include "src/tint/utils/memory/block_allocator.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/string_stream.h" + +#define TINT_DUMP_DEPENDENCY_GRAPH 0 + +namespace tint::resolver { +namespace { + +// Forward declaration +struct Global; + +/// Dependency describes how one global depends on another global +struct DependencyInfo { + /// The source of the symbol that forms the dependency + Source source; +}; + +/// DependencyEdge describes the two Globals used to define a dependency +/// relationship. +struct DependencyEdge { + /// The Global that depends on #to + const Global* from; + /// The Global that is depended on by #from + const Global* to; + + /// @returns the hash code of the DependencyEdge + tint::HashCode HashCode() const { return Hash(from, to); } + + /// Equality operator + bool operator==(const DependencyEdge& rhs) const { return from == rhs.from && to == rhs.to; } +}; + +/// A map of DependencyEdge to DependencyInfo +using DependencyEdges = Hashmap; + +/// Global describes a module-scope variable, type or function. +struct Global { + explicit Global(const ast::Node* n) : node(n) {} + + /// The declaration ast::Node + const ast::Node* node; + /// A list of dependencies that this global depends on + Vector deps; +}; + +/// A map of global name to Global +using GlobalMap = Hashmap; + +/// @returns a new error diagnostic with the given source. +diag::Diagnostic& AddError(diag::List& diagnostics, const Source& source) { + return diagnostics.AddError(source); +} + +/// @returns a new note diagnostic with the given source. +diag::Diagnostic& AddNote(diag::List& diagnostics, const Source& source) { + return diagnostics.AddNote(source); +} + +/// DependencyScanner is used to traverse a module to build the list of +/// global-to-global dependencies. +class DependencyScanner { + public: + /// Constructor + /// @param globals_by_name map of global symbol to Global pointer + /// @param diagnostics diagnostic messages, appended with any errors found + /// @param graph the dependency graph to populate with resolved symbols + /// @param edges the map of globals-to-global dependency edges, which will + /// be populated by calls to Scan() + DependencyScanner(const GlobalMap& globals_by_name, + diag::List& diagnostics, + DependencyGraph& graph, + DependencyEdges& edges) + : globals_(globals_by_name), + diagnostics_(diagnostics), + graph_(graph), + dependency_edges_(edges) { + // Register all the globals at global-scope + for (auto& it : globals_by_name) { + scope_stack_.Set(it.key, it.value->node); + } + } + + /// Walks the global declarations, resolving symbols, and determining the + /// dependencies of each global. + void Scan(Global* global) { + TINT_SCOPED_ASSIGNMENT(current_global_, global); + Switch( + global->node, + [&](const ast::Struct* str) { + Declare(str->name->symbol, str); + for (auto* member : str->members) { + TraverseAttributes(member->attributes); + TraverseExpression(member->type); + } + }, + [&](const ast::Alias* alias) { + Declare(alias->name->symbol, alias); + TraverseExpression(alias->type); + }, + [&](const ast::Function* func) { + Declare(func->name->symbol, func); + TraverseFunction(func); + }, + [&](const ast::Variable* v) { + Declare(v->name->symbol, v); + TraverseVariable(v); + }, + [&](const ast::DiagnosticDirective*) { + // Diagnostic directives do not affect the dependency graph. + }, + [&](const ast::Enable*) { + // Enable directives do not affect the dependency graph. + }, + [&](const ast::Requires*) { + // Requires directives do not affect the dependency graph. + }, + [&](const ast::ConstAssert* assertion) { + TraverseExpression(assertion->condition); + }, // + TINT_ICE_ON_NO_MATCH); + } + + private: + /// Traverses the variable, performing symbol resolution. + void TraverseVariable(const ast::Variable* v) { + if (auto* var = v->As()) { + TraverseExpression(var->declared_address_space); + TraverseExpression(var->declared_access); + } + TraverseExpression(v->type); + TraverseAttributes(v->attributes); + TraverseExpression(v->initializer); + } + + /// Traverses the function, performing symbol resolution and determining global dependencies. + void TraverseFunction(const ast::Function* func) { + TraverseAttributes(func->attributes); + TraverseAttributes(func->return_type_attributes); + // Perform symbol resolution on all the parameter types before registering + // the parameters themselves. This allows the case of declaring a parameter + // with the same identifier as its type. + for (auto* param : func->params) { + TraverseAttributes(param->attributes); + TraverseExpression(param->type); + } + // Resolve the return type + TraverseExpression(func->return_type); + + // Push the scope stack for the parameters and function body. + scope_stack_.Push(); + TINT_DEFER(scope_stack_.Pop()); + + for (auto* param : func->params) { + if (auto shadows = scope_stack_.Get(param->name->symbol)) { + graph_.shadows.Add(param, shadows); + } + Declare(param->name->symbol, param); + } + if (func->body) { + TraverseStatements(func->body->statements); + } + } + + /// Traverses the statements, performing symbol resolution and determining + /// global dependencies. + void TraverseStatements(VectorRef stmts) { + for (auto* s : stmts) { + TraverseStatement(s); + } + } + + /// Traverses the statement, performing symbol resolution and determining + /// global dependencies. + void TraverseStatement(const ast::Statement* stmt) { + if (!stmt) { + return; + } + Switch( + stmt, // + [&](const ast::AssignmentStatement* a) { + TraverseExpression(a->lhs); + TraverseExpression(a->rhs); + }, + [&](const ast::BlockStatement* b) { + scope_stack_.Push(); + TINT_DEFER(scope_stack_.Pop()); + TraverseStatements(b->statements); + }, + [&](const ast::BreakIfStatement* b) { TraverseExpression(b->condition); }, + [&](const ast::CallStatement* r) { TraverseExpression(r->expr); }, + [&](const ast::CompoundAssignmentStatement* a) { + TraverseExpression(a->lhs); + TraverseExpression(a->rhs); + }, + [&](const ast::ForLoopStatement* l) { + scope_stack_.Push(); + TINT_DEFER(scope_stack_.Pop()); + TraverseStatement(l->initializer); + TraverseExpression(l->condition); + TraverseStatement(l->continuing); + TraverseStatement(l->body); + }, + [&](const ast::IncrementDecrementStatement* i) { TraverseExpression(i->lhs); }, + [&](const ast::LoopStatement* l) { + scope_stack_.Push(); + TINT_DEFER(scope_stack_.Pop()); + TraverseStatements(l->body->statements); + TraverseStatement(l->continuing); + }, + [&](const ast::IfStatement* i) { + TraverseExpression(i->condition); + TraverseStatement(i->body); + if (i->else_statement) { + TraverseStatement(i->else_statement); + } + }, + [&](const ast::ReturnStatement* r) { TraverseExpression(r->value); }, + [&](const ast::SwitchStatement* s) { + TraverseExpression(s->condition); + for (auto* c : s->body) { + for (auto* sel : c->selectors) { + TraverseExpression(sel->expr); + } + TraverseStatement(c->body); + } + }, + [&](const ast::VariableDeclStatement* v) { + if (auto* shadows = scope_stack_.Get(v->variable->name->symbol)) { + graph_.shadows.Add(v->variable, shadows); + } + TraverseVariable(v->variable); + Declare(v->variable->name->symbol, v->variable); + }, + [&](const ast::WhileStatement* w) { + scope_stack_.Push(); + TINT_DEFER(scope_stack_.Pop()); + TraverseExpression(w->condition); + TraverseStatement(w->body); + }, + [&](const ast::ConstAssert* assertion) { TraverseExpression(assertion->condition); }, + [&](const ast::BreakStatement*) {}, // + [&](const ast::ContinueStatement*) {}, // + [&](const ast::DiscardStatement*) {}, // + TINT_ICE_ON_NO_MATCH); + } + + /// Adds the symbol definition to the current scope, raising an error if two + /// symbols collide within the same scope. + void Declare(Symbol symbol, const ast::Node* node) { + auto* old = scope_stack_.Set(symbol, node); + if (old != nullptr && node != old) { + auto name = symbol.Name(); + AddError(diagnostics_, node->source) << "redeclaration of '" << name << "'"; + AddNote(diagnostics_, old->source) << "'" << name << "' previously declared here"; + } + } + + /// Traverses the expression @p root_expr, performing symbol resolution and determining global + /// dependencies. + void TraverseExpression(const ast::Expression* root_expr) { + if (!root_expr) { + return; + } + + Vector pending{root_expr}; + while (!pending.IsEmpty()) { + auto* next = pending.Pop(); + bool ok = ast::TraverseExpressions(next, [&](const ast::IdentifierExpression* e) { + AddDependency(e->identifier, e->identifier->symbol); + return ast::TraverseAction::Descend; + }); + if (!ok) { + AddError(diagnostics_, next->source) << "TraverseExpressions failed"; + return; + } + } + } + + /// Traverses the attribute list, performing symbol resolution and + /// determining global dependencies. + void TraverseAttributes(VectorRef attrs) { + for (auto* attr : attrs) { + TraverseAttribute(attr); + } + } + + /// Traverses the attribute, performing symbol resolution and determining + /// global dependencies. + void TraverseAttribute(const ast::Attribute* attr) { + Switch( + attr, // + [&](const ast::BindingAttribute* binding) { TraverseExpression(binding->expr); }, + [&](const ast::ColorAttribute* color) { TraverseExpression(color->expr); }, + [&](const ast::GroupAttribute* group) { TraverseExpression(group->expr); }, + [&](const ast::IdAttribute* id) { TraverseExpression(id->expr); }, + [&](const ast::InputAttachmentIndexAttribute* idx) { TraverseExpression(idx->expr); }, + [&](const ast::BlendSrcAttribute* index) { TraverseExpression(index->expr); }, + [&](const ast::LocationAttribute* loc) { TraverseExpression(loc->expr); }, + [&](const ast::StructMemberAlignAttribute* align) { TraverseExpression(align->expr); }, + [&](const ast::StructMemberSizeAttribute* size) { TraverseExpression(size->expr); }, + [&](const ast::WorkgroupAttribute* wg) { + TraverseExpression(wg->x); + TraverseExpression(wg->y); + TraverseExpression(wg->z); + }, + [&](const ast::SubgroupSizeAttribute* sg) { TraverseExpression(sg->subgroup_size); }, + [&](Default) { + if (!attr->IsAnyOf()) { + TINT_ICE() << "unhandled attribute type: " << attr->TypeInfo().name; + } + }); + } + + /// The type of builtin that a symbol could represent. + enum class BuiltinType { + /// No builtin matched + kNone = 0, + /// Builtin function + kFunction, + /// Builtin + kBuiltin, + /// Address space + kAddressSpace, + /// Texel format + kTexelFormat, + /// Access + kAccess, + }; + + /// BuiltinInfo stores information about the builtin that a symbol represents. + struct BuiltinInfo { + /// @returns the builtin value + template + T Value() const { + return std::get(value); + } + + BuiltinType type = BuiltinType::kNone; + std::variant + value = {}; + }; + + /// Get the builtin info for a given symbol. + /// @param symbol the symbol + /// @returns the builtin info + DependencyScanner::BuiltinInfo GetBuiltinInfo(Symbol symbol) { + return builtin_info_map.GetOrAdd(symbol, [&] { + if (auto builtin_fn = wgsl::ParseBuiltinFn(symbol.NameView()); + builtin_fn != wgsl::BuiltinFn::kNone) { + return BuiltinInfo{BuiltinType::kFunction, builtin_fn}; + } + if (auto builtin_ty = core::ParseBuiltinType(symbol.NameView()); + builtin_ty != core::BuiltinType::kUndefined) { + return BuiltinInfo{BuiltinType::kBuiltin, builtin_ty}; + } + if (auto addr = core::ParseAddressSpace(symbol.NameView()); + addr != core::AddressSpace::kUndefined) { + return BuiltinInfo{BuiltinType::kAddressSpace, addr}; + } + if (auto fmt = core::ParseTexelFormat(symbol.NameView()); + fmt != core::TexelFormat::kUndefined) { + return BuiltinInfo{BuiltinType::kTexelFormat, fmt}; + } + if (auto access = core::ParseAccess(symbol.NameView()); + access != core::Access::kUndefined) { + return BuiltinInfo{BuiltinType::kAccess, access}; + } + return BuiltinInfo{}; + }); + } + + /// Adds the dependency from @p from to @p to, erroring if @p to cannot be resolved. + void AddDependency(const ast::Identifier* from, Symbol to) { + auto* resolved = scope_stack_.Get(to); + if (!resolved) { + auto builtin_info = GetBuiltinInfo(to); + switch (builtin_info.type) { + case BuiltinType::kNone: + graph_.resolved_identifiers.Add( + from, ResolvedIdentifier::UnresolvedIdentifier{to.Name()}); + break; + case BuiltinType::kFunction: + graph_.resolved_identifiers.Add( + from, ResolvedIdentifier(builtin_info.Value())); + break; + case BuiltinType::kBuiltin: + graph_.resolved_identifiers.Add( + from, ResolvedIdentifier(builtin_info.Value())); + break; + case BuiltinType::kAddressSpace: + graph_.resolved_identifiers.Add( + from, ResolvedIdentifier(builtin_info.Value())); + break; + case BuiltinType::kTexelFormat: + graph_.resolved_identifiers.Add( + from, ResolvedIdentifier(builtin_info.Value())); + break; + case BuiltinType::kAccess: + graph_.resolved_identifiers.Add( + from, ResolvedIdentifier(builtin_info.Value())); + break; + } + return; + } + + if (auto global = globals_.Get(to); global && (*global)->node == resolved) { + if (dependency_edges_.Add(DependencyEdge{current_global_, *global}, + DependencyInfo{from->source})) { + current_global_->deps.Push(*global); + } + } + + graph_.resolved_identifiers.Add(from, ResolvedIdentifier(resolved)); + } + + using VariableMap = Hashmap; + const GlobalMap& globals_; + diag::List& diagnostics_; + DependencyGraph& graph_; + DependencyEdges& dependency_edges_; + + ScopeStack scope_stack_; + Global* current_global_ = nullptr; + + Hashmap builtin_info_map; +}; + +/// The global dependency analysis system +struct DependencyAnalysis { + public: + /// Constructor + DependencyAnalysis(diag::List& diagnostics, DependencyGraph& graph) + : diagnostics_(diagnostics), graph_(graph) {} + + /// Performs global dependency analysis on the module, emitting any errors to + /// #diagnostics. + /// @returns true if analysis found no errors, otherwise false. + bool Run(const ast::Module& module) { + // Reserve container memory + graph_.resolved_identifiers.Reserve(module.GlobalDeclarations().Length()); + sorted_.Reserve(module.GlobalDeclarations().Length()); + + // Collect all the named globals from the AST module + GatherGlobals(module); + + // Traverse the named globals to build the dependency graph + DetermineDependencies(); + + // Sort the globals into dependency order + SortGlobals(); + + // Dump the dependency graph if TINT_DUMP_DEPENDENCY_GRAPH is non-zero + DumpDependencyGraph(); + + graph_.ordered_globals = sorted_.Release(); + + return !diagnostics_.ContainsErrors(); + } + + private: + /// @param node the ast::Node of the global declaration + /// @returns the symbol of the global declaration node + /// @note will raise an ICE if the node is not a type, function or variable + /// declaration + Symbol SymbolOf(const ast::Node* node) const { + return Switch( + node, // + [&](const ast::TypeDecl* td) { return td->name->symbol; }, + [&](const ast::Function* func) { return func->name->symbol; }, + [&](const ast::Variable* var) { return var->name->symbol; }, + [&](const ast::DiagnosticDirective*) { return Symbol(); }, + [&](const ast::Enable*) { return Symbol(); }, + [&](const ast::Requires*) { return Symbol(); }, + [&](const ast::ConstAssert*) { return Symbol(); }, // + TINT_ICE_ON_NO_MATCH); + } + + /// @param node the ast::Node of the global declaration + /// @returns the name of the global declaration node + /// @note will raise an ICE if the node is not a type, function or variable + /// declaration + std::string NameOf(const ast::Node* node) const { return SymbolOf(node).Name(); } + + /// @param node the ast::Node of the global declaration + /// @returns a string representation of the global declaration kind + /// @note will raise an ICE if the node is not a type, function or variable + /// declaration + std::string KindOf(const ast::Node* node) { + return Switch( + node, // + [&](const ast::Struct*) { return "struct"; }, // + [&](const ast::Alias*) { return "alias"; }, // + [&](const ast::Function*) { return "function"; }, // + [&](const ast::Variable* v) { return v->Kind(); }, // + [&](const ast::ConstAssert*) { return "const_assert"; }, // + TINT_ICE_ON_NO_MATCH); + } + + /// Traverses `module`, collecting all the global declarations and populating + /// the #globals and #declaration_order fields. + void GatherGlobals(const ast::Module& module) { + for (auto* node : module.GlobalDeclarations()) { + auto* global = allocator_.Create(node); + if (auto symbol = SymbolOf(node); symbol.IsValid()) { + globals_.Add(symbol, global); + } + declaration_order_.Push(global); + } + } + + /// Walks the global declarations, determining the dependencies of each global + /// and adding these to each global's Global::deps field. + void DetermineDependencies() { + DependencyScanner scanner(globals_, diagnostics_, graph_, dependency_edges_); + for (auto* global : declaration_order_) { + scanner.Scan(global); + } + } + + /// Performs a depth-first traversal of `root`'s dependencies, calling `enter` + /// as the function decends into each dependency and `exit` when bubbling back + /// up towards the root. + /// @param enter is a function with the signature: `bool(Global*)`. The + /// `enter` function returns true if TraverseDependencies() should traverse + /// the dependency, otherwise it will be skipped. + /// @param exit is a function with the signature: `void(Global*)`. The `exit` + /// function is only called if the corresponding `enter` call returned true. + template + void TraverseDependencies(const Global* root, ENTER&& enter, EXIT&& exit) { + // Entry is a single entry in the traversal stack. Entry points to a + // dep_idx'th dependency of Entry::global. + struct Entry { + const Global* global; // The parent global + size_t dep_idx; // The dependency index in `global->deps` + }; + + if (!enter(root)) { + return; + } + + Vector stack{Entry{root, 0}}; + while (true) { + auto& entry = stack.Back(); + // Have we exhausted the dependencies of entry.global? + if (entry.dep_idx < entry.global->deps.Length()) { + // No, there's more dependencies to traverse. + auto& dep = entry.global->deps[entry.dep_idx]; + // Does the caller want to enter this dependency? + if (enter(dep)) { // Yes. + stack.Push(Entry{dep, 0}); // Enter the dependency. + } else { + entry.dep_idx++; // No. Skip this node. + } + } else { + // Yes. Time to back up. + // Exit this global, pop the stack, and if there's another parent node, + // increment its dependency index, and loop again. + exit(entry.global); + stack.Pop(); + if (stack.IsEmpty()) { + return; // All done. + } + stack.Back().dep_idx++; + } + } + } + + /// SortGlobals sorts the globals into dependency order, erroring if cyclic + /// dependencies are found. The sorted dependencies are assigned to #sorted. + void SortGlobals() { + if (diagnostics_.ContainsErrors()) { + return; // This code assumes there are no undeclared identifiers. + } + + // Make sure all directives go before any other global declarations. + for (auto* global : declaration_order_) { + if (global->node->IsAnyOf()) { + sorted_.Add(global->node); + } + } + + for (auto* global : declaration_order_) { + if (global->node->IsAnyOf()) { + // Skip directives here, as they are already added. + continue; + } + UniqueVector stack; + TraverseDependencies( + global, + [&](const Global* g) { // Enter + if (!stack.Add(g)) { + CyclicDependencyFound(g, stack.Release()); + return false; + } + if (sorted_.Contains(g->node)) { + // Visited this global already. + // stack was pushed, but exit() will not be called when we return + // false, so pop here. + stack.Pop(); + return false; + } + return true; + }, + [&](const Global* g) { // Exit. Only called if Enter returned true. + sorted_.Add(g->node); + stack.Pop(); + }); + + sorted_.Add(global->node); + + // Each stack.push() must have a corresponding stack.pop_back(). + TINT_ASSERT(stack.IsEmpty()) + << "stack not empty after returning from TraverseDependencies()"; + } + } + + /// DepInfoFor() looks up the global dependency information for the dependency + /// of global `from` depending on `to`. + /// @note will raise an ICE if the edge is not found. + DependencyInfo DepInfoFor(const Global* from, const Global* to) const { + auto info = dependency_edges_.Get(DependencyEdge{from, to}); + if (DAWN_LIKELY(info)) { + return *info; + } + TINT_ICE() << "failed to find dependency info for edge: '" << NameOf(from->node) << "' -> '" + << NameOf(to->node) << "'"; + } + + /// CyclicDependencyFound() emits an error diagnostic for a cyclic dependency. + /// @param root is the global that starts the cyclic dependency, which must be + /// found in `stack`. + /// @param stack is the global dependency stack that contains a loop. + void CyclicDependencyFound(const Global* root, VectorRef stack) { + auto& err = AddError(diagnostics_, root->node->source); + err << "cyclic dependency found: "; + constexpr size_t kLoopNotStarted = ~0u; + size_t loop_start = kLoopNotStarted; + for (size_t i = 0; i < stack.Length(); i++) { + auto* e = stack[i]; + if (loop_start == kLoopNotStarted && e == root) { + loop_start = i; + } + if (loop_start != kLoopNotStarted) { + err << "'" << NameOf(e->node) << "' -> "; + } + } + err << "'" << NameOf(root->node) << "'"; + + for (size_t i = loop_start; i < stack.Length(); i++) { + auto* from = stack[i]; + auto* to = (i + 1 < stack.Length()) ? stack[i + 1] : stack[loop_start]; + auto info = DepInfoFor(from, to); + AddNote(diagnostics_, info.source) + << KindOf(from->node) + " '" << NameOf(from->node) << "' references " + << KindOf(to->node) << " '" << NameOf(to->node) << "' here"; + } + } + + void DumpDependencyGraph() { +#if TINT_DUMP_DEPENDENCY_GRAPH == 0 + if ((true)) { + return; + } +#endif // TINT_DUMP_DEPENDENCY_GRAPH + printf("=========================\n"); + printf("------ declaration ------ \n"); + for (auto* global : declaration_order_) { + printf("%s\n", NameOf(global->node).c_str()); + } + printf("------ dependencies ------ \n"); + for (auto* node : sorted_) { + auto symbol = SymbolOf(node); + auto* global = *globals_.Get(symbol); + printf("%s depends on:\n", symbol.Name().c_str()); + for (auto* dep : global->deps) { + printf(" %s\n", NameOf(dep->node).c_str()); + } + } + printf("=========================\n"); + } + + /// Program diagnostics + diag::List& diagnostics_; + + /// The resulting dependency graph + DependencyGraph& graph_; + + /// Allocator of Globals + BlockAllocator allocator_; + + /// Global map, keyed by name. Populated by GatherGlobals(). + GlobalMap globals_; + + /// Map of DependencyEdge to DependencyInfo. Populated by DetermineDependencies(). + DependencyEdges dependency_edges_; + + /// Globals in declaration order. Populated by GatherGlobals(). + Vector declaration_order_; + + /// Globals in sorted dependency order. Populated by SortGlobals(). + UniqueVector sorted_; +}; + +} // namespace + +DependencyGraph::DependencyGraph() = default; +DependencyGraph::DependencyGraph(DependencyGraph&&) = default; +DependencyGraph::~DependencyGraph() = default; + +bool DependencyGraph::Build(const ast::Module& module, + diag::List& diagnostics, + DependencyGraph& output) { + DependencyAnalysis da{diagnostics, output}; + return da.Run(module); +} + +std::string ResolvedIdentifier::String() const { + if (auto* node = Node()) { + return Switch( + node, + [&](const ast::TypeDecl* n) { // + return "type '" + n->name->symbol.Name() + "'"; + }, + [&](const ast::Var* n) { // + return "var '" + n->name->symbol.Name() + "'"; + }, + [&](const ast::Let* n) { // + return "let '" + n->name->symbol.Name() + "'"; + }, + [&](const ast::Const* n) { // + return "const '" + n->name->symbol.Name() + "'"; + }, + [&](const ast::Override* n) { // + return "override '" + n->name->symbol.Name() + "'"; + }, + [&](const ast::Function* n) { // + return "function '" + n->name->symbol.Name() + "'"; + }, + [&](const ast::Parameter* n) { // + return "parameter '" + n->name->symbol.Name() + "'"; + }, // + TINT_ICE_ON_NO_MATCH); + } + if (auto builtin_fn = BuiltinFn(); builtin_fn != wgsl::BuiltinFn::kNone) { + return "builtin function '" + tint::ToString(builtin_fn) + "'"; + } + if (auto builtin_ty = BuiltinType(); builtin_ty != core::BuiltinType::kUndefined) { + return "builtin type '" + tint::ToString(builtin_ty) + "'"; + } + if (auto access = Access(); access != core::Access::kUndefined) { + return "access '" + tint::ToString(access) + "'"; + } + if (auto addr = AddressSpace(); addr != core::AddressSpace::kUndefined) { + return "address space '" + tint::ToString(addr) + "'"; + } + if (auto fmt = TexelFormat(); fmt != core::TexelFormat::kUndefined) { + return "texel format '" + tint::ToString(fmt) + "'"; + } + if (auto* unresolved = Unresolved()) { + return "unresolved identifier '" + unresolved->name + "'"; + } + + TINT_UNREACHABLE() << "unhandled ResolvedIdentifier"; +} + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.h new file mode 100644 index 000000000..fb9220334 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/dependency_graph.h @@ -0,0 +1,191 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_DEPENDENCY_GRAPH_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_DEPENDENCY_GRAPH_H_ + +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/ast/module.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/diagnostic/diagnostic.h" + +namespace tint::resolver { + +/// ResolvedIdentifier holds the resolution of an ast::Identifier. +/// Can hold one of: +/// - UnresolvedIdentifier +/// - const ast::TypeDecl* (as const ast::Node*) +/// - const ast::Variable* (as const ast::Node*) +/// - const ast::Function* (as const ast::Node*) +/// - wgsl::BuiltinFn +/// - core::Access +/// - core::AddressSpace +/// - core::BuiltinType +/// - core::TexelFormat +class ResolvedIdentifier { + public: + /// UnresolvedIdentifier is the variant value used to represent an unresolved identifier + struct UnresolvedIdentifier { + /// Name of the unresolved identifier + std::string name; + }; + + /// Constructor + /// @param value the resolved identifier value + template + ResolvedIdentifier(T value) : value_(value) {} // NOLINT(runtime/explicit) + + /// @return the UnresolvedIdentifier if the identifier was not resolved + const UnresolvedIdentifier* Unresolved() const { + if (auto n = std::get_if(&value_)) { + return n; + } + return nullptr; + } + + /// @return the node pointer if the ResolvedIdentifier holds an AST node, otherwise nullptr + const ast::Node* Node() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return nullptr; + } + + /// @return the builtin function if the ResolvedIdentifier holds wgsl::BuiltinFn, otherwise + /// wgsl::BuiltinFn::kNone + wgsl::BuiltinFn BuiltinFn() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return wgsl::BuiltinFn::kNone; + } + + /// @return the access if the ResolvedIdentifier holds core::Access, otherwise + /// core::Access::kUndefined + core::Access Access() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return core::Access::kUndefined; + } + + /// @return the address space if the ResolvedIdentifier holds core::AddressSpace, otherwise + /// core::AddressSpace::kUndefined + core::AddressSpace AddressSpace() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return core::AddressSpace::kUndefined; + } + + /// @return the builtin type if the ResolvedIdentifier holds core::BuiltinType, otherwise + /// core::BuiltinType::kUndefined + core::BuiltinType BuiltinType() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return core::BuiltinType::kUndefined; + } + + /// @return the texel format if the ResolvedIdentifier holds type::TexelFormat, otherwise + /// type::TexelFormat::kUndefined + core::TexelFormat TexelFormat() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return core::TexelFormat::kUndefined; + } + + /// @param value the value to compare the ResolvedIdentifier to + /// @return true if the ResolvedIdentifier is equal to @p value + template + bool operator==(const T& value) const { + if (auto n = std::get_if(&value_)) { + return *n == value; + } + return false; + } + + /// @param other the other value to compare to this + /// @return true if this ResolvedIdentifier and @p other are not equal + template + bool operator!=(const T& other) const { + return !(*this == other); + } + + /// @return a description of the resolved symbol + std::string String() const; + + private: + std::variant + value_; +}; + +/// DependencyGraph holds information about module-scope declaration dependency +/// analysis and symbol resolutions. +struct DependencyGraph { + /// Constructor + DependencyGraph(); + /// Move-constructor + DependencyGraph(DependencyGraph&&); + /// Destructor + ~DependencyGraph(); + + /// Build() performs symbol resolution and dependency analysis on `module`, + /// populating `output` with the resulting dependency graph. + /// @param module the AST module to analyse + /// @param diagnostics the diagnostic list to populate with errors / warnings + /// @param output the resulting DependencyGraph + /// @returns true on success, false on error + static bool Build(const ast::Module& module, diag::List& diagnostics, DependencyGraph& output); + + /// All globals in dependency-sorted order. + Vector ordered_globals; + + /// Map of ast::Identifier to a ResolvedIdentifier + Hashmap resolved_identifiers; + + /// Map of ast::Variable to a type, function, or variable that is shadowed by + /// the variable key. A declaration (X) shadows another (Y) if X and Y use + /// the same symbol, and X is declared in a sub-scope of the scope that + /// declares Y. + Hashmap shadows; +}; + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_DEPENDENCY_GRAPH_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.cc new file mode 100644 index 000000000..72113d696 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.cc @@ -0,0 +1,63 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/incomplete_type.h" + +TINT_INSTANTIATE_TYPEINFO(tint::resolver::IncompleteType); + +namespace tint::resolver { + +IncompleteType::IncompleteType(core::BuiltinType b) + : Base(static_cast(tint::TypeCode::Of().bits), core::type::Flags{}), + builtin(b) {} + +IncompleteType::~IncompleteType() = default; + +std::string IncompleteType::FriendlyName() const { + return ""; +} + +uint32_t IncompleteType::Size() const { + return 0; +} + +uint32_t IncompleteType::Align() const { + return 0; +} + +core::type::Type* IncompleteType::Clone(core::type::CloneContext&) const { + TINT_ICE() << "IncompleteType does not support cloning"; +} + +bool IncompleteType::Equals(const core::type::UniqueNode& other) const { + if (auto* o = other.As()) { + return o->builtin == builtin; + } + return false; +} + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.h new file mode 100644 index 000000000..edb32fb6b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/incomplete_type.h @@ -0,0 +1,76 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_INCOMPLETE_TYPE_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_INCOMPLETE_TYPE_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/type.h" + +namespace tint::resolver { + +/// Represents a expression that resolved to the name of a type without explicit template arguments. +/// This is a placeholder type that on successful resolving, is replaced with the type built using +/// the inferred template arguments. +/// For example, given the expression `vec3(1i, 2i, 3i)`: +/// * The IdentifierExpression for `vec3` is resolved first, to an IncompleteType as it does not +/// know the vector element type. +/// * Next, the CallExpression replaces the IncompleteType with a core::type::Vector once it can +/// infer the element type from the call's arguments. +class IncompleteType : public Castable { + public: + /// Constructor + /// @param b the incomplete builtin type + explicit IncompleteType(core::BuiltinType b); + + /// Destructor + ~IncompleteType() override; + + /// The incomplete builtin type + const core::BuiltinType builtin = core::BuiltinType::kUndefined; + + /// @copydoc core::type::Type::FriendlyName + std::string FriendlyName() const override; + + /// @copydoc core::type::Type::Size + uint32_t Size() const override; + + /// @copydoc core::type::Type::Align + uint32_t Align() const override; + + /// @copydoc core::type::Type::Clone + core::type::Type* Clone(core::type::CloneContext& ctx) const override; + + /// @copydoc core::type::UniqueNode::Equals + bool Equals(const UniqueNode& other) const override; +}; + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_INCOMPLETE_TYPE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.cc new file mode 100644 index 000000000..376501365 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.cc @@ -0,0 +1,42 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/resolve.h" + +#include + +#include "src/tint/lang/wgsl/resolver/resolver.h" + +namespace tint::resolver { + +Program Resolve(ProgramBuilder& builder, const wgsl::AllowedFeatures& allowed_features) { + Resolver resolver(&builder, std::move(allowed_features)); + resolver.Resolve(); + return Program(std::move(builder)); +} + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.h new file mode 100644 index 000000000..179eca5a5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolve.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_RESOLVE_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_RESOLVE_H_ + +#include "src/tint/lang/wgsl/allowed_features.h" + +namespace tint { +class Program; +class ProgramBuilder; +} // namespace tint + +namespace tint::resolver { + +/// Performs semantic analysis and validation on the program builder @p builder +/// @param allowed_features the extensions and features that are allowed to be used +/// @returns the resolved Program. Program.Diagnostics() may contain validation errors. +Program Resolve( + ProgramBuilder& builder, + const wgsl::AllowedFeatures& allowed_features = wgsl::AllowedFeatures::Everything()); + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_RESOLVE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.cc new file mode 100644 index 000000000..442b764ae --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.cc @@ -0,0 +1,5018 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/resolver.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/constant/scalar.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/type/abstract_float.h" +#include "src/tint/lang/core/type/abstract_int.h" +#include "src/tint/lang/core/type/atomic.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/builtin_structs.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/external_texture.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/memory_view.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/wgsl/ast/alias.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/attribute.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/traverse_expressions.h" +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/while_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/intrinsic/ctor_conv.h" +#include "src/tint/lang/wgsl/resolver/incomplete_type.h" +#include "src/tint/lang/wgsl/resolver/uniformity.h" +#include "src/tint/lang/wgsl/resolver/unresolved_identifier.h" +#include "src/tint/lang/wgsl/sem/array.h" +#include "src/tint/lang/wgsl/sem/behavior.h" +#include "src/tint/lang/wgsl/sem/break_if_statement.h" +#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h" +#include "src/tint/lang/wgsl/sem/builtin_fn.h" +#include "src/tint/lang/wgsl/sem/call.h" +#include "src/tint/lang/wgsl/sem/for_loop_statement.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/function_expression.h" +#include "src/tint/lang/wgsl/sem/if_statement.h" +#include "src/tint/lang/wgsl/sem/index_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/load.h" +#include "src/tint/lang/wgsl/sem/loop_statement.h" +#include "src/tint/lang/wgsl/sem/materialize.h" +#include "src/tint/lang/wgsl/sem/member_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/module.h" +#include "src/tint/lang/wgsl/sem/pipeline_stage_set.h" +#include "src/tint/lang/wgsl/sem/statement.h" +#include "src/tint/lang/wgsl/sem/struct.h" +#include "src/tint/lang/wgsl/sem/switch_statement.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/lang/wgsl/sem/value_constructor.h" +#include "src/tint/lang/wgsl/sem/value_conversion.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/lang/wgsl/sem/while_statement.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/internal_limits.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/macros/scoped_assignment.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::resolver { +namespace { + +/// ICE() is a wrapper around TINT_ICE() that includes a prefixed source location +#define ICE(SOURCE) TINT_ICE() << SOURCE << (SOURCE.file ? ": " : "") + +using CtorConvIntrinsic = wgsl::intrinsic::CtorConv; +using OverloadFlag = core::intrinsic::OverloadFlag; + +constexpr uint32_t kMaxStatementDepth = 127; +constexpr size_t kMaxNestDepthOfCompositeType = 255; + +} // namespace + +Resolver::Resolver(ProgramBuilder* builder, const wgsl::AllowedFeatures& allowed_features) + : b(*builder), + diagnostics_(builder->Diagnostics()), + const_eval_(builder->constants, diagnostics_), + intrinsic_table_{builder->Types(), builder->Symbols()}, + sem_(builder), + validator_(builder, + sem_, + enabled_extensions_, + allowed_features_, + atomic_composite_info_, + valid_type_storage_layouts_), + allowed_features_(allowed_features) {} + +Resolver::~Resolver() = default; + +bool Resolver::Resolve() { + if (diagnostics_.ContainsErrors()) { + return false; + } + + b.Sem().Reserve(b.LastAllocatedNodeID()); + + // Pre-allocate the marked bitset with the total number of AST nodes. + marked_.Resize(b.ASTNodes().Count()); + + if (!DependencyGraph::Build(b.AST(), diagnostics_, dependencies_)) { + return false; + } + + bool result = ResolveInternal(); + + TINT_ASSERT(result || diagnostics_.ContainsErrors()) + << "resolving failed, but no error was raised"; + + if (!validator_.Enables(b.AST().Enables())) { + return false; + } + + // Create the semantic module. Don't be tempted to std::move() these, they're used below. + auto* mod = b.create(dependencies_.ordered_globals, enabled_extensions_); + ApplyDiagnosticSeverities(mod); + b.Sem().SetModule(mod); + + const bool disable_uniformity_analysis = + enabled_extensions_.Contains(wgsl::Extension::kChromiumDisableUniformityAnalysis); + if (result && !disable_uniformity_analysis) { + // Run the uniformity analysis, which requires a complete semantic module. + const bool subgroup_uniformity = + allowed_features_.features.count(wgsl::LanguageFeature::kSubgroupUniformity); + if (!AnalyzeUniformity(b, dependencies_, subgroup_uniformity)) { + return false; + } + } + + return result; +} + +bool Resolver::ResolveInternal() { + Mark(&b.AST()); + + // Process all module-scope declarations in dependency order. + Vector diagnostic_controls; + for (auto* decl : dependencies_.ordered_globals) { + Mark(decl); + if (!Switch( + decl, // + [&](const ast::DiagnosticDirective* d) { + diagnostic_controls.Push(&d->control); + return DiagnosticControl(d->control); + }, + [&](const ast::Enable* e) { return Enable(e); }, + [&](const ast::Requires* r) { return Requires(r); }, + [&](const ast::TypeDecl* td) { return TypeDecl(td); }, + [&](const ast::Function* func) { return Function(func); }, + [&](const ast::Variable* var) { return GlobalVariable(var); }, + [&](const ast::ConstAssert* ca) { return ConstAssert(ca); }, // + TINT_ICE_ON_NO_MATCH)) { + return false; + } + } + + if (!AllocateOverridableConstantIds()) { + return false; + } + + SetShadows(); + + if (!validator_.DiagnosticControls(diagnostic_controls, "directive", + DiagnosticDuplicates::kAllowed)) { + return false; + } + + if (!validator_.PipelineStages(entry_points_)) { + return false; + } + + if (!validator_.ModuleScopeVarUsages(entry_points_)) { + return false; + } + + bool result = true; + for (auto* node : b.ASTNodes().Objects()) { + if (DAWN_UNLIKELY(!marked_[node->node_id.value])) { + ICE(node->source) << "AST node '" << node->TypeInfo().name + << "' was not reached by the resolver\n" + << "Pointer: " << node; + } + } + + return result; +} + +sem::Variable* Resolver::Variable(const ast::Variable* v, bool is_global) { + Mark(v->name); + + return Switch( + v, // + [&](const ast::Var* var) { return Var(var, is_global); }, + [&](const ast::Let* let) { return Let(let); }, + [&](const ast::Override* override) { return Override(override); }, + [&](const ast::Const* const_) { return Const(const_, is_global); }, // + TINT_ICE_ON_NO_MATCH); +} + +sem::Variable* Resolver::Let(const ast::Let* v) { + auto* sem = b.create(v, current_statement_); + sem->SetStage(core::EvaluationStage::kRuntime); + b.Sem().Add(v, sem); + + // If the variable has a declared type, resolve it. + if (v->type) { + auto* ty = Type(v->type); + if (DAWN_UNLIKELY(!ty)) { + return nullptr; + } + sem->SetType(ty); + } + + if (!v->attributes.IsEmpty()) { + ErrorInvalidAttribute(v->attributes[0], + StyledText{} << style::Keyword("let") << " declaration"); + return nullptr; + } + + if (DAWN_UNLIKELY(!v->initializer)) { + AddError(v->source) << style::Keyword("let") << " declaration must have an initializer"; + return nullptr; + } + + auto* rhs = Load(Materialize(ValueExpression(v->initializer), sem->Type())); + if (DAWN_UNLIKELY(!rhs)) { + return nullptr; + } + sem->SetInitializer(rhs); + + // If the variable has no declared type, infer it from the RHS + if (!sem->Type()) { + sem->SetType(rhs->Type()->UnwrapRef()); // Implicit load of RHS + } + + if (DAWN_UNLIKELY(rhs && !validator_.VariableInitializer(v, sem->Type(), rhs))) { + return nullptr; + } + + if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, + const_cast(sem->Type()), v->source)) { + AddNote(v->source) << "while instantiating " << style::Keyword("let ") + << style::Variable(v->name->symbol.NameView()); + return nullptr; + } + + return sem; +} + +sem::Variable* Resolver::Override(const ast::Override* v) { + auto* sem = b.create(v); + b.Sem().Add(v, sem); + sem->SetStage(core::EvaluationStage::kOverride); + + on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) { + if (ref->Declaration()->Is()) { + sem->AddTransitivelyReferencedOverride(ref); + } + }); + TINT_DEFER(on_transitively_reference_global_.Pop()); + + // If the variable has a declared type, resolve it. + const core::type::Type* ty = nullptr; + if (v->type) { + ty = Type(v->type); + if (!ty) { + return nullptr; + } + } + + // Does the variable have an initializer? + const sem::ValueExpression* init = nullptr; + if (v->initializer) { + // Note: RHS must be a const or override expression, which excludes references. + // So there's no need to load or unwrap references here. + ExprEvalStageConstraint constraint{core::EvaluationStage::kOverride, + "override initializer"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + init = Materialize(ValueExpression(v->initializer), ty); + if (DAWN_UNLIKELY(!init)) { + return nullptr; + } + sem->SetInitializer(init); + + // If the variable has no declared type, infer it from the initializer + if (!ty) { + ty = init->Type(); + } + } else if (!ty) { + AddError(v->source) << "override declaration requires a type or initializer"; + return nullptr; + } + sem->SetType(ty); + + if (init && !validator_.VariableInitializer(v, ty, init)) { + return nullptr; + } + + if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, + const_cast(ty), v->source)) { + AddNote(v->source) << "while instantiating " << style::Keyword("override ") + << style::Variable(v->name->symbol.NameView()); + return nullptr; + } + + for (auto* attribute : v->attributes) { + Mark(attribute); + bool ok = Switch( + attribute, // + [&](const ast::IdAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@id"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return false; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) + << style::Attribute("@id") << " must be an " << style::Type("i32") << " or " + << style::Type("u32") << " value"; + return false; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value < 0) { + AddError(attr->source) + << style::Attribute("@id") << " value must be non-negative"; + return false; + } + if (value > std::numeric_limits::max()) { + AddError(attr->source) + << style::Attribute("@id") << " value must be between 0 and " + << std::numeric_limits::max(); + return false; + } + + auto o = OverrideId{static_cast(value)}; + sem->Attributes().override_id = o; + + // Track the constant IDs that are specified in the shader. + override_ids_.Add(o, sem); + return true; + }, + [&](Default) { + ErrorInvalidAttribute(attribute, + StyledText{} << style::Keyword("override") << " declaration"); + return false; + }); + if (!ok) { + return nullptr; + } + } + + return sem; +} + +sem::Variable* Resolver::Const(const ast::Const* c, bool is_global) { + sem::Variable* sem = nullptr; + sem::GlobalVariable* global = nullptr; + if (is_global) { + global = b.create(c); + sem = global; + } else { + sem = b.create(c, current_statement_); + } + b.Sem().Add(c, sem); + + for (auto* attribute : c->attributes) { + Mark(attribute); + bool ok = + Switch(attribute, // + [&](Default) { + ErrorInvalidAttribute( + attribute, StyledText{} << style::Keyword("const") << " declaration"); + return false; + }); + if (!ok) { + return nullptr; + } + } + + if (DAWN_UNLIKELY(!c->initializer)) { + AddError(c->source) << "'const' declaration must have an initializer"; + return nullptr; + } + + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "const initializer"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + const auto* init = ValueExpression(c->initializer); + if (DAWN_UNLIKELY(!init)) { + return nullptr; + } + + // Note: RHS must be a const expression, which excludes references. + // So there's no need to load or unwrap references here. + + // If the variable has a declared type, resolve it. + const core::type::Type* ty = nullptr; + if (c->type) { + ty = Type(c->type); + if (DAWN_UNLIKELY(!ty)) { + return nullptr; + } + } + + if (ty) { + // If an explicit type was specified, materialize to that type + init = Materialize(init, ty); + if (DAWN_UNLIKELY(!init)) { + return nullptr; + } + } else { + // If no type was specified, infer it from the RHS + ty = init->Type(); + } + + sem->SetInitializer(init); + sem->SetStage(core::EvaluationStage::kConstant); + sem->SetConstantValue(init->ConstantValue()); + sem->SetType(ty); + + if (!validator_.VariableInitializer(c, ty, init)) { + return nullptr; + } + + if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, + const_cast(ty), c->source)) { + AddNote(c->source) << "while instantiating 'const' " << c->name->symbol.NameView(); + return nullptr; + } + + return sem; +} + +sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) { + sem::Variable* sem = nullptr; + sem::GlobalVariable* global = nullptr; + if (is_global) { + global = b.create(var); + sem = global; + } else { + sem = b.create(var, current_statement_); + } + sem->SetStage(core::EvaluationStage::kRuntime); + b.Sem().Add(var, sem); + + if (is_global) { + on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) { + if (ref->Declaration()->Is()) { + global->AddTransitivelyReferencedOverride(ref); + } + }); + } + TINT_DEFER({ + if (is_global) { + on_transitively_reference_global_.Pop(); + } + }); + + // If the variable has a declared type, resolve it. + const core::type::Type* storage_ty = nullptr; + if (auto ty = var->type) { + storage_ty = Type(ty); + if (DAWN_UNLIKELY(!storage_ty)) { + return nullptr; + } + } + + // Does the variable have a initializer? + if (var->initializer) { + ExprEvalStageConstraint constraint{ + is_global ? core::EvaluationStage::kOverride : core::EvaluationStage::kRuntime, + "var initializer", + }; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* init = Load(Materialize(ValueExpression(var->initializer), storage_ty)); + if (DAWN_UNLIKELY(!init)) { + return nullptr; + } + sem->SetInitializer(init); + + // If the variable has no declared type, infer it from the RHS + if (!storage_ty) { + storage_ty = init->Type(); + } + } + + if (!storage_ty) { + AddError(var->source) << "var declaration requires a type or initializer"; + return nullptr; + } + + if (var->declared_address_space) { + auto space = AddressSpaceExpression(var->declared_address_space); + if (DAWN_UNLIKELY(!space)) { + return nullptr; + } + sem->SetAddressSpace(space->Value()); + } else { + // No declared address space. Infer from usage / type. + if (!is_global) { + sem->SetAddressSpace(core::AddressSpace::kFunction); + } else if (storage_ty->UnwrapRef()->IsHandle()) { + // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables + // If the store type is a handle type, then the variable declaration must not have a + // address space attribute. The address space will always be handle. + sem->SetAddressSpace(core::AddressSpace::kHandle); + } + } + + if (!is_global && sem->AddressSpace() != core::AddressSpace::kFunction) { + AddError(var->source) + << "function-scope 'var' declaration must use 'function' address space"; + return nullptr; + } + + if (var->declared_access) { + auto expr = AccessExpression(var->declared_access); + if (!expr) { + return nullptr; + } + sem->SetAccess(expr->Value()); + } else { + sem->SetAccess(DefaultAccessForAddressSpace(sem->AddressSpace())); + } + + sem->SetType(b.create(sem->AddressSpace(), storage_ty, sem->Access())); + + if (sem->Initializer() && + !validator_.VariableInitializer(var, storage_ty, sem->Initializer())) { + return nullptr; + } + + if (!ApplyAddressSpaceUsageToType(sem->AddressSpace(), + const_cast(sem->Type()), + var->type ? var->type->source : var->source)) { + AddNote(var->source) << "while instantiating 'var' " << var->name->symbol.NameView(); + return nullptr; + } + + if (is_global) { + std::optional group, binding, input_attachment_index; + for (auto* attribute : var->attributes) { + Mark(attribute); + enum Status { kSuccess, kErrored, kInvalid }; + auto res = Switch( + attribute, // + [&](const ast::BindingAttribute* attr) { + auto value = BindingAttribute(attr); + if (value != Success) { + return kErrored; + } + binding = value.Get(); + return kSuccess; + }, + [&](const ast::GroupAttribute* attr) { + auto value = GroupAttribute(attr); + if (value != Success) { + return kErrored; + } + group = value.Get(); + return kSuccess; + }, + [&](const ast::InputAttachmentIndexAttribute* attr) { + auto value = InputAttachmentIndexAttribute(attr); + if (value != Success) { + return kErrored; + } + input_attachment_index = value.Get(); + return kSuccess; + }, + [&](Default) { return kInvalid; }); + + switch (res) { + case kSuccess: + break; + case kErrored: + return nullptr; + case kInvalid: + ErrorInvalidAttribute(attribute, + StyledText{} << "module-scope " << style::Keyword("var")); + return nullptr; + } + } + + if (group && binding) { + global->Attributes().binding_point = BindingPoint{group.value(), binding.value()}; + } + + if (input_attachment_index) { + global->Attributes().input_attachment_index = input_attachment_index; + } + + } else if (!var->attributes.IsEmpty()) { + ErrorInvalidAttribute(var->attributes[0], + StyledText{} << "function-scope " << style::Keyword("var")); + return nullptr; + } + + return sem; +} + +sem::Parameter* Resolver::Parameter(const ast::Parameter* param, + const ast::Function* func, + uint32_t index) { + Mark(param->name); + + auto* sem = b.create(param, index); + b.Sem().Add(param, sem); + + auto add_note = [&] { + AddNote(param->source) << "while instantiating parameter " + << param->name->symbol.NameView(); + }; + + if (func->IsEntryPoint()) { + for (auto* attribute : param->attributes) { + Mark(attribute); + bool ok = Switch( + attribute, // + [&](const ast::LocationAttribute* attr) { + auto value = LocationAttribute(attr); + if (DAWN_UNLIKELY(value != Success)) { + return false; + } + sem->Attributes().location = value.Get(); + return true; + }, + [&](const ast::ColorAttribute* attr) { + auto value = ColorAttribute(attr); + if (DAWN_UNLIKELY(value != Success)) { + return false; + } + sem->Attributes().color = value.Get(); + return true; + }, + [&](const ast::BuiltinAttribute*) { return true; }, + [&](const ast::InvariantAttribute* attr) -> bool { + return InvariantAttribute(attr); + }, + [&](const ast::InterpolateAttribute*) { return true; }, + [&](Default) { + ErrorInvalidAttribute(attribute, StyledText{} << "function parameters"); + return false; + }); + if (!ok) { + return nullptr; + } + } + } else if (!param->attributes.IsEmpty()) { + auto& attribute = param->attributes[0]; + if (attribute->IsAnyOf()) { + ErrorInvalidAttribute(attribute, StyledText{} << "non-entry point function parameters"); + } else { + ErrorInvalidAttribute(attribute, StyledText{} << "function parameters"); + } + return nullptr; + } + + if (!validator_.NoDuplicateAttributes(param->attributes)) { + return nullptr; + } + + const core::type::Type* ty = Type(param->type); + if (DAWN_UNLIKELY(!ty)) { + return nullptr; + } + sem->SetType(ty); + + if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, ty, param->type->source)) { + add_note(); + return nullptr; + } + + if (!validator_.Parameter(sem)) { + return nullptr; + } + + return sem; +} + +core::Access Resolver::DefaultAccessForAddressSpace(core::AddressSpace address_space) { + // https://gpuweb.github.io/gpuweb/wgsl/#storage-class + switch (address_space) { + case core::AddressSpace::kImmediate: + case core::AddressSpace::kStorage: + case core::AddressSpace::kUniform: + case core::AddressSpace::kHandle: + return core::Access::kRead; + default: + break; + } + return core::Access::kReadWrite; +} + +bool Resolver::AllocateOverridableConstantIds() { + constexpr size_t kLimit = std::numeric_limits::max(); + // The next pipeline constant ID to try to allocate. + OverrideId next_id; + bool ids_exhausted = false; + + auto increment_next_id = [&] { + if (next_id.value == kLimit) { + ids_exhausted = true; + } else { + next_id.value = next_id.value + 1; + } + }; + + // Allocate constant IDs in global declaration order, so that they are + // deterministic. + // TODO(crbug.com/tint/1192): If a transform changes the order or removes an + // unused constant, the allocation may change on the next Resolver pass. + for (auto* decl : b.AST().GlobalDeclarations()) { + auto* override = decl->As(); + if (!override) { + continue; + } + + auto* sem = sem_.Get(override); + + OverrideId id; + if (auto sem_id = sem->Attributes().override_id) { + id = *sem_id; + } else { + // No ID was specified, so allocate the next available ID. + while (!ids_exhausted && override_ids_.Contains(next_id)) { + increment_next_id(); + } + if (ids_exhausted) { + AddError(decl->source) + << "number of 'override' variables exceeded limit of " << kLimit; + return false; + } + id = next_id; + increment_next_id(); + } + + const_cast(sem)->Attributes().override_id = id; + } + return true; +} + +void Resolver::SetShadows() { + for (auto& it : dependencies_.shadows) { + CastableBase* shadowed = sem_.Get(it.value); + if (DAWN_UNLIKELY(!shadowed)) { + ICE(it.value->source) << "AST node '" << it.value->TypeInfo().name + << "' had no semantic info\n" + << "Pointer: " << it.value; + } + + Switch( + sem_.Get(it.key.Value()), // + [&](sem::LocalVariable* local) { local->SetShadows(shadowed); }, + [&](sem::Parameter* param) { param->SetShadows(shadowed); }); + } +} + +sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* v) { + auto* sem = As(Variable(v, /* is_global */ true)); + if (!sem) { + return nullptr; + } + + if (!validator_.NoDuplicateAttributes(v->attributes)) { + return nullptr; + } + + if (!validator_.GlobalVariable(sem, override_ids_)) { + return nullptr; + } + + return sem; +} + +sem::Statement* Resolver::ConstAssert(const ast::ConstAssert* assertion) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "const assertion"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + auto* expr = ValueExpression(assertion->condition); + if (!expr) { + return nullptr; + } + auto* cond = expr->ConstantValue(); + if (auto* ty = cond->Type(); !ty->Is()) { + AddError(assertion->condition->source) + << "const assertion condition must be a bool, got '" << ty->FriendlyName() << "'"; + return nullptr; + } + if (!cond->ValueAs()) { + AddError(assertion->source) << "const assertion failed"; + return nullptr; + } + auto* sem = b.create(assertion, current_compound_statement_, current_function_); + b.Sem().Add(assertion, sem); + return sem; +} + +sem::Function* Resolver::Function(const ast::Function* decl) { + Mark(decl->name); + + auto* func = b.create(decl); + b.Sem().Add(decl, func); + TINT_SCOPED_ASSIGNMENT(current_function_, func); + + on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) { // + func->AddDirectlyReferencedGlobal(ref); + }); + TINT_DEFER(on_transitively_reference_global_.Pop()); + + validator_.DiagnosticFilters().Push(); + TINT_DEFER(validator_.DiagnosticFilters().Pop()); + + for (auto* attribute : decl->attributes) { + Mark(attribute); + bool ok = Switch( + attribute, + [&](const ast::DiagnosticAttribute* attr) { return DiagnosticAttribute(attr); }, + [&](const ast::StageAttribute* attr) { return StageAttribute(attr); }, + [&](const ast::MustUseAttribute* attr) { return MustUseAttribute(attr); }, + [&](const ast::WorkgroupAttribute* attr) { + auto value = WorkgroupAttribute(attr); + if (value != Success) { + return false; + } + func->SetWorkgroupSize(value.Get()); + return true; + }, + [&](const ast::SubgroupSizeAttribute* attr) { + auto value = SubgroupSizeAttribute(attr); + if (value != Success) { + return false; + } + func->SetSubgroupSize(value.Get()); + return true; + }, + [&](Default) { + ErrorInvalidAttribute(attribute, StyledText{} << "functions"); + return false; + }); + if (!ok) { + return nullptr; + } + } + if (!validator_.NoDuplicateAttributes(decl->attributes)) { + return nullptr; + } + + // Resolve all the parameters + uint32_t parameter_index = 0; + Hashmap parameter_names; + for (auto* param : decl->params) { + Mark(param); + + { // Check the parameter name is unique for the function + if (auto added = parameter_names.Add(param->name->symbol, param->source); !added) { + auto name = param->name->symbol.NameView(); + AddError(param->source) << "redefinition of parameter '" << name << "'"; + AddNote(added.value) << "previous definition is here"; + return nullptr; + } + } + + auto* p = Parameter(param, decl, parameter_index++); + if (!p) { + return nullptr; + } + + func->AddParameter(p); + + auto* p_ty = const_cast(p->Type()); + if (auto* str = p_ty->As()) { + switch (decl->PipelineStage()) { + case ast::PipelineStage::kVertex: + str->AddUsage(core::type::PipelineStageUsage::kVertexInput); + break; + case ast::PipelineStage::kFragment: + str->AddUsage(core::type::PipelineStageUsage::kFragmentInput); + break; + case ast::PipelineStage::kCompute: + str->AddUsage(core::type::PipelineStageUsage::kComputeInput); + break; + case ast::PipelineStage::kNone: + break; + } + } + } + + // Resolve the return type + const core::type::Type* return_type = nullptr; + if (auto ty = decl->return_type) { + return_type = Type(ty); + if (!return_type) { + return nullptr; + } + } else { + return_type = b.create(); + } + func->SetReturnType(return_type); + + if (decl->IsEntryPoint()) { + // Determine if the return type has a location + for (auto* attribute : decl->return_type_attributes) { + Mark(attribute); + enum Status { kSuccess, kErrored, kInvalid }; + auto res = Switch( + attribute, // + [&](const ast::LocationAttribute* attr) { + auto value = LocationAttribute(attr); + if (value != Success) { + return kErrored; + } + func->SetReturnLocation(value.Get()); + return kSuccess; + }, + [&](const ast::BuiltinAttribute*) { return kSuccess; }, + [&](const ast::InterpolateAttribute*) { return kSuccess; }, + [&](const ast::InvariantAttribute* attr) { + return InvariantAttribute(attr) ? kSuccess : kErrored; + }, + [&](Default) { return kInvalid; }); + + switch (res) { + case kSuccess: + break; + case kErrored: + return nullptr; + case kInvalid: + ErrorInvalidAttribute(attribute, StyledText{} << "entry point return types"); + return nullptr; + } + } + } else { + for (auto* attribute : decl->return_type_attributes) { + Mark(attribute); + bool ok = + Switch(attribute, // + [&](Default) { + ErrorInvalidAttribute( + attribute, StyledText{} << "non-entry point function return types"); + return false; + }); + if (!ok) { + return nullptr; + } + } + } + + if (auto* str = const_cast(return_type->As())) { + if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, str, + decl->return_type->source)) { + AddNote(decl->return_type->source) + << "while instantiating return type for " << decl->name->symbol.NameView(); + return nullptr; + } + + switch (decl->PipelineStage()) { + case ast::PipelineStage::kVertex: + str->AddUsage(core::type::PipelineStageUsage::kVertexOutput); + break; + case ast::PipelineStage::kFragment: + str->AddUsage(core::type::PipelineStageUsage::kFragmentOutput); + break; + case ast::PipelineStage::kCompute: + str->AddUsage(core::type::PipelineStageUsage::kComputeOutput); + break; + case ast::PipelineStage::kNone: + break; + } + } + + ApplyDiagnosticSeverities(func); + + if (decl->IsEntryPoint()) { + entry_points_.Push(func); + } + + if (decl->body) { + Mark(decl->body); + if (DAWN_UNLIKELY(current_compound_statement_)) { + ICE(decl->body->source) + << "Resolver::Function() called with a current compound statement"; + } + auto* body = StatementScope(decl->body, b.create(func), + [&] { return Statements(decl->body->statements); }); + if (!body) { + return nullptr; + } + func->Behaviors() = body->Behaviors(); + if (func->Behaviors().Contains(sem::Behavior::kReturn)) { + // https://www.w3.org/TR/WGSL/#behaviors-rules + // We assign a behavior to each function: it is its body’s behavior + // (treating the body as a regular statement), with any "Return" replaced + // by "Next". + func->Behaviors().Remove(sem::Behavior::kReturn); + func->Behaviors().Add(sem::Behavior::kNext); + } + } + + if (!validator_.NoDuplicateAttributes(decl->return_type_attributes)) { + return nullptr; + } + + auto stage = current_function_ ? current_function_->Declaration()->PipelineStage() + : ast::PipelineStage::kNone; + if (!validator_.Function(func, stage)) { + return nullptr; + } + + // If this is an entry point, mark all transitively called functions as being in its call graph. + if (decl->IsEntryPoint()) { + for (auto* f : func->TransitivelyCalledFunctions()) { + const_cast(f)->AddCallGraphEntryPoint(func); + } + // An entry point is considered to be in its own call graph. + func->AddCallGraphEntryPoint(func); + } + + return func; +} + +bool Resolver::Statements(VectorRef stmts) { + sem::Behaviors behaviors{sem::Behavior::kNext}; + + bool reachable = true; + for (auto* stmt : stmts) { + Mark(stmt); + auto* sem = Statement(stmt); + if (!sem) { + return false; + } + // s1 s2:(B1∖{Next}) ∪ B2 + sem->SetIsReachable(reachable); + if (reachable) { + behaviors = (behaviors - sem::Behavior::kNext) + sem->Behaviors(); + } + reachable = reachable && sem->Behaviors().Contains(sem::Behavior::kNext); + } + + current_statement_->Behaviors() = behaviors; + + if (!validator_.Statements(stmts)) { + return false; + } + + return true; +} + +sem::Statement* Resolver::Statement(const ast::Statement* stmt) { + return Switch( + stmt, + // Compound statements. These create their own sem::CompoundStatement + // bindings. + [&](const ast::BlockStatement* s) { return BlockStatement(s); }, + [&](const ast::ForLoopStatement* s) { return ForLoopStatement(s); }, + [&](const ast::LoopStatement* s) { return LoopStatement(s); }, + [&](const ast::WhileStatement* s) { return WhileStatement(s); }, + [&](const ast::IfStatement* s) { return IfStatement(s); }, + [&](const ast::SwitchStatement* s) { return SwitchStatement(s); }, + + // Non-Compound statements + [&](const ast::AssignmentStatement* s) { return AssignmentStatement(s); }, + [&](const ast::BreakStatement* s) { return BreakStatement(s); }, + [&](const ast::BreakIfStatement* s) { return BreakIfStatement(s); }, + [&](const ast::CallStatement* s) { return CallStatement(s); }, + [&](const ast::CompoundAssignmentStatement* s) { return CompoundAssignmentStatement(s); }, + [&](const ast::ContinueStatement* s) { return ContinueStatement(s); }, + [&](const ast::DiscardStatement* s) { return DiscardStatement(s); }, + [&](const ast::IncrementDecrementStatement* s) { return IncrementDecrementStatement(s); }, + [&](const ast::ReturnStatement* s) { return ReturnStatement(s); }, + [&](const ast::VariableDeclStatement* s) { return VariableDeclStatement(s); }, + [&](const ast::ConstAssert* s) { return ConstAssert(s); }, + + // Error cases + [&](const ast::CaseStatement*) { + AddError(stmt->source) << "case statement can only be used inside a switch statement"; + return nullptr; + }, + [&](Default) { + AddError(stmt->source) + << "unknown statement type: " << std::string(stmt->TypeInfo().name); + return nullptr; + }); +} + +sem::CaseStatement* Resolver::CaseStatement(const ast::CaseStatement* stmt, + const core::type::Type* ty) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + sem->Selectors().reserve(stmt->selectors.Length()); + for (auto* sel : stmt->selectors) { + Mark(sel); + + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "case selector"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + const core::constant::Value* const_value = nullptr; + if (!sel->IsDefault()) { + // The sem statement was created in the switch when attempting to determine the + // common type. + auto* materialized = Materialize(sem_.GetVal(sel->expr), ty); + if (!materialized) { + return false; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(sel->source) << "case selector must be an i32 or u32 value"; + return false; + } + const_value = materialized->ConstantValue(); + if (!const_value) { + AddError(sel->source) << "case selector must be a constant expression"; + return false; + } + } + + sem->Selectors().emplace_back(b.create(sel, const_value)); + } + + Mark(stmt->body); + auto* body = BlockStatement(stmt->body); + if (!body) { + return false; + } + sem->SetBlock(body); + sem->Behaviors() = body->Behaviors(); + return true; + }); +} + +sem::IfStatement* Resolver::IfStatement(const ast::IfStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto* cond = Load(ValueExpression(stmt->condition)); + if (!cond) { + return false; + } + sem->SetCondition(cond); + sem->Behaviors().Remove(sem::Behavior::kNext); + + Mark(stmt->body); + auto* body = b.create(stmt->body, current_compound_statement_, + current_function_); + if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) { + return false; + } + sem->Behaviors().Add(body->Behaviors()); + + if (stmt->else_statement) { + Mark(stmt->else_statement); + auto* else_sem = Statement(stmt->else_statement); + if (!else_sem) { + return false; + } + sem->Behaviors().Add(else_sem->Behaviors()); + } else { + // https://www.w3.org/TR/WGSL/#behaviors-rules + // if statements without an else branch are treated as if they had an + // empty else branch (which adds Next to their behavior) + sem->Behaviors().Add(sem::Behavior::kNext); + } + + return validator_.IfStatement(sem); + }); +} + +sem::BlockStatement* Resolver::BlockStatement(const ast::BlockStatement* stmt) { + auto* sem = b.create(stmt->As(), + current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { return Statements(stmt->statements); }); +} + +sem::LoopStatement* Resolver::LoopStatement(const ast::LoopStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + Mark(stmt->body); + + auto* body = b.create(stmt->body, current_compound_statement_, + current_function_); + return StatementScope(stmt->body, body, [&] { + if (!Statements(stmt->body->statements)) { + return false; + } + auto& behaviors = sem->Behaviors(); + behaviors = body->Behaviors(); + + // If the body only returns, then the entire loop only returns. + // Control never reaches the continuing block, and never reaches + // code that follows the loop. + const bool only_return = behaviors == sem::Behaviors(sem::Behavior::kReturn); + + if (stmt->continuing) { + Mark(stmt->continuing); + auto* continuing = StatementScope( + stmt->continuing, + b.create( + stmt->continuing, current_compound_statement_, current_function_), + [&] { return Statements(stmt->continuing->statements); }); + if (!continuing) { + return false; + } + if (!only_return) { + behaviors.Add(continuing->Behaviors()); + } + } + + // If the body behaviour is just Return, then this has no effect. + if (behaviors.Contains(sem::Behavior::kBreak)) { // Does the loop exit? + behaviors.Add(sem::Behavior::kNext); + } else { + behaviors.Remove(sem::Behavior::kNext); + } + behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kContinue); + + return validator_.LoopStatement(sem); + }); + }); +} + +sem::ForLoopStatement* Resolver::ForLoopStatement(const ast::ForLoopStatement* stmt) { + auto* sem = + b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto& behaviors = sem->Behaviors(); + if (auto* initializer = stmt->initializer) { + Mark(initializer); + auto* init = Statement(initializer); + if (!init) { + return false; + } + behaviors.Add(init->Behaviors()); + } + + if (auto* cond_expr = stmt->condition) { + auto* cond = Load(ValueExpression(cond_expr)); + if (!cond) { + return false; + } + sem->SetCondition(cond); + } + + if (auto* continuing = stmt->continuing) { + Mark(continuing); + auto* cont = Statement(continuing); + if (!cont) { + return false; + } + behaviors.Add(cont->Behaviors()); + } + + Mark(stmt->body); + + auto* body = b.create(stmt->body, current_compound_statement_, + current_function_); + if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) { + return false; + } + + behaviors.Add(body->Behaviors()); + if (stmt->condition || behaviors.Contains(sem::Behavior::kBreak)) { // Does the loop exit? + behaviors.Add(sem::Behavior::kNext); + } else { + behaviors.Remove(sem::Behavior::kNext); + } + behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kContinue); + + return validator_.ForLoopStatement(sem); + }); +} + +sem::WhileStatement* Resolver::WhileStatement(const ast::WhileStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto& behaviors = sem->Behaviors(); + + auto* cond = Load(ValueExpression(stmt->condition)); + if (!cond) { + return false; + } + sem->SetCondition(cond); + + Mark(stmt->body); + + auto* body = b.create(stmt->body, current_compound_statement_, + current_function_); + if (!StatementScope(stmt->body, body, [&] { return Statements(stmt->body->statements); })) { + return false; + } + + behaviors.Add(body->Behaviors()); + if (stmt->condition || behaviors.Contains(sem::Behavior::kBreak)) { // Does the loop exit? + behaviors.Add(sem::Behavior::kNext); + } else { + behaviors.Remove(sem::Behavior::kNext); + } + behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kContinue); + + return validator_.WhileStatement(sem); + }); +} + +sem::Expression* Resolver::Expression(const ast::Expression* root) { + Vector sorted; + constexpr size_t kMaxExpressionDepth = 512U; + bool failed = false; + if (!ast::TraverseExpressions( + root, [&](const ast::Expression* expr, size_t depth) { + if (depth > kMaxExpressionDepth) { + AddError(expr->source) + << "reached max expression depth of " << kMaxExpressionDepth; + failed = true; + return ast::TraverseAction::Stop; + } + if (!Mark(expr)) { + failed = true; + return ast::TraverseAction::Stop; + } + if (auto* binary = expr->As(); + binary && binary->IsLogical()) { + // Store potential const-eval short-circuit pair + logical_binary_lhs_to_parent_.Add(binary->lhs, binary); + } + sorted.Push(expr); + return ast::TraverseAction::Descend; + })) { + AddError(root->source) << "TraverseExpressions failed"; + return nullptr; + } + + if (failed) { + return nullptr; + } + + for (auto* expr : tint::Reverse(sorted)) { + auto* sem_expr = Switch( + expr, // + [&](const ast::IndexAccessorExpression* array) { return IndexAccessor(array); }, + [&](const ast::BinaryExpression* bin_op) { return Binary(bin_op); }, + [&](const ast::CallExpression* call) { return Call(call); }, + [&](const ast::IdentifierExpression* ident) { return Identifier(ident); }, + [&](const ast::LiteralExpression* literal) { return Literal(literal); }, + [&](const ast::MemberAccessorExpression* member) { return MemberAccessor(member); }, + [&](const ast::UnaryOpExpression* unary) { return UnaryOp(unary); }, + [&](const ast::PhonyExpression*) { + return b.create(expr, b.create(), + core::EvaluationStage::kRuntime, + current_statement_, + /* constant_value */ nullptr); + }, // + TINT_ICE_ON_NO_MATCH); + if (!sem_expr) { + return nullptr; + } + + auto* val = sem_expr->As(); + + if (val) { + if (auto* constraint = expr_eval_stage_constraint_.constraint) { + if (!validator_.EvaluationStage(val, expr_eval_stage_constraint_.stage, + constraint)) { + return nullptr; + } + } + } + + b.Sem().Add(expr, sem_expr); + if (expr == root) { + return sem_expr; + } + + // If we just processed the lhs of a constexpr logical binary expression, mark the rhs for + // short-circuiting. + if (val && val->ConstantValue()) { + if (auto binary = logical_binary_lhs_to_parent_.Get(expr)) { + const bool lhs_is_true = val->ConstantValue()->ValueAs(); + if (((*binary)->IsLogicalAnd() && !lhs_is_true) || + ((*binary)->IsLogicalOr() && lhs_is_true)) { + // Mark entire expression tree to not const-evaluate + auto r = ast::TraverseExpressions( // + (*binary)->rhs, [&](const ast::Expression* e) { + not_evaluated_.Add(e); + if (e->Is()) { + // Template arguments are still evaluated when the outer identifier + // expression is skipped. This happens in expressions like: + // false && array()[i] + // where we still need to evaluate and validate `N`. + return ast::TraverseAction::Skip; + } + return ast::TraverseAction::Descend; + }); + if (!r) { + AddError(root->source) << "TraverseExpressions failed"; + return nullptr; + } + } + } + } + } + + ICE(root->source) << "Expression() did not find root node"; +} + +sem::ValueExpression* Resolver::ValueExpression(const ast::Expression* expr) { + return sem_.AsValueExpression(Expression(expr)); +} + +sem::TypeExpression* Resolver::TypeExpression(const ast::Expression* expr) { + return sem_.AsTypeExpression(Expression(expr)); +} + +sem::FunctionExpression* Resolver::FunctionExpression(const ast::Expression* expr) { + return sem_.AsFunctionExpression(Expression(expr)); +} + +const core::type::Type* Resolver::Type(const ast::Expression* ast) { + Vector referenced_overrides; + on_transitively_reference_global_.Push([&](const sem::GlobalVariable* ref) { + if (ref->Declaration()->Is()) { + referenced_overrides.Push(ref); + } + }); + TINT_DEFER(on_transitively_reference_global_.Pop()); + + auto* type_expr = TypeExpression(ast); + if (DAWN_UNLIKELY(!type_expr)) { + return nullptr; + } + + auto* type = const_cast(type_expr->Type()); + if (DAWN_UNLIKELY(!type)) { + return nullptr; + } + + if (auto* arr = type->As()) { + for (auto* ref : referenced_overrides) { + arr->AddTransitivelyReferencedOverride(ref); + } + } + + return type; +} + +sem::BuiltinEnumExpression* Resolver::AddressSpaceExpression( + const ast::Expression* expr) { + auto address_space_expr = sem_.AsAddressSpace(Expression(expr)); + if (DAWN_UNLIKELY(!address_space_expr)) { + return nullptr; + } + if (DAWN_UNLIKELY( + address_space_expr->Value() == core::AddressSpace::kPixelLocal && + !enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalPixelLocal))) { + AddError(expr->source) << "'pixel_local' address space requires the '" + << wgsl::Extension::kChromiumExperimentalPixelLocal + << "' extension enabled"; + return nullptr; + } + return address_space_expr; +} + +sem::BuiltinEnumExpression* Resolver::TexelFormatExpression( + const ast::Expression* expr) { + return sem_.AsTexelFormat(Expression(expr)); +} + +sem::BuiltinEnumExpression* Resolver::AccessExpression(const ast::Expression* expr) { + return sem_.AsAccess(Expression(expr)); +} + +void Resolver::RegisterStore(const sem::ValueExpression* expr) { + Switch( + expr->RootIdentifier(), + [&](const sem::GlobalVariable* global) { + alias_analysis_infos_[current_function_].module_scope_writes.Add(global, expr); + }, + [&](const sem::Parameter* param) { + alias_analysis_infos_[current_function_].parameter_writes.Add(param); + }); +} + +void Resolver::RegisterLoad(const sem::ValueExpression* expr) { + Switch( + expr->RootIdentifier(), + [&](const sem::GlobalVariable* global) { + alias_analysis_infos_[current_function_].module_scope_reads.Add(global, expr); + }, + [&](const sem::Parameter* param) { + alias_analysis_infos_[current_function_].parameter_reads.Add(param); + }); +} + +bool Resolver::AliasAnalysis(const sem::Call* call) { + auto* target = call->Target()->As(); + if (!target) { + return true; + } + + // Helper to generate an aliasing error diagnostic. + struct Alias { + const sem::ValueExpression* expr; // the "other expression" + enum { Argument, ModuleScope } type; // the type of the "other" expression + std::string access; // the access performed for the "other" expression + }; + auto make_error = [&](const sem::ValueExpression* arg, Alias&& var) { + AddError(arg->Declaration()->source) << "invalid aliased pointer argument"; + switch (var.type) { + case Alias::Argument: + AddNote(var.expr->Declaration()->source) + << "aliases with another argument passed here"; + break; + case Alias::ModuleScope: { + auto* func = var.expr->Stmt()->Function(); + auto func_name = func->Declaration()->name->symbol.NameView(); + AddNote(var.expr->Declaration()->source) + << "aliases with module-scope variable " << var.access << " in '" << func_name + << "'"; + break; + } + } + return false; + }; + + auto& args = call->Arguments(); + auto& target_info = alias_analysis_infos_[target]; + auto& caller_info = alias_analysis_infos_[current_function_]; + + // Track the set of root identifiers that are read and written by arguments passed in this + // call. + Hashmap arg_reads; + Hashmap arg_writes; + for (size_t i = 0; i < args.Length(); i++) { + auto* arg = args[i]; + if (!arg->Type()->Is()) { + continue; + } + + auto* root = arg->RootIdentifier(); + if (target_info.parameter_writes.Contains(target->Parameters()[i])) { + // Arguments that are written to can alias with any other argument or module-scope + // variable access. + if (auto write = arg_writes.Get(root)) { + return make_error(arg, {*write, Alias::Argument, "write"}); + } + if (auto read = arg_reads.Get(root)) { + return make_error(arg, {*read, Alias::Argument, "read"}); + } + if (auto read = target_info.module_scope_reads.Get(root)) { + return make_error(arg, {*read, Alias::ModuleScope, "read"}); + } + if (auto write = target_info.module_scope_writes.Get(root)) { + return make_error(arg, {*write, Alias::ModuleScope, "write"}); + } + arg_writes.Add(root, arg); + + // Propagate the write access to the caller. + Switch( + root, + [&](const sem::GlobalVariable* global) { + caller_info.module_scope_writes.Add(global, arg); + }, + [&](const sem::Parameter* param) { caller_info.parameter_writes.Add(param); }); + } else if (target_info.parameter_reads.Contains(target->Parameters()[i])) { + // Arguments that are read from can alias with arguments or module-scope variables + // that are written to. + if (auto write = arg_writes.Get(root)) { + return make_error(arg, {*write, Alias::Argument, "write"}); + } + if (auto write = target_info.module_scope_writes.Get(root)) { + return make_error(arg, {*write, Alias::ModuleScope, "write"}); + } + arg_reads.Add(root, arg); + + // Propagate the read access to the caller. + Switch( + root, + [&](const sem::GlobalVariable* global) { + caller_info.module_scope_reads.Add(global, arg); + }, + [&](const sem::Parameter* param) { caller_info.parameter_reads.Add(param); }); + } + } + + // Propagate module-scope variable uses to the caller. + for (auto read : target_info.module_scope_reads) { + caller_info.module_scope_reads.Add(read.key, read.value); + } + for (auto write : target_info.module_scope_writes) { + caller_info.module_scope_writes.Add(write.key, write.value); + } + + return true; +} + +const core::type::Type* Resolver::ConcreteType(const core::type::Type* ty, + const core::type::Type* target_ty, + const Source& source) { + auto i32 = [&] { return b.create(); }; + auto f32 = [&] { return b.create(); }; + auto i32v = [&](uint32_t width) { return b.create(i32(), width); }; + auto f32v = [&](uint32_t width) { return b.create(f32(), width); }; + auto f32m = [&](uint32_t columns, uint32_t rows) { + return b.create(f32v(rows), columns); + }; + + return Switch( + ty, // + [&](const core::type::AbstractInt*) { return target_ty ? target_ty : i32(); }, + [&](const core::type::AbstractFloat*) { return target_ty ? target_ty : f32(); }, + [&](const core::type::Vector* v) { + return Switch( + v->Type(), // + [&](const core::type::AbstractInt*) { + return target_ty ? target_ty : i32v(v->Width()); + }, + [&](const core::type::AbstractFloat*) { + return target_ty ? target_ty : f32v(v->Width()); + }); + }, + [&](const core::type::Matrix* m) { + return Switch(m->Type(), // + [&](const core::type::AbstractFloat*) { + return target_ty ? target_ty : f32m(m->Columns(), m->Rows()); + }); + }, + [&](const sem::Array* a) -> const core::type::Type* { + const core::type::Type* target_el_ty = nullptr; + if (auto* target_arr_ty = As(target_ty)) { + target_el_ty = target_arr_ty->ElemType(); + } + if (auto* el_ty = ConcreteType(a->ElemType(), target_el_ty, source)) { + return Array(source, source, source, el_ty, a->Count()); + } + return nullptr; + }, + [&](const core::type::Struct* s) -> const core::type::Type* { + if (auto tys = s->ConcreteTypes(); !tys.IsEmpty()) { + return target_ty ? target_ty : tys[0]; + } + return nullptr; + }); +} + +const sem::ValueExpression* Resolver::Load(const sem::ValueExpression* expr) { + if (!expr) { + // Allow for Load(ValueExpression(blah)), where failures pass through Load() + return nullptr; + } + + if (!expr->Type()->Is()) { + // Expression is not a reference type, so cannot be loaded. Just return expr. + return expr; + } + + auto* load = b.create(expr, current_statement_, expr->Stage()); + b.Sem().Replace(expr->Declaration(), load); + + // Register the load for the alias analysis. + RegisterLoad(expr); + + return load; +} + +const sem::ValueExpression* Resolver::Materialize( + const sem::ValueExpression* expr, + const core::type::Type* target_type /* = nullptr */) { + if (!expr) { + // Allow for Materialize(ValueExpression(blah)), where failures pass through Materialize() + return nullptr; + } + + auto* decl = expr->Declaration(); + + auto* concrete_ty = ConcreteType(expr->Type(), target_type, decl->source); + if (!concrete_ty) { + return expr; // Does not require materialization + } + + auto* src_ty = expr->Type(); + if (!validator_.Materialize(concrete_ty, src_ty, decl->source)) { + return nullptr; + } + + const core::constant::Value* materialized_val = nullptr; + if (!not_evaluated_.Contains(decl)) { + auto expr_val = expr->ConstantValue(); + if (DAWN_UNLIKELY(!expr_val)) { + ICE(decl->source) << "Materialize(" << decl->TypeInfo().name + << ") called on expression with no constant value"; + } + + auto val = const_eval_.Convert(concrete_ty, expr_val, decl->source); + if (val != Success) { + // Convert() has already failed and raised an diagnostic error. + return nullptr; + } + materialized_val = val.Get(); + if (DAWN_UNLIKELY(!materialized_val)) { + ICE(decl->source) << "ConvertValue(" << expr_val->Type()->FriendlyName() << " -> " + << concrete_ty->FriendlyName() << ") returned invalid value"; + } + } + + auto* m = b.create(expr, current_statement_, concrete_ty, materialized_val); + b.Sem().Replace(decl, m); + return m; +} + +template +bool Resolver::MaybeMaterializeAndLoadArguments(Vector& args, + const sem::CallTarget* target) { + for (size_t i = 0, n = std::min(args.Length(), target->Parameters().Length()); i < n; i++) { + const auto* param_ty = target->Parameters()[i]->Type(); + if (ShouldMaterializeArgument(param_ty)) { + auto* materialized = Materialize(args[i], param_ty); + if (!materialized) { + return false; + } + args[i] = materialized; + } + if (!param_ty->Is()) { + auto* load = Load(args[i]); + if (!load) { + return false; + } + args[i] = load; + } + } + return true; +} + +bool Resolver::ShouldMaterializeArgument(const core::type::Type* parameter_ty) const { + const auto* param_el_ty = parameter_ty->DeepestElement(); + return (param_el_ty != nullptr) && !param_el_ty->Is(); +} + +bool Resolver::Convert(const core::constant::Value*& c, + const core::type::Type* target_ty, + const Source& source) { + auto r = const_eval_.Convert(target_ty, c, source); + if (r != Success) { + return false; + } + c = r.Get(); + return true; +} + +template +tint::Result> Resolver::ConvertArguments( + const Vector& args, + const sem::CallTarget* target) { + auto const_args = tint::Transform(args, [](auto* arg) { return arg->ConstantValue(); }); + for (size_t i = 0, n = std::min(args.Length(), target->Parameters().Length()); i < n; i++) { + if (!Convert(const_args[i], target->Parameters()[i]->Type(), + args[i]->Declaration()->source)) { + return Failure{}; + } + } + return const_args; +} + +template +const core::constant::Value* Resolver::ConvertConstArgument( + const Vector& args, + const sem::CallTarget* target, + unsigned i) { + TINT_ASSERT(i < args.Length()); + if (const auto* const_arg = args[i]->ConstantValue()) { + const auto& params = target->Parameters(); + TINT_ASSERT(i < params.Length()); + // If successful, the conversion updates `const_arg`. + if (Convert(const_arg, params[i]->Type(), Source{})) { + return const_arg; + } + } + return nullptr; +} + +sem::ValueExpression* Resolver::IndexAccessor(const ast::IndexAccessorExpression* expr) { + auto* idx = Load(Materialize(sem_.GetVal(expr->index))); + if (!idx) { + return nullptr; + } + const auto* obj = sem_.GetVal(expr->object); + if (idx->Stage() != core::EvaluationStage::kConstant) { + // If the index is non-constant, then the resulting expression is non-constant, so we'll + // have to materialize the object. For example, consider: + // vec2(1, 2)[runtime-index] + obj = Materialize(obj); + } + if (!obj) { + return nullptr; + } + auto* object_ty = obj->Type(); + auto* const memory_view = object_ty->As(); + const core::type::Type* storage_ty = object_ty->UnwrapRef(); + if (memory_view) { + if (memory_view->Is() && + (allowed_features_.features.count(wgsl::LanguageFeature::kPointerCompositeAccess) == + 0u)) { + AddError(expr->source) + << "pointer composite access requires the pointer_composite_access language " + "feature, which is not allowed in the current environment"; + return nullptr; + } + storage_ty = memory_view->StoreType(); + } + + auto* ty = Switch( + storage_ty, // + [&](const sem::Array* arr) { return arr->ElemType(); }, + [&](const core::type::BindingArray* arr) { return arr->ElemType(); }, + [&](const core::type::Vector* vec) { return vec->Type(); }, + [&](const core::type::Matrix* mat) { + return b.create(mat->Type(), mat->Rows()); + }, + [&](Default) { + AddError(expr->source) << "cannot index type '" << sem_.TypeNameOf(storage_ty) << "'"; + return nullptr; + }); + if (ty == nullptr) { + return nullptr; + } + + auto* idx_ty = idx->Type()->UnwrapRef(); + if (!idx_ty->IsAnyOf()) { + AddError(idx->Declaration()->source) + << "index must be of type 'i32' or 'u32', found: '" << sem_.TypeNameOf(idx_ty) << "'"; + return nullptr; + } + + // If we're extracting from a memory view, we return a reference. + if (memory_view) { + ty = + b.create(memory_view->AddressSpace(), ty, memory_view->Access()); + } + + const core::constant::Value* val = nullptr; + auto stage = core::EarliestStage(obj->Stage(), idx->Stage()); + if (not_evaluated_.Contains(expr)) { + stage = core::EvaluationStage::kNotEvaluated; + } else { + if (auto* idx_val = idx->ConstantValue()) { + auto res = const_eval_.Index(obj->ConstantValue(), obj->Type(), idx_val, + idx->Declaration()->source); + if (res != Success) { + return nullptr; + } + val = res.Get(); + } + } + auto* sem = b.create( + expr, ty, stage, obj, idx, current_statement_, std::move(val), obj->RootIdentifier()); + return sem; +} + +sem::Call* Resolver::Call(const ast::CallExpression* expr) { + // A CallExpression can resolve to one of: + // * A function call. + // * A builtin call. + // * A value constructor. + // * A value conversion. + auto* target = sem_.Get(expr->target); + if (DAWN_UNLIKELY(!target)) { + return nullptr; + } + + // Resolve all of the arguments, their types and the set of behaviors. + Vector args; + args.Reserve(expr->args.Length()); + auto args_stage = core::EvaluationStage::kConstant; + for (size_t i = 0; i < expr->args.Length(); i++) { + auto* arg = sem_.GetVal(expr->args[i]); + if (!arg) { + return nullptr; + } + args.Push(arg); + args_stage = core::EarliestStage(args_stage, arg->Stage()); + } + + // ctor_or_conv is a helper for building either a sem::ValueConstructor or + // sem::ValueConversion call for a CtorConvIntrinsic with an optional template argument type. + auto ctor_or_conv = [&](CtorConvIntrinsic ty, + VectorRef template_args) -> sem::Call* { + auto arg_tys = tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); }); + auto match = intrinsic_table_.Lookup(ty, template_args, arg_tys, args_stage); + if (match != Success) { + AddError(expr->source) << match.Failure(); + return nullptr; + } + + auto overload_stage = match->const_eval_fn ? core::EvaluationStage::kConstant + : core::EvaluationStage::kRuntime; + + sem::CallTarget* target_sem = nullptr; + + // Is this overload a constructor or conversion? + if (match->info->flags.Contains(OverloadFlag::kIsConstructor)) { + // Type constructor + target_sem = constructors_.GetOrAdd(match.Get(), [&] { + auto params = Transform(match->parameters, [&](auto& p, size_t i) { + return b.create(nullptr, static_cast(i), p.type, + p.usage); + }); + return b.create(match->return_type, std::move(params), + overload_stage); + }); + } else { + // Type conversion + target_sem = converters_.GetOrAdd(match.Get(), [&] { + auto* param = b.create(nullptr, 0u, match->parameters[0].type, + match->parameters[0].usage); + return b.create(match->return_type, param, overload_stage); + }); + } + + if (!MaybeMaterializeAndLoadArguments(args, target_sem)) { + return nullptr; + } + + const core::constant::Value* value = nullptr; + auto stage = core::EarliestStage(overload_stage, args_stage); + if (not_evaluated_.Contains(expr)) { + stage = core::EvaluationStage::kNotEvaluated; + } + if (stage == core::EvaluationStage::kConstant) { + auto const_args = ConvertArguments(args, target_sem); + if (const_args != Success) { + return nullptr; + } + auto const_eval_fn = match->const_eval_fn; + auto r = (const_eval_.*const_eval_fn)(target_sem->ReturnType(), const_args.Get(), + expr->source); + if (r != Success) { + return nullptr; + } + value = r.Get(); + } + return b.create(expr, target_sem, stage, std::move(args), current_statement_, + value); + }; + + // arr_or_str_init is a helper for building a sem::ValueConstructor for an array or structure + // constructor call target. + auto arr_or_str_init = [&](const core::type::Type* ty, + const sem::CallTarget* call_target) -> sem::Call* { + auto stage = args_stage; // The evaluation stage of the call + const core::constant::Value* value = nullptr; // The constant value for the call + if (subgroup_matrix_uses_.Contains(ty)) { + // Composites that contain subgroup matrices cannot be evaluated until runtime. + stage = core::EvaluationStage::kRuntime; + } + if (not_evaluated_.Contains(expr)) { + stage = core::EvaluationStage::kNotEvaluated; + } + if (stage == core::EvaluationStage::kConstant) { + auto const_args = ConvertArguments(args, call_target); + if (const_args != Success) { + return nullptr; + } + auto r = const_eval_.ArrayOrStructCtor(ty, std::move(const_args.Get())); + if (r != Success) { + return nullptr; + } + value = r.Get(); + if (!value) { + // Constant evaluation failed. + // Can happen for expressions that will fail validation (later). + // Use the kRuntime EvaluationStage, as kConstant will trigger an assertion in + // the sem::ValueExpression constructor, which checks that kConstant is paired + // with a constant value. + stage = core::EvaluationStage::kRuntime; + } + } + + return b.create(expr, call_target, stage, std::move(args), current_statement_, + value); + }; + + auto ty_init_or_conv = [&](const core::type::Type* type) { + return Switch( + type, // + [&](const core::type::I32*) { return ctor_or_conv(CtorConvIntrinsic::kI32, Empty); }, + [&](const core::type::U32*) { return ctor_or_conv(CtorConvIntrinsic::kU32, Empty); }, + [&](const core::type::F16*) { + return validator_.CheckF16Enabled(expr->source) + ? ctor_or_conv(CtorConvIntrinsic::kF16, Empty) + : nullptr; + }, + [&](const core::type::F32*) { return ctor_or_conv(CtorConvIntrinsic::kF32, Empty); }, + [&](const core::type::Bool*) { return ctor_or_conv(CtorConvIntrinsic::kBool, Empty); }, + [&](const core::type::Vector* v) { + return ctor_or_conv(wgsl::intrinsic::VectorCtorConv(v->Width()), Vector{v->Type()}); + }, + [&](const core::type::Matrix* m) { + return ctor_or_conv(wgsl::intrinsic::MatrixCtorConv(m->Columns(), m->Rows()), + Vector{m->Type()}); + }, + [&](const sem::Array* arr) -> sem::Call* { + auto* call_target = array_ctors_.GetOrAdd( + ArrayConstructorSig{{arr, args.Length(), args_stage}}, + [&]() -> sem::ValueConstructor* { + auto params = tint::Transform(args, [&](auto, size_t i) { + return b.create(nullptr, // declaration + static_cast(i), // index + arr->ElemType()); + }); + return b.create(arr, std::move(params), args_stage); + }); + + if (DAWN_UNLIKELY(!MaybeMaterializeAndLoadArguments(args, call_target))) { + return nullptr; + } + + if (DAWN_UNLIKELY(!validator_.ArrayConstructor(expr, arr))) { + return nullptr; + } + + return arr_or_str_init(arr, call_target); + }, + [&](const core::type::Struct* str) -> sem::Call* { + auto* call_target = struct_ctors_.GetOrAdd( + StructConstructorSig{{str, args.Length(), args_stage}}, + [&]() -> sem::ValueConstructor* { + Vector params; + params.Resize(std::min(args.Length(), str->Members().Length())); + for (size_t i = 0, n = params.Length(); i < n; i++) { + params[i] = + b.create(nullptr, // declaration + static_cast(i), // index + str->Members()[i]->Type()); // type + } + return b.create(str, std::move(params), args_stage); + }); + + if (DAWN_UNLIKELY(!MaybeMaterializeAndLoadArguments(args, call_target))) { + return nullptr; + } + + if (DAWN_UNLIKELY(!validator_.StructureInitializer(expr, str))) { + return nullptr; + } + + return arr_or_str_init(str, call_target); + }, + [&](const core::type::SubgroupMatrix* m) -> sem::Call* { + auto* call_target = subgroup_matrix_ctors_.GetOrAdd( + SubgroupMatrixConstructorSig{{m, args.Length()}}, + [&]() -> sem::ValueConstructor* { + // 8-bit integer matrices use 32-bit shader scalar types. + auto* scalar_ty = m->Type(); + if (m->Type()->Is()) { + scalar_ty = b.create(); + } else if (m->Type()->Is()) { + scalar_ty = b.create(); + } + auto params = tint::Transform(args, [&](auto, size_t i) { + return b.create(nullptr, // declaration + static_cast(i), // index + scalar_ty); + }); + return b.create(m, std::move(params), + core::EvaluationStage::kRuntime); + }); + + if (DAWN_UNLIKELY(!MaybeMaterializeAndLoadArguments(args, call_target))) { + return nullptr; + } + + if (DAWN_UNLIKELY(!validator_.SubgroupMatrixConstructor(expr, m, call_target))) { + return nullptr; + } + + // Subgroup matrix constructors are never const-evaluated. + auto stage = core::EvaluationStage::kRuntime; + if (not_evaluated_.Contains(expr)) { + stage = core::EvaluationStage::kNotEvaluated; + } + + return b.create(expr, call_target, stage, std::move(args), + current_statement_, nullptr); + }, + [&](Default) { + AddError(expr->source) << "type is not constructible"; + return nullptr; + }); + }; + + auto incomplete_type = [&](const IncompleteType* t) -> sem::Call* { + // A type without template arguments. + // Examples: vec3(...), array(...) + switch (t->builtin) { + case core::BuiltinType::kVec2: + return ctor_or_conv(CtorConvIntrinsic::kVec2, Empty); + case core::BuiltinType::kVec3: + return ctor_or_conv(CtorConvIntrinsic::kVec3, Empty); + case core::BuiltinType::kVec4: + return ctor_or_conv(CtorConvIntrinsic::kVec4, Empty); + case core::BuiltinType::kMat2X2: + return ctor_or_conv(CtorConvIntrinsic::kMat2x2, Empty); + case core::BuiltinType::kMat2X3: + return ctor_or_conv(CtorConvIntrinsic::kMat2x3, Empty); + case core::BuiltinType::kMat2X4: + return ctor_or_conv(CtorConvIntrinsic::kMat2x4, Empty); + case core::BuiltinType::kMat3X2: + return ctor_or_conv(CtorConvIntrinsic::kMat3x2, Empty); + case core::BuiltinType::kMat3X3: + return ctor_or_conv(CtorConvIntrinsic::kMat3x3, Empty); + case core::BuiltinType::kMat3X4: + return ctor_or_conv(CtorConvIntrinsic::kMat3x4, Empty); + case core::BuiltinType::kMat4X2: + return ctor_or_conv(CtorConvIntrinsic::kMat4x2, Empty); + case core::BuiltinType::kMat4X3: + return ctor_or_conv(CtorConvIntrinsic::kMat4x3, Empty); + case core::BuiltinType::kMat4X4: + return ctor_or_conv(CtorConvIntrinsic::kMat4x4, Empty); + case core::BuiltinType::kArray: { + auto el_count = + b.create(static_cast(args.Length())); + auto arg_tys = + tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); }); + auto el_ty = core::type::Type::Common(arg_tys); + if (DAWN_UNLIKELY(!el_ty)) { + AddError(expr->source) + << "cannot infer common array element type from constructor arguments"; + Hashset types; + for (size_t i = 0; i < args.Length(); i++) { + if (types.Add(args[i]->Type())) { + AddNote(args[i]->Declaration()->source) + << "argument " << i << " is of type '" + << sem_.TypeNameOf(args[i]->Type()) << "'"; + } + } + return nullptr; + } + auto* arr = Array(expr->source, expr->source, expr->source, el_ty, el_count); + if (DAWN_UNLIKELY(!arr)) { + return nullptr; + } + return ty_init_or_conv(arr); + } + default: { + TINT_ICE() << "unhandled IncompleteType builtin: " << t->builtin; + } + } + }; + + auto* call = Switch( + target, // + [&](const sem::FunctionExpression* fn_expr) { + return FunctionCall(expr, const_cast(fn_expr->Function()), + std::move(args)); + }, + [&](const sem::TypeExpression* ty_expr) { + return Switch( + ty_expr->Type(), // + [&](const IncompleteType* t) -> sem::Call* { + auto* ctor = incomplete_type(t); + if (DAWN_UNLIKELY(!ctor)) { + return nullptr; + } + // Replace incomplete type with resolved type + const_cast(ty_expr)->SetType(ctor->Type()); + return ctor; + }, + [&](Default) { return ty_init_or_conv(ty_expr->Type()); }); + }, + [&](const sem::BuiltinEnumExpression* fn_expr) { + return BuiltinCall(expr, fn_expr->Value(), args); + }, + [&](Default) { + sem_.ErrorUnexpectedExprKind(target, "call target"); + return nullptr; + }); + + if (!call) { + return nullptr; + } + + return validator_.Call(call, current_statement_) ? call : nullptr; +} + +template +sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr, + wgsl::BuiltinFn fn, + Vector& args) { + auto arg_stage = core::EvaluationStage::kConstant; + for (auto* arg : args) { + arg_stage = core::EarliestStage(arg_stage, arg->Stage()); + } + + Vector tmpl_args; + if (auto* tmpl = expr->target->identifier->As()) { + for (auto* arg : tmpl->arguments) { + auto* arg_ty = sem_.AsTypeExpression(sem_.Get(arg)); + if (DAWN_UNLIKELY(!arg_ty)) { + return nullptr; + } + tmpl_args.Push(arg_ty->Type()); + } + } + + auto arg_tys = tint::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); }); + auto overload = intrinsic_table_.Lookup(fn, tmpl_args, arg_tys, arg_stage); + if (overload != Success) { + AddError(expr->source) << overload.Failure(); + return nullptr; + } + + // De-duplicate builtins that are identical. + auto* target = builtins_.GetOrAdd(std::make_pair(overload.Get(), fn), [&] { + auto params = Transform(overload->parameters, [&](auto& p, size_t i) { + return b.create(nullptr, static_cast(i), p.type, p.usage); + }); + sem::PipelineStageSet supported_stages; + auto flags = overload->info->flags; + if (flags.Contains(OverloadFlag::kSupportsVertexPipeline)) { + supported_stages.Add(ast::PipelineStage::kVertex); + } + if (flags.Contains(OverloadFlag::kSupportsFragmentPipeline)) { + supported_stages.Add(ast::PipelineStage::kFragment); + } + if (flags.Contains(OverloadFlag::kSupportsComputePipeline)) { + supported_stages.Add(ast::PipelineStage::kCompute); + } + auto eval_stage = overload->const_eval_fn ? core::EvaluationStage::kConstant + : core::EvaluationStage::kRuntime; + return b.create(fn, overload->return_type, std::move(params), eval_stage, + supported_stages, *overload->info); + }); + + if (fn == wgsl::BuiltinFn::kTintMaterialize) { + args[0] = Materialize(args[0]); + if (!args[0]) { + return nullptr; + } + } else { + // Materialize arguments if the parameter type is not abstract + if (!MaybeMaterializeAndLoadArguments(args, target)) { + return nullptr; + } + } + + if (target->IsDeprecated()) { + AddWarning(expr->source) << "use of deprecated builtin"; + } + + // If the builtin is @const, and all arguments have constant values, evaluate the builtin + // now. + const core::constant::Value* value = nullptr; + auto stage = core::EarliestStage(arg_stage, target->Stage()); + if (not_evaluated_.Contains(expr)) { + stage = core::EvaluationStage::kNotEvaluated; + } + if (stage == core::EvaluationStage::kConstant) { + auto const_args = ConvertArguments(args, target); + if (const_args != Success) { + return nullptr; + } + auto const_eval_fn = overload->const_eval_fn; + auto r = (const_eval_.*const_eval_fn)(target->ReturnType(), const_args.Get(), expr->source); + if (r != Success) { + return nullptr; + } + value = r.Get(); + } + + // If the builtin is bufferView, set the root identifier based on the first argument. + const sem::Variable* root_ident = nullptr; + if (fn == wgsl::BuiltinFn::kBufferView) { + root_ident = args[0]->RootIdentifier(); + } + auto* call = b.create(expr, target, stage, std::move(args), current_statement_, + value, root_ident); + + if (current_function_) { + current_function_->AddDirectlyCalledBuiltin(target); + current_function_->AddDirectCall(call); + } + + if (!validator_.RequiredFeaturesForBuiltinFn(call)) { + return nullptr; + } + + if (IsTexture(fn)) { + if (!validator_.TextureBuiltinFn(call)) { + return nullptr; + } + } + + switch (fn) { + case wgsl::BuiltinFn::kWorkgroupUniformLoad: + RegisterLoad(args[0]); + break; + + case wgsl::BuiltinFn::kSubgroupBroadcast: + if (!validator_.SubgroupBroadcast(call)) { + return nullptr; + } + break; + case wgsl::BuiltinFn::kSubgroupShuffle: + case wgsl::BuiltinFn::kSubgroupShuffleUp: + case wgsl::BuiltinFn::kSubgroupShuffleDown: + case wgsl::BuiltinFn::kSubgroupShuffleXor: + if (!validator_.SubgroupShuffleFunction(fn, call)) { + return nullptr; + } + break; + + case wgsl::BuiltinFn::kQuadBroadcast: + if (!validator_.QuadBroadcast(call)) { + return nullptr; + } + break; + + case wgsl::BuiltinFn::kAtomicLoad: + RegisterLoad(args[0]); + break; + + case wgsl::BuiltinFn::kAtomicStore: + RegisterStore(args[0]); + break; + + case wgsl::BuiltinFn::kAtomicAdd: + case wgsl::BuiltinFn::kAtomicSub: + case wgsl::BuiltinFn::kAtomicMax: + case wgsl::BuiltinFn::kAtomicMin: + case wgsl::BuiltinFn::kAtomicAnd: + case wgsl::BuiltinFn::kAtomicOr: + case wgsl::BuiltinFn::kAtomicXor: + case wgsl::BuiltinFn::kAtomicExchange: + case wgsl::BuiltinFn::kAtomicCompareExchangeWeak: + RegisterLoad(args[0]); + RegisterStore(args[0]); + break; + + case wgsl::BuiltinFn::kSubgroupMatrixLoad: + RegisterLoad(args[0]); + break; + case wgsl::BuiltinFn::kSubgroupMatrixStore: + RegisterStore(args[0]); + break; + + case wgsl::BuiltinFn::kBufferView: { + auto address_space = + call->Target()->ReturnType()->template As()->AddressSpace(); + auto* store_type = + call->Target()->ReturnType()->template As()->StoreType(); + if (!ApplyAddressSpaceUsageToType(address_space, store_type, + call->Declaration()->source)) { + AddNote(call->Declaration()->source) << " while instantiating bufferView"; + return nullptr; + } + if (!validator_.BufferView(call)) { + return nullptr; + } + break; + } + + default: + break; + } + + // Check for errors when only some arguments are const or override. + // Const-eval checks error cases when all arguments are const or override. + switch (fn) { + case wgsl::BuiltinFn::kClamp: { + const auto* lowConst = ConvertConstArgument(args, target, 1); + const auto* highConst = ConvertConstArgument(args, target, 2); + if (lowConst && highConst) { + // Delegate error checking to the const-eval function, but use a harmless + // first argument. + auto fakeArgs = Vector{lowConst, lowConst, highConst}; + auto res = const_eval_.clamp(call->Type(), fakeArgs, call->Declaration()->source); + if (res != Success) { + return nullptr; + } + } + } break; + case wgsl::BuiltinFn::kLdexp: + if (auto* exponentConst = ConvertConstArgument(args, target, 1)) { + auto* zero = const_eval_.Zero(call->Type(), {}, Source{}).Get(); + auto fakeArgs = Vector{zero, exponentConst}; + auto res = const_eval_.ldexp(call->Type(), fakeArgs, call->Declaration()->source); + if (res != Success) { + return nullptr; + } + } + break; + case wgsl::BuiltinFn::kExtractBits: { + auto* offsetConst = ConvertConstArgument(args, target, 1); + auto* countConst = ConvertConstArgument(args, target, 2); + if (offsetConst && countConst) { + auto* zero = const_eval_.Zero(call->Type(), {}, Source{}).Get(); + auto fakeArgs = Vector{zero, offsetConst, countConst}; + auto res = + const_eval_.extractBits(call->Type(), fakeArgs, call->Declaration()->source); + if (res != Success) { + return nullptr; + } + } + } break; + case wgsl::BuiltinFn::kInsertBits: { + auto* offsetConst = ConvertConstArgument(args, target, 2); + auto* countConst = ConvertConstArgument(args, target, 3); + if (offsetConst && countConst) { + auto* zero = const_eval_.Zero(call->Type(), {}, Source{}).Get(); + auto fakeArgs = Vector{zero, zero, offsetConst, countConst}; + auto res = + const_eval_.insertBits(call->Type(), fakeArgs, call->Declaration()->source); + if (res != Success) { + return nullptr; + } + } + } break; + case wgsl::BuiltinFn::kSmoothstep: { + auto* lowConst = ConvertConstArgument(args, target, 0); + auto* highConst = ConvertConstArgument(args, target, 1); + if (lowConst && highConst) { + // Delegate error checking to the const-eval function, but use a harmless + // last argument. + auto fakeArgs = Vector{lowConst, highConst, highConst}; + auto res = + const_eval_.smoothstep(call->Type(), fakeArgs, call->Declaration()->source); + if (res != Success) { + return nullptr; + } + } + } break; + default: + break; + } + + if (!validator_.BuiltinCall(call)) { + return nullptr; + } + + return call; +} + +const core::type::Type* Resolver::BuiltinType(core::BuiltinType builtin_ty, + const ast::Identifier* ident) { + auto check_no_tmpl_args = [&](const core::type::Type* ty) -> const core::type::Type* { + return DAWN_LIKELY(CheckNotTemplated("type", ident)) ? ty : nullptr; + }; + + switch (builtin_ty) { + case core::BuiltinType::kBool: + return check_no_tmpl_args(b.create()); + case core::BuiltinType::kBuffer: + return Buffer(ident); + case core::BuiltinType::kI32: + return check_no_tmpl_args(I32()); + case core::BuiltinType::kU32: + return check_no_tmpl_args(U32()); + case core::BuiltinType::kF16: + return check_no_tmpl_args(F16(ident)); + case core::BuiltinType::kF32: + return check_no_tmpl_args(b.create()); + case core::BuiltinType::kI8: + return check_no_tmpl_args(I8(ident)); + case core::BuiltinType::kU8: + return check_no_tmpl_args(U8(ident)); + case core::BuiltinType::kVec2: + return VecT(ident, builtin_ty, 2); + case core::BuiltinType::kVec3: + return VecT(ident, builtin_ty, 3); + case core::BuiltinType::kVec4: + return VecT(ident, builtin_ty, 4); + case core::BuiltinType::kMat2X2: + return MatT(ident, builtin_ty, 2, 2); + case core::BuiltinType::kMat2X3: + return MatT(ident, builtin_ty, 2, 3); + case core::BuiltinType::kMat2X4: + return MatT(ident, builtin_ty, 2, 4); + case core::BuiltinType::kMat3X2: + return MatT(ident, builtin_ty, 3, 2); + case core::BuiltinType::kMat3X3: + return MatT(ident, builtin_ty, 3, 3); + case core::BuiltinType::kMat3X4: + return MatT(ident, builtin_ty, 3, 4); + case core::BuiltinType::kMat4X2: + return MatT(ident, builtin_ty, 4, 2); + case core::BuiltinType::kMat4X3: + return MatT(ident, builtin_ty, 4, 3); + case core::BuiltinType::kMat4X4: + return MatT(ident, builtin_ty, 4, 4); + case core::BuiltinType::kMat2X2F: + return check_no_tmpl_args(Mat(ident, F32(), 2u, 2u)); + case core::BuiltinType::kMat2X3F: + return check_no_tmpl_args(Mat(ident, F32(), 2u, 3u)); + case core::BuiltinType::kMat2X4F: + return check_no_tmpl_args(Mat(ident, F32(), 2u, 4u)); + case core::BuiltinType::kMat3X2F: + return check_no_tmpl_args(Mat(ident, F32(), 3u, 2u)); + case core::BuiltinType::kMat3X3F: + return check_no_tmpl_args(Mat(ident, F32(), 3u, 3u)); + case core::BuiltinType::kMat3X4F: + return check_no_tmpl_args(Mat(ident, F32(), 3u, 4u)); + case core::BuiltinType::kMat4X2F: + return check_no_tmpl_args(Mat(ident, F32(), 4u, 2u)); + case core::BuiltinType::kMat4X3F: + return check_no_tmpl_args(Mat(ident, F32(), 4u, 3u)); + case core::BuiltinType::kMat4X4F: + return check_no_tmpl_args(Mat(ident, F32(), 4u, 4u)); + case core::BuiltinType::kMat2X2H: + return check_no_tmpl_args(Mat(ident, F16(ident), 2u, 2u)); + case core::BuiltinType::kMat2X3H: + return check_no_tmpl_args(Mat(ident, F16(ident), 2u, 3u)); + case core::BuiltinType::kMat2X4H: + return check_no_tmpl_args(Mat(ident, F16(ident), 2u, 4u)); + case core::BuiltinType::kMat3X2H: + return check_no_tmpl_args(Mat(ident, F16(ident), 3u, 2u)); + case core::BuiltinType::kMat3X3H: + return check_no_tmpl_args(Mat(ident, F16(ident), 3u, 3u)); + case core::BuiltinType::kMat3X4H: + return check_no_tmpl_args(Mat(ident, F16(ident), 3u, 4u)); + case core::BuiltinType::kMat4X2H: + return check_no_tmpl_args(Mat(ident, F16(ident), 4u, 2u)); + case core::BuiltinType::kMat4X3H: + return check_no_tmpl_args(Mat(ident, F16(ident), 4u, 3u)); + case core::BuiltinType::kMat4X4H: + return check_no_tmpl_args(Mat(ident, F16(ident), 4u, 4u)); + case core::BuiltinType::kVec2F: + return check_no_tmpl_args(Vec(ident, F32(), 2u)); + case core::BuiltinType::kVec3F: + return check_no_tmpl_args(Vec(ident, F32(), 3u)); + case core::BuiltinType::kVec4F: + return check_no_tmpl_args(Vec(ident, F32(), 4u)); + case core::BuiltinType::kVec2H: + return check_no_tmpl_args(Vec(ident, F16(ident), 2u)); + case core::BuiltinType::kVec3H: + return check_no_tmpl_args(Vec(ident, F16(ident), 3u)); + case core::BuiltinType::kVec4H: + return check_no_tmpl_args(Vec(ident, F16(ident), 4u)); + case core::BuiltinType::kVec2I: + return check_no_tmpl_args(Vec(ident, I32(), 2u)); + case core::BuiltinType::kVec3I: + return check_no_tmpl_args(Vec(ident, I32(), 3u)); + case core::BuiltinType::kVec4I: + return check_no_tmpl_args(Vec(ident, I32(), 4u)); + case core::BuiltinType::kVec2U: + return check_no_tmpl_args(Vec(ident, U32(), 2u)); + case core::BuiltinType::kVec3U: + return check_no_tmpl_args(Vec(ident, U32(), 3u)); + case core::BuiltinType::kVec4U: + return check_no_tmpl_args(Vec(ident, U32(), 4u)); + case core::BuiltinType::kArray: + return Array(ident); + case core::BuiltinType::kBindingArray: + return BindingArray(ident); + case core::BuiltinType::kAtomic: + return Atomic(ident); + case core::BuiltinType::kPtr: + return Ptr(ident); + case core::BuiltinType::kSampler: + return check_no_tmpl_args( + b.create(core::type::SamplerKind::kSampler)); + case core::BuiltinType::kSamplerComparison: + return check_no_tmpl_args( + b.create(core::type::SamplerKind::kComparisonSampler)); + case core::BuiltinType::kSubgroupMatrixLeft: + return SubgroupMatrix(ident, core::SubgroupMatrixKind::kLeft); + case core::BuiltinType::kSubgroupMatrixRight: + return SubgroupMatrix(ident, core::SubgroupMatrixKind::kRight); + case core::BuiltinType::kSubgroupMatrixResult: + return SubgroupMatrix(ident, core::SubgroupMatrixKind::kResult); + case core::BuiltinType::kTexture1D: + return SampledTexture(ident, core::type::TextureDimension::k1d); + case core::BuiltinType::kTexture2D: + return SampledTexture(ident, core::type::TextureDimension::k2d); + case core::BuiltinType::kTexture2DArray: + return SampledTexture(ident, core::type::TextureDimension::k2dArray); + case core::BuiltinType::kTexture3D: + return SampledTexture(ident, core::type::TextureDimension::k3d); + case core::BuiltinType::kTextureCube: + return SampledTexture(ident, core::type::TextureDimension::kCube); + case core::BuiltinType::kTextureCubeArray: + return SampledTexture(ident, core::type::TextureDimension::kCubeArray); + case core::BuiltinType::kTextureDepth2D: + return check_no_tmpl_args( + b.create(core::type::TextureDimension::k2d)); + case core::BuiltinType::kTextureDepth2DArray: + return check_no_tmpl_args( + b.create(core::type::TextureDimension::k2dArray)); + case core::BuiltinType::kTextureDepthCube: + return check_no_tmpl_args( + b.create(core::type::TextureDimension::kCube)); + case core::BuiltinType::kTextureDepthCubeArray: + return check_no_tmpl_args( + b.create(core::type::TextureDimension::kCubeArray)); + case core::BuiltinType::kTextureDepthMultisampled2D: + return check_no_tmpl_args( + b.create(core::type::TextureDimension::k2d)); + case core::BuiltinType::kTextureExternal: + return check_no_tmpl_args(b.create()); + case core::BuiltinType::kTextureMultisampled2D: + return MultisampledTexture(ident, core::type::TextureDimension::k2d); + case core::BuiltinType::kTextureStorage1D: + return StorageTexture(ident, core::type::TextureDimension::k1d); + case core::BuiltinType::kTextureStorage2D: + return StorageTexture(ident, core::type::TextureDimension::k2d); + case core::BuiltinType::kTextureStorage2DArray: + return StorageTexture(ident, core::type::TextureDimension::k2dArray); + case core::BuiltinType::kTextureStorage3D: + return StorageTexture(ident, core::type::TextureDimension::k3d); + case core::BuiltinType::kTexelBuffer: + return TexelBuffer(ident); + case core::BuiltinType::kInputAttachment: + return InputAttachment(ident); + case core::BuiltinType::kAtomicCompareExchangeResultI32: + return core::type::CreateAtomicCompareExchangeResult(b.Types(), b.Symbols(), I32()); + case core::BuiltinType::kAtomicCompareExchangeResultU32: + return core::type::CreateAtomicCompareExchangeResult(b.Types(), b.Symbols(), U32()); + case core::BuiltinType::kFrexpResultAbstract: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), AF()); + case core::BuiltinType::kFrexpResultF16: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), F16(ident)); + case core::BuiltinType::kFrexpResultF32: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), F32()); + case core::BuiltinType::kFrexpResultVec2Abstract: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, AF(), 2)); + case core::BuiltinType::kFrexpResultVec2F16: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 2)); + case core::BuiltinType::kFrexpResultVec2F32: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F32(), 2)); + case core::BuiltinType::kFrexpResultVec3Abstract: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, AF(), 3)); + case core::BuiltinType::kFrexpResultVec3F16: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 3)); + case core::BuiltinType::kFrexpResultVec3F32: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F32(), 3)); + case core::BuiltinType::kFrexpResultVec4Abstract: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, AF(), 4)); + case core::BuiltinType::kFrexpResultVec4F16: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 4)); + case core::BuiltinType::kFrexpResultVec4F32: + return core::type::CreateFrexpResult(b.Types(), b.Symbols(), Vec(ident, F32(), 4)); + case core::BuiltinType::kModfResultAbstract: + return core::type::CreateModfResult(b.Types(), b.Symbols(), AF()); + case core::BuiltinType::kModfResultF16: + return core::type::CreateModfResult(b.Types(), b.Symbols(), F16(ident)); + case core::BuiltinType::kModfResultF32: + return core::type::CreateModfResult(b.Types(), b.Symbols(), F32()); + case core::BuiltinType::kModfResultVec2Abstract: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, AF(), 2)); + case core::BuiltinType::kModfResultVec2F16: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 2)); + case core::BuiltinType::kModfResultVec2F32: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F32(), 2)); + case core::BuiltinType::kModfResultVec3Abstract: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, AF(), 3)); + case core::BuiltinType::kModfResultVec3F16: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 3)); + case core::BuiltinType::kModfResultVec3F32: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F32(), 3)); + case core::BuiltinType::kModfResultVec4Abstract: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, AF(), 4)); + case core::BuiltinType::kModfResultVec4F16: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F16(ident), 4)); + case core::BuiltinType::kModfResultVec4F32: + return core::type::CreateModfResult(b.Types(), b.Symbols(), Vec(ident, F32(), 4)); + case core::BuiltinType::kUndefined: + break; + } + + ICE(ident->source) << " unhandled builtin type '" << ident->symbol.NameView() << "'"; +} + +const core::type::AbstractFloat* Resolver::AF() { + return b.create(); +} + +const core::type::F32* Resolver::F32() { + return b.create(); +} + +const core::type::I32* Resolver::I32() { + return b.create(); +} + +const core::type::U32* Resolver::U32() { + return b.create(); +} + +const core::type::F16* Resolver::F16(const ast::Identifier* ident) { + return validator_.CheckF16Enabled(ident->source) ? b.create() : nullptr; +} + +const core::type::I8* Resolver::I8(const ast::Identifier* ident) { + return validator_.CheckI8Enabled(ident->source) ? b.create() : nullptr; +} + +const core::type::U8* Resolver::U8(const ast::Identifier* ident) { + return validator_.CheckU8Enabled(ident->source) ? b.create() : nullptr; +} + +const core::type::Vector* Resolver::Vec(const ast::Identifier* ident, + const core::type::Type* el, + uint32_t n) { + if (DAWN_UNLIKELY(!el)) { + return nullptr; + } + if (DAWN_UNLIKELY(!validator_.Vector(el, ident->source))) { + return nullptr; + } + return b.create(el, n); +} + +const core::type::Type* Resolver::VecT(const ast::Identifier* ident, + core::BuiltinType builtin, + uint32_t n) { + auto* tmpl_ident = ident->As(); + if (!tmpl_ident) { + // 'vecN' has no template arguments, so return an incomplete type. + return b.create(builtin); + } + + if (DAWN_UNLIKELY(!CheckTemplatedIdentifierArgs(tmpl_ident, 1))) { + return nullptr; + } + + auto* ty = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!ty)) { + return nullptr; + } + + return Vec(ident, const_cast(ty), n); +} + +const core::type::Matrix* Resolver::Mat(const ast::Identifier* ident, + const core::type::Type* el, + uint32_t num_columns, + uint32_t num_rows) { + if (DAWN_UNLIKELY(!el)) { + return nullptr; + } + if (DAWN_UNLIKELY(!validator_.Matrix(el, ident->source))) { + return nullptr; + } + auto* column = Vec(ident, el, num_rows); + if (!column) { + return nullptr; + } + return b.create(column, num_columns); +} + +const core::type::Type* Resolver::MatT(const ast::Identifier* ident, + core::BuiltinType builtin, + uint32_t num_columns, + uint32_t num_rows) { + auto* tmpl_ident = ident->As(); + if (!tmpl_ident) { + // 'vecN' has no template arguments, so return an incomplete type. + return b.create(builtin); + } + + if (DAWN_UNLIKELY(!CheckTemplatedIdentifierArgs(tmpl_ident, 1))) { + return nullptr; + } + + auto* el_ty = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!el_ty)) { + return nullptr; + } + + return Mat(ident, const_cast(el_ty), num_columns, num_rows); +} + +const core::type::Type* Resolver::Array(const ast::Identifier* ident) { + auto* tmpl_ident = ident->As(); + if (!tmpl_ident) { + // 'array' has no template arguments, so return an incomplete type. + return b.create(core::BuiltinType::kArray); + } + + if (DAWN_UNLIKELY(!CheckTemplatedIdentifierArgs(tmpl_ident, 1, 2))) { + return nullptr; + } + auto* ast_el_ty = tmpl_ident->arguments[0]; + auto* ast_count = (tmpl_ident->arguments.Length() > 1) ? tmpl_ident->arguments[1] : nullptr; + + auto* el_ty = sem_.GetType(ast_el_ty); + if (!el_ty) { + return nullptr; + } + + const core::type::ArrayCount* el_count = + ast_count ? ArrayCount(ast_count) : b.create(); + if (!el_count) { + return nullptr; + } + + auto* out = Array(tmpl_ident->source, // + ast_el_ty->source, // + ast_count ? ast_count->source : ident->source, // + el_ty, el_count); + if (!out) { + return nullptr; + } + + if (el_ty->Is()) { + atomic_composite_info_.Add(out, &ast_el_ty->source); + } else { + if (auto found = atomic_composite_info_.Get(el_ty)) { + atomic_composite_info_.Add(out, *found); + } + } + if (subgroup_matrix_uses_.Contains(el_ty)) { + subgroup_matrix_uses_.Add(out); + } + + return out; +} + +const core::type::BindingArray* Resolver::BindingArray(const ast::Identifier* ident) { + auto* tmpl_ident = TemplatedIdentifier(ident, 2); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto* el_type = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!el_type)) { + return nullptr; + } + + const core::type::ArrayCount* el_count = ArrayCount(tmpl_ident->arguments[1]); + if (!el_count) { + return nullptr; + } + + auto* out = b.create(el_type, el_count); + if (DAWN_UNLIKELY(!validator_.BindingArray(out, ident->source))) { + return nullptr; + } + + return out; +} + +const core::type::Atomic* Resolver::Atomic(const ast::Identifier* ident) { + auto* tmpl_ident = TemplatedIdentifier(ident, 1); // atomic + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto* el_ty = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!el_ty)) { + return nullptr; + } + + auto* out = b.create(el_ty); + if (DAWN_UNLIKELY(!validator_.Atomic(tmpl_ident, out))) { + return nullptr; + } + return out; +} + +const core::type::Pointer* Resolver::Ptr(const ast::Identifier* ident) { + auto* tmpl_ident = TemplatedIdentifier(ident, 2, 3); // ptr + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto address_space = sem_.GetAddressSpace(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(address_space == core::AddressSpace::kUndefined)) { + return nullptr; + } + + auto* store_ty = const_cast(sem_.GetType(tmpl_ident->arguments[1])); + if (DAWN_UNLIKELY(!store_ty)) { + return nullptr; + } + + core::Access access = core::Access::kUndefined; + if (tmpl_ident->arguments.Length() > 2) { + access = sem_.GetAccess(tmpl_ident->arguments[2]); + if (DAWN_UNLIKELY(access == core::Access::kUndefined)) { + return nullptr; + } + } else { + access = DefaultAccessForAddressSpace(address_space); + } + + auto* out = b.create(address_space, store_ty, access); + if (DAWN_UNLIKELY(!validator_.Pointer(tmpl_ident, out))) { + return nullptr; + } + + if (!ApplyAddressSpaceUsageToType(address_space, store_ty, tmpl_ident->arguments[1]->source)) { + AddNote(ident->source) << "while instantiating " << out->FriendlyName(); + return nullptr; + } + return out; +} + +const core::type::SampledTexture* Resolver::SampledTexture(const ast::Identifier* ident, + core::type::TextureDimension dim) { + auto* tmpl_ident = TemplatedIdentifier(ident, 1); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!ty_expr)) { + return nullptr; + } + + auto* out = b.create(dim, ty_expr); + return validator_.SampledTexture(out, ident->source) ? out : nullptr; +} + +const core::type::MultisampledTexture* Resolver::MultisampledTexture( + const ast::Identifier* ident, + core::type::TextureDimension dim) { + auto* tmpl_ident = TemplatedIdentifier(ident, 1); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!ty_expr)) { + return nullptr; + } + + auto* out = b.create(dim, ty_expr); + return validator_.MultisampledTexture(out, ident->source) ? out : nullptr; +} + +const core::type::StorageTexture* Resolver::StorageTexture(const ast::Identifier* ident, + core::type::TextureDimension dim) { + auto* tmpl_ident = TemplatedIdentifier(ident, 2); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto format = sem_.GetTexelFormat(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(format == core::TexelFormat::kUndefined)) { + return nullptr; + } + + auto access = sem_.GetAccess(tmpl_ident->arguments[1]); + if (DAWN_UNLIKELY(access == core::Access::kUndefined)) { + return nullptr; + } + + auto* tex = b.Types().storage_texture(dim, format, access); + if (!validator_.StorageTexture(tex, ident->source)) { + return nullptr; + } + + return tex; +} + +const core::type::InputAttachment* Resolver::InputAttachment(const ast::Identifier* ident) { + auto* tmpl_ident = TemplatedIdentifier(ident, 1); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!ty_expr)) { + return nullptr; + } + + auto* out = b.create(ty_expr); + return validator_.InputAttachment(out, ident->source) ? out : nullptr; +} + +const core::type::SubgroupMatrix* Resolver::SubgroupMatrix(const ast::Identifier* ident, + core::SubgroupMatrixKind kind) { + auto* tmpl_ident = TemplatedIdentifier(ident, 3); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(!ty_expr)) { + return nullptr; + } + + auto get_dim = [&](const ast::Expression* arg, + const char* dim) -> const core::constant::Value* { + const auto* cols_sem = Materialize(sem_.GetVal(arg)); + if (!cols_sem) { + return nullptr; + } + if (!cols_sem->ConstantValue() || cols_sem->ConstantValue()->ValueAs() < 1) { + AddError(arg->source) << "subgroup matrix " << dim + << " count must be a constant positive integer"; + return nullptr; + } + return cols_sem->ConstantValue(); + }; + auto* cols = get_dim(tmpl_ident->arguments[1], "column"); + if (!cols) { + return nullptr; + } + auto* rows = get_dim(tmpl_ident->arguments[2], "row"); + if (!rows) { + return nullptr; + } + + auto* out = b.create(kind, ty_expr, cols->ValueAs(), + rows->ValueAs()); + + subgroup_matrix_uses_.Add(out); + if (current_function_) { + current_function_->SetDirectlyUsedSubgroupMatrix(&ident->source); + } + + return validator_.SubgroupMatrix(out, ident->source) ? out : nullptr; +} + +const core::type::Buffer* Resolver::Buffer(const ast::Identifier* ident) { + core::type::Buffer* out = nullptr; + if (ident->Is()) { + auto* tmpl_ident = TemplatedIdentifier(ident, 1); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + auto* arg = tmpl_ident->arguments[0]; + const core::type::ArrayCount* size = ArrayCount(arg, /* array = */ false); + if (!size) { + return nullptr; + } + out = b.create(size); + } else { + out = b.create(b.create()); + } + return validator_.Buffer(out, ident->source) ? out : nullptr; +} + +const core::type::TexelBuffer* Resolver::TexelBuffer(const ast::Identifier* ident) { + auto* tmpl_ident = TemplatedIdentifier(ident, 2); + if (DAWN_UNLIKELY(!tmpl_ident)) { + return nullptr; + } + + auto format = sem_.GetTexelFormat(tmpl_ident->arguments[0]); + if (DAWN_UNLIKELY(format == core::TexelFormat::kUndefined)) { + return nullptr; + } + + auto access = sem_.GetAccess(tmpl_ident->arguments[1]); + if (DAWN_UNLIKELY(access == core::Access::kUndefined)) { + return nullptr; + } + + auto* out = b.Types().texel_buffer(format, access); + + if (DAWN_UNLIKELY(!validator_.TexelBuffer(out, ident->source))) { + return nullptr; + } + + return out; +} + +const ast::TemplatedIdentifier* Resolver::TemplatedIdentifier(const ast::Identifier* ident, + size_t min_args, + size_t max_args /* = use min 0 */) { + auto* tmpl_ident = ident->As(); + if (!tmpl_ident) { + if (DAWN_UNLIKELY(min_args != 0)) { + AddError(Source{ident->source.range.end}) << "expected " << style::Code("<") << " for " + << style::Code(ident->symbol.NameView()); + } + return nullptr; + } + return CheckTemplatedIdentifierArgs(tmpl_ident, min_args, max_args) ? tmpl_ident : nullptr; +} + +bool Resolver::CheckTemplatedIdentifierArgs(const ast::TemplatedIdentifier* ident, + size_t min_args, + size_t max_args /* = use min 0 */) { + if (max_args == 0) { + max_args = min_args; + } + if (min_args == max_args) { + if (DAWN_UNLIKELY(ident->arguments.Length() != min_args)) { + AddError(ident->source) << style::Code(ident->symbol.NameView()) << " requires " + << min_args << " template arguments"; + return false; + } + } else { + if (DAWN_UNLIKELY(ident->arguments.Length() < min_args)) { + AddError(ident->source) << style::Code(ident->symbol.NameView()) + << " requires at least " << min_args << " template arguments"; + return false; + } + if (DAWN_UNLIKELY(ident->arguments.Length() > max_args)) { + AddError(ident->source) << style::Code(ident->symbol.NameView()) << " requires at most " + << max_args << " template arguments"; + return false; + } + } + return ident != nullptr; +} + +size_t Resolver::NestDepth(const core::type::Type* ty) const { + return Switch( + ty, // + [](const core::type::Vector*) { return size_t{1}; }, + [](const core::type::Matrix*) { return size_t{2}; }, + [&](Default) { + if (auto d = nest_depth_.Get(ty)) { + return *d; + } + return size_t{0}; + }); +} + +sem::Call* Resolver::FunctionCall(const ast::CallExpression* expr, + sem::Function* target, + VectorRef args_in) { + Vector args = std::move(args_in); + if (!MaybeMaterializeAndLoadArguments(args, target)) { + return nullptr; + } + + auto stage = not_evaluated_.Contains(expr) ? core::EvaluationStage::kNotEvaluated + : core::EvaluationStage::kRuntime; + + auto* call = b.create(expr, target, stage, std::move(args), current_statement_, + /* constant_value */ nullptr); + + target->AddCallSite(call); + + if (!validator_.FunctionCall(call, current_statement_)) { + return nullptr; + } + + if (current_function_) { + // Note: Requires called functions to be resolved first. + // This is currently guaranteed as functions must be declared before + // use. + current_function_->AddTransitivelyCalledFunction(target); + current_function_->AddDirectCall(call); + for (auto* transitive_call : target->TransitivelyCalledFunctions()) { + current_function_->AddTransitivelyCalledFunction(transitive_call); + } + + // We inherit any referenced variables from the callee. + for (auto* var : target->TransitivelyReferencedGlobals()) { + current_function_->AddTransitivelyReferencedGlobal(var); + } + + if (!AliasAnalysis(call)) { + return nullptr; + } + } + + return call; +} + +sem::ValueExpression* Resolver::Literal(const ast::LiteralExpression* literal) { + auto* ty = Switch( + literal, + [&](const ast::IntLiteralExpression* i) -> core::type::Type* { + switch (i->suffix) { + case ast::IntLiteralExpression::Suffix::kNone: + return b.create(); + case ast::IntLiteralExpression::Suffix::kI: + return b.create(); + case ast::IntLiteralExpression::Suffix::kU: + return b.create(); + } + TINT_UNREACHABLE() << "Unhandled integer literal suffix: " << i->suffix; + }, + [&](const ast::FloatLiteralExpression* f) -> core::type::Type* { + switch (f->suffix) { + case ast::FloatLiteralExpression::Suffix::kNone: + return b.create(); + case ast::FloatLiteralExpression::Suffix::kF: + return b.create(); + case ast::FloatLiteralExpression::Suffix::kH: + return validator_.CheckF16Enabled(literal->source) ? b.create() + : nullptr; + } + TINT_UNREACHABLE() << "Unhandled float literal suffix: " << f->suffix; + }, + [&](const ast::BoolLiteralExpression*) { return b.create(); }, // + TINT_ICE_ON_NO_MATCH); + + if (ty == nullptr) { + return nullptr; + } + + const core::constant::Value* val = nullptr; + auto stage = core::EvaluationStage::kConstant; + if (not_evaluated_.Contains(literal)) { + stage = core::EvaluationStage::kNotEvaluated; + } + if (stage == core::EvaluationStage::kConstant) { + val = Switch( + literal, + [&](const ast::BoolLiteralExpression* lit) { return b.constants.Get(lit->value); }, + [&](const ast::IntLiteralExpression* lit) -> const core::constant::Value* { + switch (lit->suffix) { + case ast::IntLiteralExpression::Suffix::kNone: + return b.constants.Get(AInt(lit->value)); + case ast::IntLiteralExpression::Suffix::kI: + return b.constants.Get(i32(lit->value)); + case ast::IntLiteralExpression::Suffix::kU: + return b.constants.Get(u32(lit->value)); + } + return nullptr; + }, + [&](const ast::FloatLiteralExpression* lit) -> const core::constant::Value* { + switch (lit->suffix) { + case ast::FloatLiteralExpression::Suffix::kNone: + return b.constants.Get(AFloat(lit->value)); + case ast::FloatLiteralExpression::Suffix::kF: + return b.constants.Get(f32(lit->value)); + case ast::FloatLiteralExpression::Suffix::kH: + return b.constants.Get(f16(lit->value)); + } + return nullptr; + }); + } + return b.create(literal, ty, stage, current_statement_, std::move(val)); +} + +sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) { + auto* ident = expr->identifier; + Mark(ident); + + auto resolved = dependencies_.resolved_identifiers.Get(ident); + if (!resolved) { + ICE(expr->source) << "identifier '" << ident->symbol.NameView() << "' was not resolved"; + } + + if (auto* ast_node = resolved->Node()) { + auto* resolved_node = sem_.Get(ast_node); + return Switch( + resolved_node, // + [&](sem::Variable* variable) -> sem::VariableUser* { + if (!DAWN_LIKELY(CheckNotTemplated("variable", ident))) { + return nullptr; + } + + auto stage = variable->Stage(); + const core::constant::Value* value = variable->ConstantValue(); + if (not_evaluated_.Contains(expr)) { + // This expression is short-circuited by an ancestor expression. + // Do not const-eval. + stage = core::EvaluationStage::kNotEvaluated; + value = nullptr; + } + auto* user = + b.create(expr, stage, current_statement_, value, variable); + + if (current_statement_) { + // Check all parent continuing blocks to make sure that this is not a reference + // to a variable that is bypassed by a continue statement in a loop's body + // block. + auto* continuing_block = + current_statement_->FindFirstParent(); + while (continuing_block) { + auto* loop_block = + continuing_block->FindFirstParent(); + if (loop_block->FirstContinue()) { + // If our identifier is in loop_block->decls, make sure its index is + // less than first_continue + auto symbol = ident->symbol; + if (auto decl = loop_block->Decls().Get(symbol)) { + if (decl->order >= loop_block->NumDeclsAtFirstContinue()) { + AddError(loop_block->FirstContinue()->source) + << "continue statement bypasses declaration of '" + << symbol.NameView() << "'"; + AddNote(decl->variable->Declaration()->source) + << "identifier '" << symbol.NameView() << "' declared here"; + AddNote(expr->source) + << "identifier '" << symbol.NameView() + << "' referenced in continuing block here"; + return nullptr; + } + } + } + continuing_block = + continuing_block->Parent() + ->FindFirstParent(); + } + } + + if (auto* global = variable->As()) { + for (auto& fn : on_transitively_reference_global_) { + fn(global); + } + if (!current_function_ && variable->Declaration()->Is()) { + // Use of a module-scope 'var' outside of a function. + AddError(expr->source) + << style::Keyword("var ") << style::Variable(ident->symbol.NameView()) + << " cannot be referenced at module-scope"; + sem_.NoteDeclarationSource(variable->Declaration()); + return nullptr; + } + if (current_function_ && + subgroup_matrix_uses_.Contains(variable->Type()->UnwrapRef())) { + current_function_->SetDirectlyUsedSubgroupMatrix(&expr->source); + } + } + + variable->AddUser(user); + return user; + }, + [&](const core::type::Type* ty) -> sem::TypeExpression* { + // User declared types cannot be templated. + if (!DAWN_LIKELY(CheckNotTemplated("type", ident))) { + return nullptr; + } + + // Notify callers of all transitively referenced globals. + if (auto* arr = ty->As()) { + for (auto& fn : on_transitively_reference_global_) { + for (auto* ref : arr->TransitivelyReferencedOverrides()) { + fn(ref); + } + } + } + + if (current_function_ && subgroup_matrix_uses_.Contains(ty)) { + current_function_->SetDirectlyUsedSubgroupMatrix(&expr->source); + } + + return b.create(expr, current_statement_, ty); + }, + [&](const sem::Function* fn) -> sem::FunctionExpression* { + if (!DAWN_LIKELY(CheckNotTemplated("function", ident))) { + return nullptr; + } + return b.create(expr, current_statement_, fn); + }); + } + + if (auto builtin_ty = resolved->BuiltinType(); builtin_ty != core::BuiltinType::kUndefined) { + auto* ty = BuiltinType(builtin_ty, ident); + if (!ty) { + return nullptr; + } + return b.create(expr, current_statement_, ty); + } + + if (auto fn = resolved->BuiltinFn(); fn != wgsl::BuiltinFn::kNone) { + return b.create>(expr, current_statement_, fn); + } + + if (auto access = resolved->Access(); access != core::Access::kUndefined) { + return CheckNotTemplated("access", ident) + ? b.create>(expr, current_statement_, + access) + : nullptr; + } + + if (auto addr = resolved->AddressSpace(); addr != core::AddressSpace::kUndefined) { + return CheckNotTemplated("address space", ident) + ? b.create>( + expr, current_statement_, addr) + : nullptr; + } + + if (auto fmt = resolved->TexelFormat(); fmt != core::TexelFormat::kUndefined) { + return CheckNotTemplated("texel format", ident) + ? b.create>( + expr, current_statement_, fmt) + : nullptr; + } + + if (resolved->Unresolved()) { + return b.create(expr, current_statement_); + } + + TINT_UNREACHABLE() << "unhandled resolved identifier: " << resolved->String(); +} + +sem::ValueExpression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* expr) { + auto* object = sem_.GetVal(expr->object); + if (!object) { + return nullptr; + } + + auto* object_ty = object->Type(); + + auto* const memory_view = object_ty->As(); + const core::type::Type* storage_ty = object_ty->UnwrapRef(); + if (memory_view) { + if (memory_view->Is() && + (allowed_features_.features.count(wgsl::LanguageFeature::kPointerCompositeAccess) == + 0u)) { + AddError(expr->source) + << "pointer composite access requires the pointer_composite_access language " + "feature, which is not allowed in the current environment"; + return nullptr; + } + storage_ty = memory_view->StoreType(); + } + + auto* root_ident = object->RootIdentifier(); + + const core::type::Type* ty = nullptr; + + Mark(expr->member); + + return Switch( + storage_ty, // + [&](const core::type::Struct* str) -> sem::ValueExpression* { + auto symbol = expr->member->symbol; + + const core::type::StructMember* member = nullptr; + for (auto* m : str->Members()) { + if (m->Name() == symbol) { + member = m; + break; + } + } + + if (member == nullptr) { + AddError(expr->source) << "struct member " << symbol.NameView() << " not found"; + return nullptr; + } + + ty = member->Type(); + + // If we're extracting from a memory view, we return a reference. + if (memory_view) { + ty = b.create(memory_view->AddressSpace(), ty, + memory_view->Access()); + } + + const core::constant::Value* val = nullptr; + if (auto* obj_val = object->ConstantValue()) { + val = obj_val->Index(static_cast(member->Index())); + } + return b.create(expr, ty, current_statement_, val, object, + member, root_ident); + }, + + [&](const core::type::Vector* vec) -> sem::ValueExpression* { + std::string_view s = expr->member->symbol.NameView(); + auto size = s.size(); + Vector swizzle; + swizzle.Reserve(s.size()); + + for (auto c : s) { + switch (c) { + case 'x': + case 'r': + swizzle.Push(0u); + break; + case 'y': + case 'g': + swizzle.Push(1u); + break; + case 'z': + case 'b': + swizzle.Push(2u); + break; + case 'w': + case 'a': + swizzle.Push(3u); + break; + default: + AddError(expr->member->source.Begin() + + static_cast(swizzle.Length())) + << "invalid vector swizzle character"; + return nullptr; + } + + if (swizzle.Back() >= vec->Width()) { + AddError(expr->member->source) << "invalid vector swizzle member"; + return nullptr; + } + } + + if (size < 1 || size > 4) { + AddError(expr->member->source) << "invalid vector swizzle size"; + return nullptr; + } + + // All characters are valid, check if they're being mixed + auto is_rgba = [](char c) { return c == 'r' || c == 'g' || c == 'b' || c == 'a'; }; + auto is_xyzw = [](char c) { return c == 'x' || c == 'y' || c == 'z' || c == 'w'; }; + if (!std::all_of(s.begin(), s.end(), is_rgba) && + !std::all_of(s.begin(), s.end(), is_xyzw)) { + AddError(expr->member->source) + << "invalid mixing of vector swizzle characters rgba with xyzw"; + return nullptr; + } + + const sem::ValueExpression* obj_expr = object; + if (size == 1) { + // A single element swizzle is just the type of the vector. + ty = vec->Type(); + // If we're extracting from a memory view, we return a reference. + if (memory_view) { + ty = b.create(memory_view->AddressSpace(), ty, + memory_view->Access()); + } + } else { + // The vector will have a number of components equal to the length of + // the swizzle. + ty = b.create(vec->Type(), static_cast(size)); + + if (obj_expr->Type()->Is()) { + // If the LHS is a pointer, the load rule is invoked. We special case this + // because our usual handling of implicit loads assumes the expression has + // reference type. This expression also has an implicit dereference before the + // load, but we have no way of representing that, so we create the load directly + // from the pointer expression. + auto* load = + b.create(obj_expr, current_statement_, obj_expr->Stage()); + b.Sem().Replace(obj_expr->Declaration(), load); + + // Register the load for the alias analysis. + RegisterLoad(obj_expr); + + obj_expr = load; + } else { + // The load rule is invoked before the swizzle, if necessary. + obj_expr = Load(obj_expr); + } + } + const core::constant::Value* val = nullptr; + if (auto* obj_val = object->ConstantValue()) { + auto res = const_eval_.Swizzle(ty, obj_val, swizzle); + if (res != Success) { + return nullptr; + } + val = res.Get(); + } + return b.create(expr, ty, current_statement_, val, obj_expr, + std::move(swizzle), root_ident); + }, + + [&](Default) { + AddError(expr->object->source) + << "cannot index into expression of type '" << sem_.TypeNameOf(storage_ty) << "'"; + return nullptr; + }); +} + +sem::ValueExpression* Resolver::Binary(const ast::BinaryExpression* expr) { + const auto* lhs = sem_.GetVal(expr->lhs); + const auto* rhs = sem_.GetVal(expr->rhs); + if (!lhs || !rhs) { + return nullptr; + } + + // Load arguments if they are references + lhs = Load(lhs); + if (!lhs) { + return nullptr; + } + rhs = Load(rhs); + if (!rhs) { + return nullptr; + } + + auto stage = core::EarliestStage(lhs->Stage(), rhs->Stage()); + auto overload = intrinsic_table_.Lookup(expr->op, lhs->Type()->UnwrapRef(), + rhs->Type()->UnwrapRef(), stage, false); + if (overload != Success) { + AddError(expr->source) << overload.Failure(); + return nullptr; + } + + auto* res_ty = overload->return_type; + + // Parameter types + auto* lhs_ty = overload->parameters[0].type; + auto* rhs_ty = overload->parameters[1].type; + if (ShouldMaterializeArgument(lhs_ty)) { + lhs = Materialize(lhs, lhs_ty); + if (!lhs) { + return nullptr; + } + } + if (ShouldMaterializeArgument(rhs_ty)) { + rhs = Materialize(rhs, rhs_ty); + if (!rhs) { + return nullptr; + } + } + + if (!validator_.BinaryExpression(expr, expr->op, lhs, rhs)) { + return nullptr; + } + + const core::constant::Value* value = nullptr; + if (not_evaluated_.Contains(expr)) { + // This expression is short-circuited by an ancestor expression. + // Do not const-eval. + stage = core::EvaluationStage::kNotEvaluated; + } else if (lhs->Stage() == core::EvaluationStage::kConstant && + rhs->Stage() == core::EvaluationStage::kNotEvaluated) { + // Short-circuiting binary expression. Use the LHS value and stage. + value = lhs->ConstantValue(); + stage = core::EvaluationStage::kConstant; + } else if (stage == core::EvaluationStage::kConstant) { + // Both LHS and RHS have expressions that are constant evaluation stage. + auto const_eval_fn = overload->const_eval_fn; + if (const_eval_fn) { // Do we have a @const operator? + // Yes. Perform any required abstract argument values implicit conversions to the + // overload parameter types, and const-eval. + Vector const_args{lhs->ConstantValue(), rhs->ConstantValue()}; + // Implicit conversion (e.g. AInt -> AFloat) + if (!Convert(const_args[0], lhs_ty, lhs->Declaration()->source)) { + return nullptr; + } + if (!Convert(const_args[1], rhs_ty, rhs->Declaration()->source)) { + return nullptr; + } + auto r = (const_eval_.*const_eval_fn)(res_ty, const_args, expr->source); + if (r != Success) { + return nullptr; + } + value = r.Get(); + } else { + // The arguments have constant values, but the operator cannot be const-evaluated. + // This can only be evaluated at runtime. + stage = core::EvaluationStage::kRuntime; + } + } + + auto* sem = b.create(expr, res_ty, stage, current_statement_, value); + return sem; +} + +sem::ValueExpression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) { + const auto* expr = sem_.GetVal(unary->expr); + if (!expr) { + return nullptr; + } + auto* expr_ty = expr->Type(); + + const core::type::Type* ty = nullptr; + const sem::Variable* root_ident = nullptr; + const core::constant::Value* value = nullptr; + auto stage = core::EvaluationStage::kRuntime; + + switch (unary->op) { + case core::UnaryOp::kAddressOf: + if (auto* ref = expr_ty->As()) { + if (ref->StoreType()->UnwrapRef()->IsHandle()) { + AddError(unary->expr->source) + << "cannot take the address of " << sem_.Describe(expr) + << " in handle address space"; + return nullptr; + } + + auto* array = unary->expr->As(); + auto* member = unary->expr->As(); + if ((array && + sem_.TypeOf(array->object)->UnwrapPtrOrRef()->Is()) || + (member && + sem_.TypeOf(member->object)->UnwrapPtrOrRef()->Is())) { + AddError(unary->expr->source) + << "cannot take the address of a vector component"; + return nullptr; + } + + ty = b.create(ref->AddressSpace(), ref->StoreType(), + ref->Access()); + + root_ident = expr->RootIdentifier(); + } else { + AddError(unary->expr->source) + << "cannot take the address of " << sem_.Describe(expr); + return nullptr; + } + break; + + case core::UnaryOp::kIndirection: + if (auto* ptr = expr_ty->As()) { + ty = b.create(ptr->AddressSpace(), ptr->StoreType(), + ptr->Access()); + root_ident = expr->RootIdentifier(); + } else { + AddError(unary->expr->source) << "cannot dereference expression of type " + << style::Type(sem_.TypeNameOf(expr_ty)); + return nullptr; + } + break; + + default: { + stage = expr->Stage(); + auto overload = intrinsic_table_.Lookup(unary->op, expr_ty->UnwrapRef(), stage); + if (overload != Success) { + AddError(unary->source) << overload.Failure(); + return nullptr; + } + ty = overload->return_type; + auto* param_ty = overload->parameters[0].type; + if (ShouldMaterializeArgument(param_ty)) { + expr = Materialize(expr, param_ty); + if (!expr) { + return nullptr; + } + } + + // Load expr if it is a reference + expr = Load(expr); + if (!expr) { + return nullptr; + } + + stage = expr->Stage(); + if (stage == core::EvaluationStage::kConstant) { + if (auto const_eval_fn = overload->const_eval_fn) { + auto r = (const_eval_.*const_eval_fn)(ty, Vector{expr->ConstantValue()}, + expr->Declaration()->source); + if (r != Success) { + return nullptr; + } + value = r.Get(); + } else { + stage = core::EvaluationStage::kRuntime; + } + } + break; + } + } + + auto* sem = + b.create(unary, ty, stage, current_statement_, value, root_ident); + return sem; +} + +tint::Result Resolver::LocationAttribute(const ast::LocationAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@location value"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return Failure{}; + } + + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) << style::Attribute("@location") << " must be an " + << style::Type("i32") << " or " << style::Type("u32") << " value"; + return Failure{}; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value < 0) { + AddError(attr->source) << style::Attribute("@location") << " value must be non-negative"; + return Failure{}; + } + + return static_cast(value); +} + +tint::Result Resolver::ColorAttribute(const ast::ColorAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@color value"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return Failure{}; + } + + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) << style::Attribute("@color") << " must be an " << style::Type("i32") + << " or " << style::Type("u32") << " value"; + return Failure{}; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value < 0) { + AddError(attr->source) << style::Attribute("@color") << " value must be non-negative"; + return Failure{}; + } + + return static_cast(value); +} +tint::Result Resolver::BlendSrcAttribute(const ast::BlendSrcAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@blend_src value"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return Failure{}; + } + + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) << style::Attribute("@blend_src") << " value must be " + << style::Type("i32") << " or " << style::Type("u32"); + return Failure{}; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value != 0 && value != 1) { + AddError(attr->source) << style::Attribute("@blend_src") << " value must be zero or one"; + return Failure{}; + } + + return static_cast(value); +} + +tint::Result Resolver::BindingAttribute(const ast::BindingAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@binding"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return Failure{}; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) << style::Attribute("@binding") << " must be an " + << style::Type("i32") << " or " << style::Type("u32") << " value"; + return Failure{}; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value < 0) { + AddError(attr->source) << style::Attribute("@binding") << " value must be non-negative"; + return Failure{}; + } + return static_cast(value); +} + +tint::Result Resolver::GroupAttribute(const ast::GroupAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@group"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return Failure{}; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) << style::Attribute("@group") << " must be an " << style::Type("i32") + << " or " << style::Type("u32") << " value"; + return Failure{}; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value < 0) { + AddError(attr->source) << style::Attribute("@group") << " value must be non-negative"; + return Failure{}; + } + return static_cast(value); +} + +tint::Result Resolver::InputAttachmentIndexAttribute( + const ast::InputAttachmentIndexAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@input_attachment_index"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return Failure{}; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) << style::Attribute("@input_attachment_index") << " must be an " + << style::Type("i32") << " or " << style::Type("u32") << " value"; + return Failure{}; + } + + auto const_value = materialized->ConstantValue(); + auto value = const_value->ValueAs(); + if (value < 0) { + AddError(attr->source) << style::Attribute("@input_attachment_index") + << " value must be non-negative"; + return Failure{}; + } + return static_cast(value); +} + +tint::Result Resolver::WorkgroupAttribute(const ast::WorkgroupAttribute* attr) { + // Set work-group size defaults. + sem::WorkgroupSize ws; + for (size_t i = 0; i < 3; i++) { + ws[i] = 1; + } + + auto values = attr->Values(); + Vector args; + Vector arg_tys; + + auto err_bad_expr = [&](const ast::Expression* value) { + AddError(value->source) << style::Attribute("@workgroup_size") + << " argument must be a constant or override-expression of type " + << style::Type("abstract-integer") << ", " << style::Type("i32") + << " or " << style::Type("u32"); + }; + + for (size_t i = 0; i < 3; i++) { + // Each argument to this attribute can either be a literal, an identifier for a + // module-scope constants, a const-expression, or nullptr if not specified. + auto* value = values[i]; + if (!value) { + break; + } + const auto* expr = ValueExpression(value); + if (!expr) { + return Failure{}; + } + auto* ty = expr->Type(); + if (!ty->IsAnyOf()) { + err_bad_expr(value); + return Failure{}; + } + + if (expr->Stage() != core::EvaluationStage::kConstant && + expr->Stage() != core::EvaluationStage::kOverride) { + err_bad_expr(value); + return Failure{}; + } + + args.Push(expr); + arg_tys.Push(ty); + } + + auto* common_ty = core::type::Type::Common(arg_tys); + if (!common_ty) { + AddError(attr->source) << style::Attribute("@workgroup_size") + << " arguments must be of the same type, either " + << style::Type("i32") << " or " << style::Type("u32"); + return Failure{}; + } + + // If all arguments are abstract-integers, then materialize to i32. + if (common_ty->Is()) { + common_ty = b.create(); + } + + for (size_t i = 0; i < args.Length(); i++) { + auto* materialized = Materialize(args[i], common_ty); + if (!materialized) { + return Failure{}; + } + if (auto* value = materialized->ConstantValue()) { + if (value->ValueAs() < 1) { + AddError(values[i]->source) + << style::Attribute("@workgroup_size") << " argument must be at least 1"; + return Failure{}; + } + ws[i] = value->ValueAs(); + } else { + ws[i] = std::nullopt; + } + } + + uint64_t total_size = static_cast(ws[0].value_or(1)); + for (size_t i = 1; i < 3; i++) { + total_size *= static_cast(ws[i].value_or(1)); + if (total_size > 0xffffffff) { + AddError(values[i]->source) << "total workgroup grid size cannot exceed 0xffffffff"; + return Failure{}; + } + } + + return ws; +} + +tint::Result Resolver::SubgroupSizeAttribute(const ast::SubgroupSizeAttribute* attr) { + auto value = attr->subgroup_size; + + auto err_bad_expr = [&]() { + AddError(attr->source) << style::Attribute("@subgroup_size") + << " argument must be a constant or override-expression of type " + << style::Type("abstract-integer") << ", " << style::Type("i32") + << " or " << style::Type("u32"); + }; + + const auto* expr = ValueExpression(value); + if (!expr) { + return Failure{}; + } + auto* type = expr->Type(); + if (!type->IsAnyOf()) { + err_bad_expr(); + return Failure{}; + } + + if (expr->Stage() != core::EvaluationStage::kConstant && + expr->Stage() != core::EvaluationStage::kOverride) { + err_bad_expr(); + return Failure{}; + } + + // If all arguments are abstract-integers, then materialize to i32. + if (type->Is()) { + type = b.create(); + } + + auto* materialized = Materialize(expr, type); + if (!materialized) { + return Failure{}; + } + + uint32_t subgroup_size = 0u; + if (auto* constant_value = materialized->ConstantValue()) { + if (constant_value->ValueAs() < 1) { + AddError(attr->source) + << style::Attribute("@subgroup_size") << " argument must be at least 1"; + return Failure{}; + } + subgroup_size = constant_value->ValueAs(); + if (!IsPowerOfTwo(subgroup_size)) { + AddError(attr->source) + << style::Attribute("@subgroup_size") << " argument must be a power of 2"; + return Failure{}; + } + } + + return subgroup_size; +} + +bool Resolver::DiagnosticAttribute(const ast::DiagnosticAttribute* attr) { + return DiagnosticControl(attr->control); +} + +bool Resolver::StageAttribute(const ast::StageAttribute*) { + return true; +} + +bool Resolver::MustUseAttribute(const ast::MustUseAttribute*) { + return true; +} + +bool Resolver::InvariantAttribute(const ast::InvariantAttribute*) { + return true; +} + +bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) { + Mark(control.rule_name); + Mark(control.rule_name->name); + auto name = control.rule_name->name->symbol.NameView(); + + if (control.rule_name->category) { + Mark(control.rule_name->category); + if (control.rule_name->category->symbol.NameView() == "chromium") { + auto rule = wgsl::ParseChromiumDiagnosticRule(name); + if (rule != wgsl::ChromiumDiagnosticRule::kUndefined) { + validator_.DiagnosticFilters().Set(rule, control.severity); + } else { + auto& warning = AddWarning(control.rule_name->source) + << "unrecognized diagnostic rule " << style::Code("chromium.", name) + << "\n"; + tint::SuggestAlternativeOptions opts; + opts.prefix = "chromium."; + tint::SuggestAlternatives(name, wgsl::kChromiumDiagnosticRuleStrings, + warning.message, opts); + } + } + return true; + } + + auto rule = wgsl::ParseCoreDiagnosticRule(name); + if (rule != wgsl::CoreDiagnosticRule::kUndefined) { + validator_.DiagnosticFilters().Set(rule, control.severity); + } else { + auto& warning = AddWarning(control.rule_name->source) + << "unrecognized diagnostic rule " << style::Code(name) << "\n"; + tint::SuggestAlternatives(name, wgsl::kCoreDiagnosticRuleStrings, warning.message); + } + return true; +} + +bool Resolver::Enable(const ast::Enable* enable) { + for (auto* ext : enable->extensions) { + Mark(ext); + enabled_extensions_.Add(ext->name); + if (!allowed_features_.extensions.count(ext->name)) { + AddError(ext->source) << "extension " << style::Code(ext->name) + << " is not allowed in the current environment"; + return false; + } + } + return true; +} + +bool Resolver::Requires(const ast::Requires* req) { + for (auto feature : req->features) { + if (!allowed_features_.features.count(feature)) { + AddError(req->source) << "language feature " << style::Code(wgsl::ToString(feature)) + << " is not allowed in the current environment"; + return false; + } + } + return true; +} + +const core::type::Type* Resolver::TypeDecl(const ast::TypeDecl* named_type) { + Mark(named_type->name); + + const core::type::Type* result = nullptr; + if (auto* alias = named_type->As()) { + result = Alias(alias); + } else if (auto* str = named_type->As()) { + result = Structure(str); + } else { + TINT_UNREACHABLE() << "Unhandled TypeDecl"; + } + + if (!result) { + return nullptr; + } + + b.Sem().Add(named_type, result); + return result; +} + +const core::type::ArrayCount* Resolver::ArrayCount(const ast::Expression* count_expr, bool array) { + const std::string count_kind = array ? "array count" : "buffer size"; + // Evaluate the constant array count expression. + const auto* count_sem = Materialize(sem_.GetVal(count_expr)); + if (!count_sem) { + return nullptr; + } + + switch (count_sem->Stage()) { + case core::EvaluationStage::kNotEvaluated: + ICE(count_expr->source) << "array element count was not evaluated"; + + case core::EvaluationStage::kOverride: { + // array count is an override expression. + // Is the count a named 'override'? + if (auto* user = count_sem->UnwrapMaterialize()->As()) { + if (auto* global = user->Variable()->As()) { + return b.create(global); + } + } + return b.create(count_sem); + } + + case core::EvaluationStage::kConstant: { + auto* count_val = count_sem->ConstantValue(); + if (auto* ty = count_val->Type(); !ty->IsIntegerScalar()) { + AddError(count_expr->source) + << count_kind << " must evaluate to a constant integer expression, but is type " + << style::Type(ty->FriendlyName()); + return nullptr; + } + + int64_t count = count_val->ValueAs(); + if (count < 1) { + AddError(count_expr->source) + << count_kind << " (" << count << ") must be greater than 0"; + return nullptr; + } + + return b.create(static_cast(count)); + } + + default: { + AddError(count_expr->source) << count_kind + << " must evaluate to a constant integer expression " + "or override variable"; + return nullptr; + } + } +} + +sem::Array* Resolver::Array(const Source& array_source, + const Source& el_source, + const Source& count_source, + const core::type::Type* el_ty, + const core::type::ArrayCount* el_count) { + uint32_t el_size = el_ty->Size(); + uint64_t implicit_stride = el_size ? tint::RoundUp(el_ty->Align(), el_size) : 0; + uint64_t size = 0; + + if (auto const_count = el_count->As()) { + size = const_count->value * implicit_stride; + if (size > std::numeric_limits::max()) { + AddError(count_source) << "array byte size (0x" << std::hex << size + << ") must not exceed 0xffffffff bytes"; + return nullptr; + } + } else if (el_count->Is()) { + size = implicit_stride; + } + auto* out = b.create(el_ty, el_count, static_cast(size)); + + // Maximum nesting depth of composite types + // https://gpuweb.github.io/gpuweb/wgsl/#limits + const size_t nest_depth = 1 + NestDepth(el_ty); + if (nest_depth > kMaxNestDepthOfCompositeType) { + AddError(array_source) << "array has nesting depth of " << nest_depth << ", maximum is " + << kMaxNestDepthOfCompositeType; + return nullptr; + } + nest_depth_.Add(out, nest_depth); + + if (!validator_.Array(out, el_source)) { + return nullptr; + } + + return out; +} + +const core::type::Type* Resolver::Alias(const ast::Alias* alias) { + auto* ty = Type(alias->type); + if (DAWN_UNLIKELY(!ty)) { + return nullptr; + } + if (DAWN_UNLIKELY(!validator_.Alias(alias))) { + return nullptr; + } + return ty; +} + +sem::Struct* Resolver::Structure(const ast::Struct* str) { + auto struct_name = [&] { // + return str->name->symbol.NameView(); + }; + + // Maximum number of members in a structure type + // https://gpuweb.github.io/gpuweb/wgsl/#limits + const size_t kMaxNumStructMembers = 16383; + if (str->members.Length() > kMaxNumStructMembers) { + AddError(str->source) << style::Keyword("struct ") << style::Type(struct_name()) << " has " + << str->members.Length() << " members, maximum is " + << kMaxNumStructMembers; + return nullptr; + } + + if (!validator_.NoDuplicateAttributes(str->attributes)) { + return nullptr; + } + + if (!str->attributes.IsEmpty()) { + ErrorInvalidAttribute(str->attributes[0], + StyledText{} << style::Keyword("struct") << " declarations"); + return nullptr; + } + + Vector sem_members; + sem_members.Reserve(str->members.Length()); + + // Calculate the effective size and alignment of each field, and the overall size of the + // structure. For size, use the size attribute if provided, otherwise use the default size + // for the type. For alignment, use the alignment attribute if provided, otherwise use the + // default alignment for the member type. Diagnostic errors are raised if a basic rule is + // violated. Validation of storage-class rules requires analyzing the actual variable usage + // of the structure, and so is performed as part of the variable validation. + uint64_t struct_size = 0; + uint64_t struct_align = 1; + Hashmap member_map; + + size_t members_nest_depth = 0; + for (auto* member : str->members) { + Mark(member); + Mark(member->name); + if (auto added = member_map.Add(member->name->symbol, member); !added) { + AddError(member->source) + << "redefinition of " << style::Code(member->name->symbol.NameView()); + AddNote(added.value->source) << "previous definition is here"; + return nullptr; + } + + // Resolve member type + auto type = Type(member->type); + if (!type) { + return nullptr; + } + + members_nest_depth = std::max(members_nest_depth, NestDepth(type)); + + // validator_.Validate member type + if (!validator_.IsPlain(type)) { + AddError(member->source) + << sem_.TypeNameOf(type) << " cannot be used as the type of a structure member"; + return nullptr; + } + + uint64_t offset = struct_size; + uint64_t align = type->Align(); + uint64_t size = type->Size(); + + if (!validator_.NoDuplicateAttributes(member->attributes)) { + return nullptr; + } + + bool has_align_attr = false; + bool has_size_attr = false; + core::IOAttributes attributes; + for (auto* attribute : member->attributes) { + Mark(attribute); + bool ok = Switch( + attribute, // + [&](const ast::StructMemberAlignAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@align"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return false; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) + << style::Attribute("@align") << " value must be an " + << style::Type("i32") << " or " << style::Type("u32"); + return false; + } + + auto const_value = materialized->ConstantValue(); + if (!const_value) { + AddError(attr->source) + << style::Attribute("@align") << " value must be constant expression"; + return false; + } + auto value = const_value->ValueAs(); + + if (value <= 0 || !tint::IsPowerOfTwo(value)) { + AddError(attr->source) << style::Attribute("@align") + << " value must be a positive, power-of-two integer"; + return false; + } + align = u32(value); + has_align_attr = true; + return true; + }, + [&](const ast::StructMemberSizeAttribute* attr) { + ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@size"}; + TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); + + auto* materialized = Materialize(ValueExpression(attr->expr)); + if (!materialized) { + return false; + } + if (!materialized->Type()->IsAnyOf()) { + AddError(attr->source) + << style::Attribute("@size") << " value must be an " + << style::Type("i32") << " or " << style::Type("u32"); + return false; + } + + auto const_value = materialized->ConstantValue(); + if (!const_value) { + AddError(attr->expr->source) + << style::Attribute("@size") << " value must be constant expression"; + return false; + } + { + auto value = const_value->ValueAs(); + if (value <= 0) { + AddError(attr->source) + << style::Attribute("@size") << " value must be a positive integer"; + return false; + } + } + auto value = const_value->ValueAs(); + if (value < size) { + AddError(attr->source) + << style::Attribute("@size") + << " must be at least as big as the type's size (" << size << ")"; + return false; + } + size = u32(value); + has_size_attr = true; + return true; + }, + [&](const ast::LocationAttribute* attr) { + auto value = LocationAttribute(attr); + if (value != Success) { + return false; + } + attributes.location = value.Get(); + return true; + }, + [&](const ast::BlendSrcAttribute* attr) { + auto value = BlendSrcAttribute(attr); + if (value != Success) { + return false; + } + attributes.blend_src = value.Get(); + return true; + }, + [&](const ast::ColorAttribute* attr) { + auto value = ColorAttribute(attr); + if (value != Success) { + return false; + } + attributes.color = value.Get(); + return true; + }, + [&](const ast::BuiltinAttribute* attr) { + attributes.builtin = attr->builtin; + attributes.depth_mode = attr->depth_mode; + return true; + }, + [&](const ast::InterpolateAttribute* attr) { + attributes.interpolation = attr->interpolation; + return true; + }, + [&](const ast::InvariantAttribute* attr) { + if (!InvariantAttribute(attr)) { + return false; + } + attributes.invariant = true; + return true; + }, + [&](Default) { + ErrorInvalidAttribute(attribute, + StyledText{} << style::Keyword("struct") << " members"); + return false; + }); + if (!ok) { + return nullptr; + } + } + + offset = tint::RoundUp(align, offset); + if (offset > std::numeric_limits::max()) { + AddError(member->source) + << "struct member offset (0x" << std::hex << offset << ") must not exceed 0x" + << std::hex << std::numeric_limits::max() << " bytes"; + return nullptr; + } + + auto* sem_member = b.create( + member, member->name->symbol, type, static_cast(sem_members.Length()), + static_cast(offset), static_cast(align), + static_cast(size), attributes); + b.Sem().Add(member, sem_member); + sem_members.Push(sem_member); + + struct_size = offset + size; + struct_align = std::max(struct_align, align); + } + + struct_size = tint::RoundUp(struct_align, struct_size); + + if (struct_size > std::numeric_limits::max()) { + AddError(str->source) << "struct size (0x" << std::hex << struct_size + << ") must not exceed 0xffffffff bytes"; + return nullptr; + } + if (DAWN_UNLIKELY(struct_align > std::numeric_limits::max())) { + ICE(str->source) << "calculated struct stride exceeds uint32"; + } + + auto* out = b.create(str, str->name->symbol, std::move(sem_members), + static_cast(struct_size)); + + for (size_t i = 0; i < sem_members.Length(); i++) { + auto* mem_type = sem_members[i]->Type(); + if (mem_type->Is()) { + atomic_composite_info_.Add(out, &sem_members[i]->Declaration()->source); + } else { + if (auto found = atomic_composite_info_.Get(mem_type)) { + atomic_composite_info_.Add(out, *found); + } + } + if (subgroup_matrix_uses_.Contains(mem_type)) { + subgroup_matrix_uses_.Add(out); + } + + const_cast(sem_members[i])->SetStruct(out); + } + + auto stage = current_function_ ? current_function_->Declaration()->PipelineStage() + : ast::PipelineStage::kNone; + if (!validator_.Structure(out, stage)) { + return nullptr; + } + + // Maximum nesting depth of composite types + // https://gpuweb.github.io/gpuweb/wgsl/#limits + const size_t nest_depth = 1 + members_nest_depth; + if (nest_depth > kMaxNestDepthOfCompositeType) { + AddError(str->source) << style::Keyword("struct ") << style::Type(struct_name()) + << " has nesting depth of " << nest_depth << ", maximum is " + << kMaxNestDepthOfCompositeType; + return nullptr; + } + nest_depth_.Add(out, nest_depth); + + return out; +} + +sem::Statement* Resolver::ReturnStatement(const ast::ReturnStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto& behaviors = current_statement_->Behaviors(); + behaviors = sem::Behavior::kReturn; + + const core::type::Type* value_ty = nullptr; + if (auto* value = stmt->value) { + const auto* expr = Load(ValueExpression(value)); + if (!expr) { + return false; + } + if (auto* ret_ty = current_function_->ReturnType(); !ret_ty->Is()) { + expr = Materialize(expr, ret_ty); + if (!expr) { + return false; + } + } + value_ty = expr->Type(); + } else { + value_ty = b.create(); + } + + // Validate after processing the return value expression so that its type + // is available for validation. + return validator_.Return(stmt, current_function_->ReturnType(), value_ty, + current_statement_); + }); +} + +sem::SwitchStatement* Resolver::SwitchStatement(const ast::SwitchStatement* stmt) { + auto* sem = + b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto& behaviors = sem->Behaviors(); + + const auto* cond = Load(ValueExpression(stmt->condition)); + if (!cond) { + return false; + } + // Each case clause will contribute behaviors. Switches must + // have at least a default clause, so we'll always end up with + // a non-empty behaviour set. + behaviors = behaviors - sem::Behavior::kNext; + + auto* cond_ty = cond->Type(); + + // Determine the common type across all selectors and the switch expression + // This must materialize to an integer scalar (non-abstract). + Vector types; + types.Push(cond_ty); + for (auto* case_stmt : stmt->body) { + for (auto* sel : case_stmt->selectors) { + if (sel->IsDefault()) { + continue; + } + auto* sem_expr = ValueExpression(sel->expr); + if (!sem_expr) { + return false; + } + types.Push(sem_expr->Type()->UnwrapRef()); + } + } + auto* common_ty = core::type::Type::Common(types); + if (!common_ty || !common_ty->IsIntegerScalar()) { + // No common type found or the common type was abstract. + // Pick i32 and let validation deal with any mismatches. + common_ty = b.create(); + } + cond = Materialize(cond, common_ty); + if (!cond) { + return false; + } + + // Handle switch body attributes. + for (auto* attribute : stmt->body_attributes) { + Mark(attribute); + bool ok = Switch( + attribute, + [&](const ast::DiagnosticAttribute* attr) { return DiagnosticAttribute(attr); }, + [&](Default) { + ErrorInvalidAttribute(attribute, + StyledText{} << style::Keyword("switch") << " body"); + return false; + }); + if (!ok) { + return false; + } + } + if (!validator_.NoDuplicateAttributes(stmt->body_attributes)) { + return false; + } + + Vector cases; + cases.Reserve(stmt->body.Length()); + for (auto* case_stmt : stmt->body) { + Mark(case_stmt); + auto* c = CaseStatement(case_stmt, common_ty); + if (!c) { + return false; + } + cases.Push(c); + behaviors.Add(c->Behaviors()); + sem->Cases().emplace_back(c); + + ApplyDiagnosticSeverities(c); + } + + if (behaviors.Contains(sem::Behavior::kBreak)) { + behaviors.Add(sem::Behavior::kNext); + } + behaviors.Remove(sem::Behavior::kBreak); + + return validator_.SwitchStatement(stmt); + }); +} + +sem::Statement* Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + Mark(stmt->variable); + + auto* variable = Variable(stmt->variable, /* is_global */ false); + if (!variable) { + return false; + } + + current_compound_statement_->AddDecl(variable->As()); + + return validator_.LocalVariable(variable); + }); +} + +sem::Statement* Resolver::AssignmentStatement(const ast::AssignmentStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto* lhs = ValueExpression(stmt->lhs); + if (!lhs) { + return false; + } + + const bool is_phony_assignment = stmt->lhs->Is(); + + const auto* rhs = ValueExpression(stmt->rhs); + if (!rhs) { + return false; + } + + if (!is_phony_assignment) { + rhs = Materialize(rhs, lhs->Type()->UnwrapRef()); + if (!rhs) { + return false; + } + } + + rhs = Load(rhs); + if (!rhs) { + return false; + } + + if (!is_phony_assignment) { + RegisterStore(lhs); + } + + return validator_.Assignment(stmt, sem_.TypeOf(stmt->rhs)); + }); +} + +sem::Statement* Resolver::BreakStatement(const ast::BreakStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + sem->Behaviors() = sem::Behavior::kBreak; + + return validator_.BreakStatement(sem, current_statement_); + }); +} + +sem::Statement* Resolver::BreakIfStatement(const ast::BreakIfStatement* stmt) { + auto* sem = + b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto* cond = Load(ValueExpression(stmt->condition)); + if (!cond) { + return false; + } + sem->SetCondition(cond); + sem->Behaviors().Add(sem::Behavior::kBreak); + + return validator_.BreakIfStatement(sem, current_statement_); + }); +} + +sem::Statement* Resolver::CallStatement(const ast::CallStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + if (ValueExpression(stmt->expr)) { + return true; + } + return false; + }); +} + +sem::Statement* Resolver::CompoundAssignmentStatement( + const ast::CompoundAssignmentStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto* lhs = ValueExpression(stmt->lhs); + if (!lhs) { + return false; + } + + const auto* rhs = ValueExpression(stmt->rhs); + if (!rhs) { + return false; + } + + RegisterStore(lhs); + + auto stage = core::EarliestStage(lhs->Stage(), rhs->Stage()); + + auto overload = intrinsic_table_.Lookup(stmt->op, lhs->Type()->UnwrapRef(), + rhs->Type()->UnwrapRef(), stage, true); + if (overload != Success) { + AddError(stmt->source) << overload.Failure(); + return false; + } + + // Load or materialize the RHS if necessary. + rhs = Load(Materialize(rhs, overload->parameters[1].type)); + if (!rhs) { + return false; + } + + return validator_.Assignment(stmt, overload->return_type); + }); +} + +sem::Statement* Resolver::ContinueStatement(const ast::ContinueStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + sem->Behaviors() = sem::Behavior::kContinue; + + // Set if we've hit the first continue statement in our parent loop + if (auto* block = sem->FindFirstParent()) { + if (!block->FirstContinue()) { + const_cast(block)->SetFirstContinue( + stmt, block->Decls().Count()); + } + } + + return validator_.ContinueStatement(sem, current_statement_); + }); +} + +sem::Statement* Resolver::DiscardStatement(const ast::DiscardStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + current_function_->SetDiscardStatement(sem); + return true; + }); +} + +sem::Statement* Resolver::IncrementDecrementStatement( + const ast::IncrementDecrementStatement* stmt) { + auto* sem = b.create(stmt, current_compound_statement_, current_function_); + return StatementScope(stmt, sem, [&] { + auto* lhs = ValueExpression(stmt->lhs); + if (!lhs) { + return false; + } + RegisterStore(lhs); + + return validator_.IncrementDecrementStatement(stmt); + }); +} + +bool Resolver::ApplyAddressSpaceUsageToType(core::AddressSpace address_space, + const core::type::Type* ty, + const Source& usage) { + ty = const_cast(ty->UnwrapRef()); + + if (auto* str = const_cast(ty->As())) { + if (str->AddressSpaceUsage().Contains(address_space)) { + return true; // Already applied + } + + str->AddUsage(address_space); + + for (auto* member : str->Members()) { + auto decl = member->Declaration(); + if (decl && !ApplyAddressSpaceUsageToType(address_space, + const_cast(member->Type()), + decl->type->source)) { + AddNote(member->Declaration()->source) + << "while analyzing structure member " << sem_.TypeNameOf(str) << "." + << member->Name().Name(); + return false; + } + } + return true; + } + + if (auto* arr = ty->As()) { + if (address_space != core::AddressSpace::kStorage) { + if (arr->Count()->Is()) { + AddError(usage) + << "runtime-sized arrays can only be used in the address space"; + return false; + } + + auto count = arr->ConstantCount(); + if (count.has_value() && count.value() >= internal_limits::kMaxArrayElementCount) { + AddError(usage) << "array count (" << count.value() << ") must be less than " + << internal_limits::kMaxArrayElementCount; + return false; + } + } + if (address_space != core::AddressSpace::kWorkgroup) { + if (arr->Count() + ->IsAnyOf()) { + AddError(usage) + << "override-sized arrays can only be used in the address space"; + return false; + } + } + + return ApplyAddressSpaceUsageToType(address_space, + const_cast(arr->ElemType()), usage); + } + + // Subgroup matrix types can only be declared in the `function` address space, or in value + // declarations (the `undefined` address space). + if (ty->Is() && address_space != core::AddressSpace::kUndefined && + address_space != core::AddressSpace::kFunction) { + AddError(usage) << "subgroup matrix types cannot be declared in the " + << style::Enum(address_space) << " address space"; + return false; + } + + if (ty->Is() && address_space != core::AddressSpace::kStorage && + address_space != core::AddressSpace::kUniform && + address_space != core::AddressSpace::kWorkgroup) { + AddError(usage) << "buffer types cannot be declared in the " << style::Enum(address_space) + << " address space"; + } + + if (core::IsHostShareable(address_space) && !ty->IsHostShareable()) { + AddError(usage) << "type " << style::Type(sem_.TypeNameOf(ty)) + << " cannot be used in address space " << style::Enum(address_space) + << " as it is non-host-shareable"; + return false; + } + + return true; +} + +template +SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback) { + b.Sem().Add(ast, sem); + + auto* as_compound = + As(sem); + + // Helper to handle attributes that are supported on certain types of statement. + auto handle_attributes = [&](auto* stmt, sem::Statement* sem_stmt, const char* use) { + for (auto* attribute : stmt->attributes) { + Mark(attribute); + bool ok = Switch( + attribute, // + [&](const ast::DiagnosticAttribute* attr) { return DiagnosticAttribute(attr); }, + [&](Default) { + ErrorInvalidAttribute(attribute, StyledText{} << use); + return false; + }); + if (!ok) { + return false; + } + } + if (!validator_.NoDuplicateAttributes(stmt->attributes)) { + return false; + } + ApplyDiagnosticSeverities(sem_stmt); + return true; + }; + + // Handle attributes, if necessary. + // Some statements can take diagnostic filtering attributes, so push a new diagnostic filter + // scope to capture them. + validator_.DiagnosticFilters().Push(); + TINT_DEFER(validator_.DiagnosticFilters().Pop()); + if (!Switch( + ast, // + [&](const ast::BlockStatement* block) { + return handle_attributes(block, sem, "block statements"); + }, + [&](const ast::ForLoopStatement* f) { + return handle_attributes(f, sem, "for statements"); + }, + [&](const ast::IfStatement* i) { return handle_attributes(i, sem, "if statements"); }, + [&](const ast::LoopStatement* l) { + return handle_attributes(l, sem, "loop statements"); + }, + [&](const ast::SwitchStatement* s) { + return handle_attributes(s, sem, "switch statements"); + }, + [&](const ast::WhileStatement* w) { + return handle_attributes(w, sem, "while statements"); + }, + [&](Default) { return true; })) { + return nullptr; + } + + TINT_SCOPED_ASSIGNMENT(current_statement_, sem); + TINT_SCOPED_ASSIGNMENT(current_compound_statement_, + as_compound ? as_compound : current_compound_statement_); + TINT_SCOPED_ASSIGNMENT(current_scoping_depth_, current_scoping_depth_ + 1); + + if (current_scoping_depth_ > kMaxStatementDepth) { + AddError(ast->source) << "statement nesting depth / chaining length exceeds limit of " + << kMaxStatementDepth; + return nullptr; + } + + if (!callback()) { + return nullptr; + } + + return sem; +} + +bool Resolver::Mark(const ast::Node* node) { + TINT_ASSERT(node != nullptr) << "Resolver::Mark() called with nullptr"; + + auto marked_bit_ref = marked_[node->node_id.value]; + if (DAWN_LIKELY(!marked_bit_ref)) { + marked_bit_ref = true; + return true; + } + ICE(node->source) << "AST node '" << node->TypeInfo().name + << "' was encountered twice in the same AST of a Program\n" + << "Pointer: " << node; +} + +template +void Resolver::ApplyDiagnosticSeverities(NODE* node) { + for (auto itr : validator_.DiagnosticFilters().Top()) { + node->SetDiagnosticSeverity(itr.key, itr.value); + } +} + +bool Resolver::CheckNotTemplated(const char* use, const ast::Identifier* ident) { + if (DAWN_UNLIKELY(ident->Is())) { + AddError(ident->source) << use << " " << style::Code(ident->symbol.NameView()) + << " does not take template arguments"; + if (auto resolved = dependencies_.resolved_identifiers.Get(ident)) { + if (auto* ast_node = resolved->Node()) { + sem_.NoteDeclarationSource(ast_node); + } + } + return false; + } + return true; +} + +void Resolver::ErrorInvalidAttribute(const ast::Attribute* attr, StyledText use) { + AddError(attr->source) << style::Attribute("@", attr->Name()) << " is not valid for " << use; +} + +diag::Diagnostic& Resolver::AddError(const Source& source) const { + return diagnostics_.AddError(source); +} + +diag::Diagnostic& Resolver::AddWarning(const Source& source) const { + return diagnostics_.AddWarning(source); +} + +diag::Diagnostic& Resolver::AddNote(const Source& source) const { + return diagnostics_.AddNote(source); +} + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.h new file mode 100644 index 000000000..aa4e74f38 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/resolver.h @@ -0,0 +1,710 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_RESOLVER_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_RESOLVER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/constant/eval.h" +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/intrinsic/table.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/wgsl/allowed_features.h" +#include "src/tint/lang/wgsl/intrinsic/dialect.h" +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/resolver/dependency_graph.h" +#include "src/tint/lang/wgsl/resolver/sem_helper.h" +#include "src/tint/lang/wgsl/resolver/validator.h" +#include "src/tint/lang/wgsl/sem/block_statement.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/struct.h" +#include "src/tint/utils/containers/bitset.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/text/styled_text.h" + +// Forward declarations +namespace tint::ast { +class IndexAccessorExpression; +class BinaryExpression; +class BitcastExpression; +class CallExpression; +class CallStatement; +class CaseStatement; +class ForLoopStatement; +class Function; +class IdentifierExpression; +class LoopStatement; +class MemberAccessorExpression; +class ReturnStatement; +class SwitchStatement; +class UnaryOpExpression; +class Variable; +class WhileStatement; +} // namespace tint::ast +namespace tint::sem { +class Array; +class BlockStatement; +class BuiltinFn; +class CaseStatement; +class ForLoopStatement; +class IfStatement; +class LoopStatement; +class Statement; +class StructMember; +class SwitchStatement; +class ValueConstructor; +class ValueConversion; +class WhileStatement; +} // namespace tint::sem +namespace tint::core::type { +class Atomic; +} // namespace tint::core::type + +namespace tint::resolver { + +/// Resolves types for all items in the given tint program +class Resolver { + public: + /// Constructor + /// @param builder the program builder + /// @param allowed_features the extensions and features that are allowed to be used + Resolver(ProgramBuilder* builder, const wgsl::AllowedFeatures& allowed_features); + + /// Destructor + ~Resolver(); + + /// @returns error messages from the resolver + std::string error() const { return diagnostics_.Str(); } + + /// @returns the list of diagnostics raised by the generator. + const diag::List& Diagnostics() const { return diagnostics_; } + + /// @returns true if the resolver was successful + bool Resolve(); + + /// @param type the given type + /// @returns true if the given type is a plain type + bool IsPlain(const core::type::Type* type) const { return validator_.IsPlain(type); } + + /// @param type the given type + /// @returns true if the given type is storable + bool IsStorable(const core::type::Type* type) const { return validator_.IsStorable(type); } + + /// @returns the validator for testing + const Validator* GetValidatorForTesting() const { return &validator_; } + + private: + /// Resolves the program, without creating final the semantic nodes. + /// @returns true on success, false on error + bool ResolveInternal(); + + /// Creates the nodes and adds them to the sem::Info mappings of the + /// ProgramBuilder. + void CreateSemanticNodes() const; + + /// @returns the call of Expression() cast to a sem::ValueExpression. If the sem::Expression is + /// not a sem::ValueExpression, then an error diagnostic is raised and nullptr is returned. + sem::ValueExpression* ValueExpression(const ast::Expression* expr); + + /// @returns the call of Expression() cast to a sem::TypeExpression. If the sem::Expression is + /// not a sem::TypeExpression, then an error diagnostic is raised and nullptr is returned. + sem::TypeExpression* TypeExpression(const ast::Expression* expr); + + /// @returns the call of Expression() cast to a sem::FunctionExpression. If the sem::Expression + /// is not a sem::FunctionExpression, then an error diagnostic is raised and nullptr is + /// returned. + sem::FunctionExpression* FunctionExpression(const ast::Expression* expr); + + /// @returns the resolved type from an expression, or nullptr on error + const core::type::Type* Type(const ast::Expression* ast); + + /// @returns a new abstract-float + const core::type::AbstractFloat* AF(); + + /// @returns a new f32 + const core::type::F32* F32(); + + /// @returns a new i32 + const core::type::I32* I32(); + + /// @returns a new u32 + const core::type::U32* U32(); + + /// @returns a new f16, if the f16 extension is enabled, otherwise nullptr + const core::type::F16* F16(const ast::Identifier* ident); + + /// @returns a new i8, if the subgroup matrix extension is enabled, otherwise nullptr + const core::type::I8* I8(const ast::Identifier* ident); + + /// @returns a new u8, if the subgroup matrix extension is enabled, otherwise nullptr + const core::type::U8* U8(const ast::Identifier* ident); + + /// @returns a vector with the element type @p el of width @p n resolved from the identifier @p + /// ident. + const core::type::Vector* Vec(const ast::Identifier* ident, + const core::type::Type* el, + uint32_t n); + + /// @returns a vector of width @p n resolved from the templated identifier @p ident, or an + /// IncompleteType if the identifier is not templated. + const core::type::Type* VecT(const ast::Identifier* ident, + core::BuiltinType builtin, + uint32_t n); + + /// @returns a matrix with the element type @p el of dimensions @p num_columns x @p num_rows + /// resolved from the identifier @p ident. + const core::type::Matrix* Mat(const ast::Identifier* ident, + const core::type::Type* el, + uint32_t num_columns, + uint32_t num_rows); + + /// @returns a matrix of dimensions @p num_columns x @p num_rows resolved from the templated + /// identifier @p ident, or an IncompleteType if the identifier is not templated. + const core::type::Type* MatT(const ast::Identifier* ident, + core::BuiltinType builtin, + uint32_t num_columns, + uint32_t num_rows); + + /// @returns an array resolved from the templated identifier @p ident, or an IncompleteType if + /// the identifier is not templated. + const core::type::Type* Array(const ast::Identifier* ident); + + /// @returns a binding_array resolved from the templated identifier @p ident. + const core::type::BindingArray* BindingArray(const ast::Identifier* ident); + + /// @returns an atomic resolved from the templated identifier @p ident. + const core::type::Atomic* Atomic(const ast::Identifier* ident); + + /// @returns a pointer resolved from the templated identifier @p ident. + const core::type::Pointer* Ptr(const ast::Identifier* ident); + + /// @returns a sampled texture resolved from the templated identifier @p ident with the + /// dimensions @p dim. + const core::type::SampledTexture* SampledTexture(const ast::Identifier* ident, + core::type::TextureDimension dim); + + /// @returns a multisampled texture resolved from the templated identifier @p ident with the + /// dimensions @p dim. + const core::type::MultisampledTexture* MultisampledTexture(const ast::Identifier* ident, + core::type::TextureDimension dim); + + /// @returns a storage texture resolved from the templated identifier @p ident with the + /// dimensions @p dim. + const core::type::StorageTexture* StorageTexture(const ast::Identifier* ident, + core::type::TextureDimension dim); + + /// @returns a texel buffer resolved from the templated identifier @p ident. + /// @param ident the identifier to resolve + const core::type::TexelBuffer* TexelBuffer(const ast::Identifier* ident); + + /// @returns an input attachment resolved from the templated identifier @p ident + const core::type::InputAttachment* InputAttachment(const ast::Identifier* ident); + + /// @returns a subgroup matrix resolved from the templated identifier @p ident + const core::type::SubgroupMatrix* SubgroupMatrix(const ast::Identifier* ident, + core::SubgroupMatrixKind kind); + + /// @returns a buffer resolved from the templated identifier @p ident + const core::type::Buffer* Buffer(const ast::Identifier* ident); + + /// @returns @p ident cast to an ast::TemplatedIdentifier, if the identifier is templated and + /// the number of templated arguments are between @p min_args and @p max_args. + const ast::TemplatedIdentifier* TemplatedIdentifier(const ast::Identifier* ident, + size_t min_args, + size_t max_args = /* use min */ 0); + + /// @returns true if the number of templated arguments are between @p min_args and @p max_args + /// otherwise raises an error and returns false. + bool CheckTemplatedIdentifierArgs(const ast::TemplatedIdentifier* ident, + size_t min_args, + size_t max_args = /* use min */ 0); + + /// @returns the call of Expression() cast to a + /// sem::BuiltinEnumExpression. If the sem::Expression is not a + /// sem::BuiltinEnumExpression, then an error diagnostic is raised and + /// nullptr is returned. + sem::BuiltinEnumExpression* AddressSpaceExpression( + const ast::Expression* expr); + + /// @returns the call of Expression() cast to a + /// sem::BuiltinEnumExpression. If the sem::Expression is not a + /// sem::BuiltinEnumExpression, then an error diagnostic is raised and + /// nullptr is returned. + sem::BuiltinEnumExpression* TexelFormatExpression( + const ast::Expression* expr); + + /// @returns the call of Expression() cast to a sem::BuiltinEnumExpression*. + /// If the sem::Expression is not a sem::BuiltinEnumExpression*, then an error + /// diagnostic is raised and nullptr is returned. + sem::BuiltinEnumExpression* AccessExpression(const ast::Expression* expr); + + /// Expression traverses the graph of expressions starting at `expr`, building a post-ordered + /// list (leaf-first) of all the expression nodes. Each of the expressions are then resolved by + /// dispatching to the appropriate expression handlers below. + /// @returns the resolved semantic node for the expression `expr`, or nullptr on failure. + sem::Expression* Expression(const ast::Expression* expr); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Expression resolving methods + // + // Returns the semantic node pointer on success, nullptr on failure. + // + // These methods are invoked by Expression(), in postorder (child-first). These methods should + // not attempt to resolve their children. This design avoids recursion, which is a common cause + // of stack-overflows. + //////////////////////////////////////////////////////////////////////////////////////////////// + sem::ValueExpression* IndexAccessor(const ast::IndexAccessorExpression*); + sem::ValueExpression* Binary(const ast::BinaryExpression*); + sem::Call* Call(const ast::CallExpression*); + sem::Function* Function(const ast::Function*); + sem::Call* FunctionCall(const ast::CallExpression*, + sem::Function* target, + VectorRef args); + sem::Expression* Identifier(const ast::IdentifierExpression*); + template + sem::Call* BuiltinCall(const ast::CallExpression*, + wgsl::BuiltinFn, + Vector& args); + sem::ValueExpression* Literal(const ast::LiteralExpression*); + sem::ValueExpression* MemberAccessor(const ast::MemberAccessorExpression*); + sem::ValueExpression* UnaryOp(const ast::UnaryOpExpression*); + + /// Register a memory store to an expression, to track accesses to root identifiers in order to + /// perform alias analysis. + void RegisterStore(const sem::ValueExpression* expr); + + /// Register a memory load of an expression, to track accesses to root identifiers in order to + /// perform alias analysis. + void RegisterLoad(const sem::ValueExpression* expr); + + /// Perform pointer alias analysis for `call`. + /// @returns true is the call arguments are free from aliasing issues, false otherwise. + bool AliasAnalysis(const sem::Call* call); + + /// If `expr` is of a reference type, then Load will create and return a sem::Load node wrapping + /// `expr`. If `expr` is not of a reference type, then Load will just return `expr`. + const sem::ValueExpression* Load(const sem::ValueExpression* expr); + + /// If `expr` is not of an abstract-numeric type, then Materialize() will just return `expr`. + /// * Materialize will create and return a sem::Materialize node wrapping `expr`. + /// * The AST -> Sem binding will be updated to point to the new sem::Materialize node. + /// * The sem::Materialize node will have a new concrete type, which will be `target_type` if + /// not nullptr, otherwise: + /// * a type with the element type of `i32` (e.g. `i32`, `vec2`) if `expr` has a + /// element type of abstract-integer... + /// * ... or a type with the element type of `f32` (e.g. `f32`, vec3`, `mat2x3`) + /// if `expr` has a element type of abstract-float. + /// * The sem::Materialize constant value will be the value of `expr` value-converted to the + /// materialized type. + /// If `expr` is not of an abstract-numeric type, then Materialize() will just return `expr`. + /// If `expr` is nullptr, then Materialize() will also return nullptr. + const sem::ValueExpression* Materialize(const sem::ValueExpression* expr, + const core::type::Type* target_type = nullptr); + + /// For each argument in `args`: + /// * Calls Materialize() passing the argument and the corresponding parameter type. + /// * Calls Load() passing the argument, iff the corresponding parameter type is not a + /// reference type. + /// @returns true on success, false on failure. + template + bool MaybeMaterializeAndLoadArguments(Vector& args, + const sem::CallTarget* target); + + /// @returns true if an argument of an abstract numeric type, passed to a parameter of type + /// `parameter_ty` should be materialized. + bool ShouldMaterializeArgument(const core::type::Type* parameter_ty) const; + + /// Converts `c` to `target_ty` + /// @returns true on success, false on failure. + bool Convert(const core::constant::Value*& c, + const core::type::Type* target_ty, + const Source& source); + + /// Transforms `args` to a vector of constants, and converts each constant to the call target's + /// parameter type. + /// @returns the vector of constants, `tint::Failure` on failure. + template + tint::Result> ConvertArguments( + const Vector& args, + const sem::CallTarget* target); + + /// Converts the value of `args`[`i`] to the type of the `i`th of the `target`. + /// Assumes `i` is a valid argument index. Returns nullptr if the value is not + /// a constant, or can't be converted. + /// @returns the possibly converted argument + template + const core::constant::Value* ConvertConstArgument( + const Vector& args, + const sem::CallTarget* target, + unsigned i); + + /// @param ty the type that may hold abstract numeric types + /// @param target_ty the target type for the expression (variable type, parameter type, etc). + /// May be nullptr. + /// @param source the source of the expression requiring materialization + /// @returns the concrete (materialized) type for the given type, or nullptr if the type is + /// already concrete. + const core::type::Type* ConcreteType(const core::type::Type* ty, + const core::type::Type* target_ty, + const Source& source); + + // Statement resolving methods + // Each return true on success, false on failure. + sem::Statement* AssignmentStatement(const ast::AssignmentStatement*); + sem::BlockStatement* BlockStatement(const ast::BlockStatement*); + sem::Statement* BreakStatement(const ast::BreakStatement*); + sem::Statement* BreakIfStatement(const ast::BreakIfStatement*); + sem::Statement* CallStatement(const ast::CallStatement*); + sem::CaseStatement* CaseStatement(const ast::CaseStatement*, const core::type::Type*); + sem::Statement* CompoundAssignmentStatement(const ast::CompoundAssignmentStatement*); + sem::Statement* ContinueStatement(const ast::ContinueStatement*); + sem::Statement* ConstAssert(const ast::ConstAssert*); + sem::Statement* DiscardStatement(const ast::DiscardStatement*); + sem::ForLoopStatement* ForLoopStatement(const ast::ForLoopStatement*); + sem::WhileStatement* WhileStatement(const ast::WhileStatement*); + sem::GlobalVariable* GlobalVariable(const ast::Variable*); + sem::Statement* Parameter(const ast::Variable*); + sem::IfStatement* IfStatement(const ast::IfStatement*); + sem::Statement* IncrementDecrementStatement(const ast::IncrementDecrementStatement*); + sem::LoopStatement* LoopStatement(const ast::LoopStatement*); + sem::Statement* ReturnStatement(const ast::ReturnStatement*); + sem::Statement* Statement(const ast::Statement*); + sem::SwitchStatement* SwitchStatement(const ast::SwitchStatement* s); + sem::Statement* VariableDeclStatement(const ast::VariableDeclStatement*); + bool Statements(VectorRef); + + /// Resolves the WorkgroupSize for the given function, assigning it to + /// current_function_ + bool WorkgroupSize(const ast::Function*); + + /// Resolves the `@location` attribute @p attr + /// @returns the location value on success. + tint::Result LocationAttribute(const ast::LocationAttribute* attr); + + /// Resolves the `@color` attribute @p attr + /// @returns the color value on success. + tint::Result ColorAttribute(const ast::ColorAttribute* attr); + + /// Resolves the `@blend_src` attribute @p attr + /// @returns the blend_src value on success. + tint::Result BlendSrcAttribute(const ast::BlendSrcAttribute* attr); + + /// Resolves the `@binding` attribute @p attr + /// @returns the binding value on success. + tint::Result BindingAttribute(const ast::BindingAttribute* attr); + + /// Resolves the `@group` attribute @p attr + /// @returns the group value on success. + tint::Result GroupAttribute(const ast::GroupAttribute* attr); + + /// Resolves the `@input_attachment_index` attribute @p attr + /// @returns the index value on success. + tint::Result InputAttachmentIndexAttribute( + const ast::InputAttachmentIndexAttribute* attr); + + /// Resolves the `@workgroup_size` attribute @p attr + /// @returns the workgroup size on success. + tint::Result WorkgroupAttribute(const ast::WorkgroupAttribute* attr); + + /// Resolves the `@sugbroup_size` attribute @p attr + /// @returns the subgroup size on success. + tint::Result SubgroupSizeAttribute(const ast::SubgroupSizeAttribute* attr); + + /// Resolves the `@diagnostic` attribute @p attr + /// @returns true on success, false on failure + bool DiagnosticAttribute(const ast::DiagnosticAttribute* attr); + + /// Resolves the stage attribute @p attr + /// @returns true on success, false on failure + bool StageAttribute(const ast::StageAttribute* attr); + + /// Resolves the `@must_use` attribute @p attr + /// @returns true on success, false on failure + bool MustUseAttribute(const ast::MustUseAttribute* attr); + + /// Resolves the `@invariant` attribute @p attr + /// @returns true on success, false on failure + bool InvariantAttribute(const ast::InvariantAttribute*); + + /// @param control the diagnostic control + /// @returns true on success, false on failure + bool DiagnosticControl(const ast::DiagnosticControl& control); + + /// @param enable the enable declaration + /// @returns true on success, false on failure + bool Enable(const ast::Enable* enable); + + /// @param req the requires declaration + /// @returns true on success, false on failure + bool Requires(const ast::Requires* req); + + /// @param named_type the named type to resolve + /// @returns the resolved semantic type + const core::type::Type* TypeDecl(const ast::TypeDecl* named_type); + + /// Resolves and validates the expression used as the count parameter of an array. + /// @param count_expr the expression used as the second template parameter to an array<>. + /// @param array indicates whether the count is for an array or buffer + /// @returns the number of elements in the array. + const core::type::ArrayCount* ArrayCount(const ast::Expression* count_expr, bool array = true); + + /// Builds and returns the semantic information for an array. + /// @returns the semantic Array information, or nullptr if an error is raised. + /// @param array_source the source of the array + /// @param el_source the source of the array element, or the array if the array does not have a + /// locally-declared element AST node. + /// @param count_source the source of the array count, or the array if the array does not have a + /// locally-declared element AST node. + /// @param el_ty the Array element type + /// @param el_count the number of elements in the array. + sem::Array* Array(const Source& array_source, + const Source& el_source, + const Source& count_source, + const core::type::Type* el_ty, + const core::type::ArrayCount* el_count); + + /// Builds and returns the semantic information for the alias `alias`. + /// This method does not mark the ast::Alias node, nor attach the generated + /// semantic information to the AST node. + /// @returns the aliased type, or nullptr if an error is raised. + const core::type::Type* Alias(const ast::Alias* alias); + + /// Builds and returns the semantic information for the structure `str`. + /// This method does not mark the ast::Struct node, nor attach the generated + /// semantic information to the AST node. + /// @returns the semantic Struct information, or nullptr if an error is + /// raised. + sem::Struct* Structure(const ast::Struct* str); + + /// @returns the semantic info for the variable `v`. If an error is raised, nullptr is + /// returned. + /// @note this method does not resolve the attributes as these are context-dependent (global, + /// local) + /// @param var the variable + /// @param is_global true if this is module scope, otherwise function scope + sem::Variable* Variable(const ast::Variable* var, bool is_global); + + /// @returns the semantic info for the `ast::Let` `v`. If an error is raised, nullptr is + /// returned. + /// @note this method does not resolve the attributes as these are context-dependent (global, + /// local) + /// @param var the variable + sem::Variable* Let(const ast::Let* var); + + /// @returns the semantic info for the module-scope `ast::Override` `v`. If an error is raised, + /// nullptr is returned. + /// @note this method does not resolve the attributes as these are context-dependent (global, + /// local) + /// @param override the variable + sem::Variable* Override(const ast::Override* override); + + /// @returns the semantic info for an `ast::Const` `v`. If an error is raised, nullptr is + /// returned. + /// @note this method does not resolve the attributes as these are context-dependent (global, + /// local) + /// @param const_ the variable + /// @param is_global true if this is module scope, otherwise function scope + sem::Variable* Const(const ast::Const* const_, bool is_global); + + /// @returns the semantic info for the `ast::Var` `var`. If an error is raised, nullptr is + /// returned. + /// @note this method does not resolve the attributes as these are context-dependent (global, + /// local) + /// @param var the variable + /// @param is_global true if this is module scope, otherwise function scope + sem::Variable* Var(const ast::Var* var, bool is_global); + + /// @returns the semantic info for the function parameter `param`. If an error is raised, + /// nullptr is returned. + /// @note the caller is expected to validate the parameter + /// @param param the AST parameter + /// @param func the AST function that owns the parameter + /// @param index the index of the parameter + sem::Parameter* Parameter(const ast::Parameter* param, + const ast::Function* func, + uint32_t index); + + /// Records the address space usage for the given type, and any transient + /// dependencies of the type. Validates that the type can be used for the + /// given address space, erroring if it cannot. + /// @param sc the address space to apply to the type and transitent types + /// @param ty the type to apply the address space on + /// @param usage the Source of the root variable declaration that uses the + /// given type and address space. Used for generating sensible error + /// messages. + /// @returns true on success, false on error + bool ApplyAddressSpaceUsageToType(core::AddressSpace sc, + const core::type::Type* ty, + const Source& usage); + + /// @param address_space the address space + /// @returns the default access control for the given address space + core::Access DefaultAccessForAddressSpace(core::AddressSpace address_space); + + /// Allocate constant IDs for pipeline-overridable constants. + /// @returns true on success, false on error + bool AllocateOverridableConstantIds(); + + /// Set the shadowing information on variable declarations. + /// @note this method must only be called after all semantic nodes are built. + void SetShadows(); + + /// StatementScope() does the following: + /// * Creates the AST -> SEM mapping. + /// * Assigns `sem` to #current_statement_ + /// * Assigns `sem` to #current_compound_statement_ if `sem` derives from + /// sem::CompoundStatement. + /// * Then calls `callback`. + /// * Before returning #current_statement_ and #current_compound_statement_ are restored to + /// their original values. + /// @returns `sem` if `callback` returns true, otherwise `nullptr`. + template + SEM* StatementScope(const ast::Statement* ast, SEM* sem, F&& callback); + + /// Mark records that the given AST node has been visited, and asserts that + /// the given node has not already been seen. Diamonds in the AST are + /// illegal. + /// @param node the AST node. + /// @returns true on success, false on error + bool Mark(const ast::Node* node); + + /// Applies the diagnostic severities from the current scope to a semantic node. + /// @param node the semantic node to apply the diagnostic severities to + template + void ApplyDiagnosticSeverities(NODE* node); + + /// Checks @p ident is not an ast::TemplatedIdentifier. + /// If @p ident is a ast::TemplatedIdentifier, then an error diagnostic is raised. + /// @returns true if @p ident is not a ast::TemplatedIdentifier. + bool CheckNotTemplated(const char* use, const ast::Identifier* ident); + + /// Raises an error that the attribute is not valid for the given use. + /// @param attr the invalue attribute + /// @param use the thing that the attribute was applied to + void ErrorInvalidAttribute(const ast::Attribute* attr, StyledText use); + + /// @returns a new error message added to the program's diagnostics + diag::Diagnostic& AddError(const Source& source) const; + + /// @returns a new warning message added to the program's diagnostics + diag::Diagnostic& AddWarning(const Source& source) const; + + /// @returns a new note message added to the program's diagnostics + diag::Diagnostic& AddNote(const Source& source) const; + + /// @returns the core::type::Type for the builtin type @p builtin_ty with the identifier @p + /// ident + /// @note: Will raise an ICE if @p symbol is not a builtin type. + const core::type::Type* BuiltinType(core::BuiltinType builtin_ty, const ast::Identifier* ident); + + /// @returns the nesting depth of @ty as defined in + /// https://gpuweb.github.io/gpuweb/wgsl/#composite-types + size_t NestDepth(const core::type::Type* ty) const; + + // ArrayConstructorSig represents a unique array constructor signature. + // It is a tuple of the array type, number of arguments provided and earliest evaluation stage. + using ArrayConstructorSig = + tint::UnorderedKeyWrapper>; + + // StructConstructorSig represents a unique structure constructor signature. + // It is a tuple of the structure type, number of arguments provided and earliest evaluation + // stage. + using StructConstructorSig = tint::UnorderedKeyWrapper< + std::tuple>; + + // SubgroupMatrixConstructorSig represents a unique subgroup matrix constructor signature. + // It is a tuple of the subgroup matrix type and the number of arguments provided. + using SubgroupMatrixConstructorSig = + tint::UnorderedKeyWrapper>; + + /// ExprEvalStageConstraint describes a constraint on when expressions can be evaluated. + struct ExprEvalStageConstraint { + /// The latest stage that the expression can be evaluated + core::EvaluationStage stage = core::EvaluationStage::kRuntime; + /// The 'thing' that is imposing the contraint. e.g. "var declaration" + /// If nullptr, then there is no constraint + const char* constraint = nullptr; + }; + + /// AliasAnalysisInfo captures the memory accesses performed by a given function for the purpose + /// of determining if any two arguments alias at any callsite. + struct AliasAnalysisInfo { + /// The set of module-scope variables that are written to, and where that write occurs. + Hashmap module_scope_writes; + /// The set of module-scope variables that are read from, and where that read occurs. + Hashmap module_scope_reads; + /// The set of function parameters that are written to. + Hashset parameter_writes; + /// The set of function parameters that are read from. + Hashset parameter_reads; + }; + + ProgramBuilder& b; + diag::List& diagnostics_; + core::constant::Eval const_eval_; + core::intrinsic::Table intrinsic_table_; + DependencyGraph dependencies_; + SemHelper sem_; + Validator validator_; + wgsl::AllowedFeatures allowed_features_; + wgsl::Extensions enabled_extensions_; + Vector entry_points_; + Hashmap atomic_composite_info_; + Hashset subgroup_matrix_uses_; + tint::Bitset<0> marked_; + ExprEvalStageConstraint expr_eval_stage_constraint_; + std::unordered_map alias_analysis_infos_; + Hashmap override_ids_; + Hashmap array_ctors_; + Hashmap struct_ctors_; + Hashmap subgroup_matrix_ctors_; + sem::Function* current_function_ = nullptr; + sem::Statement* current_statement_ = nullptr; + sem::CompoundStatement* current_compound_statement_ = nullptr; + Vector, 4> on_transitively_reference_global_; + uint32_t current_scoping_depth_ = 0; + Hashset valid_type_storage_layouts_; + Hashmap logical_binary_lhs_to_parent_; + Hashset not_evaluated_; + Hashmap nest_depth_; + Hashmap, sem::BuiltinFn*, 64> builtins_; + Hashmap constructors_; + Hashmap converters_; +}; + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_RESOLVER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.cc new file mode 100644 index 000000000..3c62c6f1c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.cc @@ -0,0 +1,237 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/sem_helper.h" + +#include "src/tint/lang/wgsl/resolver/incomplete_type.h" +#include "src/tint/lang/wgsl/resolver/unresolved_identifier.h" +#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/function_expression.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +namespace tint::resolver { + +SemHelper::SemHelper(ProgramBuilder* builder) : builder_(builder) {} + +SemHelper::~SemHelper() = default; + +std::string SemHelper::TypeNameOf(const core::type::Type* ty) const { + return RawTypeNameOf(ty->UnwrapRef()); +} + +std::string SemHelper::RawTypeNameOf(const core::type::Type* ty) const { + return ty->FriendlyName(); +} + +core::type::Type* SemHelper::TypeOf(const ast::Expression* expr) const { + auto* sem = GetVal(expr); + return sem ? const_cast(sem->Type()) : nullptr; +} + +sem::TypeExpression* SemHelper::AsTypeExpression(sem::Expression* expr) const { + if (DAWN_UNLIKELY(!expr)) { + return nullptr; + } + + auto* ty_expr = expr->As(); + if (DAWN_UNLIKELY(!ty_expr)) { + ErrorUnexpectedExprKind(expr, "type"); + return nullptr; + } + + auto* type = ty_expr->Type(); + if (auto* incomplete = type->As(); DAWN_UNLIKELY(incomplete)) { + AddError(expr->Declaration()->source.End()) + << "expected " << style::Code("<") << " for " << style::Type(incomplete->builtin); + return nullptr; + } + + return ty_expr; +} + +StyledText SemHelper::Describe(const sem::Expression* expr) const { + StyledText text; + + Switch( + expr, // + [&](const sem::VariableUser* var_expr) { + auto* variable = var_expr->Variable()->Declaration(); + auto name = variable->name->symbol.NameView(); + Switch( + variable, // + [&](const ast::Var*) { text << style::Keyword("var") << style::Code(" "); }, // + [&](const ast::Let*) { text << style::Keyword("let") << style::Code(" "); }, // + [&](const ast::Const*) { text << style::Keyword("const") << style::Code(" "); }, // + [&](const ast::Parameter*) { text << "parameter "; }, // + [&](const ast::Override*) { + text << style::Keyword("override") << style::Code(" "); + }, // + [&](Default) { text << "variable "; }); + text << style::Variable(name); + }, + [&](const sem::ValueExpression* val_expr) { + text << "value of type " << style::Type(val_expr->Type()->FriendlyName()); + }, + [&](const sem::TypeExpression* ty_expr) { + text << "type " << style::Type(ty_expr->Type()->FriendlyName()); + }, + [&](const sem::FunctionExpression* fn_expr) { + auto* fn = fn_expr->Function()->Declaration(); + text << "function " << style::Function(fn->name->symbol.NameView()); + }, + [&](const sem::BuiltinEnumExpression* fn) { + text << "builtin function " << style::Function(fn->Value()); + }, + [&](const sem::BuiltinEnumExpression* access) { + text << "access enumerant " << style::Enum(access->Value()); + }, + [&](const sem::BuiltinEnumExpression* addr) { + text << "address space " << style::Enum(addr->Value()); + }, + [&](const sem::BuiltinEnumExpression* fmt) { + text << "texel format " << style::Enum(fmt->Value()); + }, + [&](const UnresolvedIdentifier* ui) { + auto name = ui->Identifier()->identifier->symbol.NameView(); + text << "unresolved identifier " << style::Code(name); + }, // + TINT_ICE_ON_NO_MATCH); + + return text; +} + +void SemHelper::ErrorUnexpectedIdent( + const ast::Identifier* ident, + std::string_view wanted, + tint::Slice suggestions /* = Empty */) const { + auto name = ident->symbol.NameView(); + AddError(ident->source) << "unresolved " << wanted << " " << style::Code(name); + if (!suggestions.IsEmpty()) { + // Filter out suggestions that have a leading underscore. + Vector filtered; + for (auto str : suggestions) { + if (str[0] != '_') { + filtered.Push(str); + } + } + auto& note = AddNote(ident->source); + SuggestAlternativeOptions opts; + opts.alternatives_style = style::Enum; + SuggestAlternatives(name, filtered.Slice(), note.message, opts); + } +} + +void SemHelper::ErrorUnexpectedExprKind( + const sem::Expression* expr, + std::string_view wanted, + tint::Slice suggestions /* = Empty */) const { + if (auto* ui = expr->As()) { + return ErrorUnexpectedIdent(ui->Identifier()->identifier, wanted, suggestions); + } + + AddError(expr->Declaration()->source) << "cannot use " << Describe(expr) << " as " << wanted; + NoteDeclarationSource(expr->Declaration()); +} + +void SemHelper::ErrorExpectedValueExpr(const sem::Expression* expr) const { + ErrorUnexpectedExprKind(expr, "value"); + if (auto* ident = expr->Declaration()->As()) { + if (expr->IsAnyOf>()) { + AddNote(ident->source.End()) + << "are you missing " << style::Code("()") << style::Plain("?"); + } + } +} + +void SemHelper::NoteDeclarationSource(const ast::Node* node) const { + if (!node) { + return; + } + + Switch( + Get(node), // + [&](const sem::VariableUser* var_expr) { node = var_expr->Variable()->Declaration(); }, + [&](const sem::TypeExpression* ty_expr) { + Switch(ty_expr->Type(), // + [&](const sem::Struct* s) { node = s->Declaration(); }); + }, + [&](const sem::FunctionExpression* fn_expr) { node = fn_expr->Function()->Declaration(); }); + + Switch( + node, + [&](const ast::Struct* n) { + AddNote(n->source) << style::Keyword("struct ") + << style::Type(n->name->symbol.NameView()) << " declared here"; + }, + [&](const ast::Alias* n) { + AddNote(n->source) << style::Keyword("alias ") + << style::Type(n->name->symbol.NameView()) << " declared here"; + }, + [&](const ast::Var* n) { + AddNote(n->source) << style::Keyword("var ") + << style::Variable(n->name->symbol.NameView()) << " declared here"; + }, + [&](const ast::Let* n) { + AddNote(n->source) << style::Keyword("let ") + << style::Variable(n->name->symbol.NameView()) << " declared here"; + }, + [&](const ast::Override* n) { + AddNote(n->source) << style::Keyword("override ") + << style::Variable(n->name->symbol.NameView()) << " declared here"; + }, + [&](const ast::Const* n) { + AddNote(n->source) << style::Keyword("const ") + << style::Variable(n->name->symbol.NameView()) << " declared here"; + }, + [&](const ast::Parameter* n) { + AddNote(n->source) << "parameter " << style::Variable(n->name->symbol.NameView()) + << " declared here"; + }, + [&](const ast::Function* n) { + AddNote(n->source) << "function " << style::Function(n->name->symbol.NameView()) + << " declared here"; + }); +} + +diag::Diagnostic& SemHelper::AddError(const Source& source) const { + return builder_->Diagnostics().AddError(source); +} + +diag::Diagnostic& SemHelper::AddWarning(const Source& source) const { + return builder_->Diagnostics().AddWarning(source); +} + +diag::Diagnostic& SemHelper::AddNote(const Source& source) const { + return builder_->Diagnostics().AddNote(source); +} +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.h new file mode 100644 index 000000000..bbe186a32 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/sem_helper.h @@ -0,0 +1,265 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_SEM_HELPER_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_SEM_HELPER_H_ + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/resolver/dependency_graph.h" +#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h" +#include "src/tint/lang/wgsl/sem/function_expression.h" +#include "src/tint/lang/wgsl/sem/type_expression.h" +#include "src/tint/utils/containers/map.h" +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/text/styled_text.h" + +namespace tint::resolver { + +/// Helper class to retrieve sem information. +class SemHelper { + public: + /// Constructor + /// @param builder the program builder + explicit SemHelper(ProgramBuilder* builder); + ~SemHelper(); + + /// Get is a helper for obtaining the semantic node for the given AST node. + /// Raises an ICE and returns `nullptr` if there is no semantic node associated with the AST + /// node. + /// @param ast the ast node to get the sem for + /// @returns the sem node for @p ast + template + auto* Get(const AST* ast) const { + using T = sem::Info::GetResultType; + auto* sem = builder_->Sem().Get(ast); + TINT_ASSERT(sem) << "AST node '" << ast->TypeInfo().name << "' had no semantic info\n" + << "At: " << ast->source << "\n" + << "Pointer: " << ast; + + return const_cast(As(sem)); + } + + /// GetVal is a helper for obtaining the semantic sem::ValueExpression for the given AST + /// expression. Raises an error diagnostic and returns `nullptr` if the semantic node is not a + /// sem::ValueExpression. + /// @param ast the ast node to get the sem for + /// @returns the sem node for @p ast + template + auto* GetVal(const AST* ast) const { + return AsValueExpression(Get(ast)); + } + + /// @param expr the semantic node + /// @returns nullptr if @p expr is nullptr, or @p expr cast to sem::ValueExpression if the cast + /// is successful, otherwise an error diagnostic is raised. + sem::ValueExpression* AsValueExpression(sem::Expression* expr) const { + if (DAWN_LIKELY(expr)) { + if (auto* val_expr = expr->As(); DAWN_LIKELY(val_expr)) { + return val_expr; + } + ErrorExpectedValueExpr(expr); + } + return nullptr; + } + + /// @param expr the semantic node + /// @returns nullptr if @p expr is nullptr, or @p expr cast to type::Type if the cast is + /// successful, otherwise an error diagnostic is raised. + sem::TypeExpression* AsTypeExpression(sem::Expression* expr) const; + + /// GetType is a helper for obtaining the semantic type for the given AST expression. + /// Raises an error diagnostic and returns `nullptr` if the semantic node is not a + /// sem::TypeExpression + /// @param ast the ast node to get the sem for + /// @returns the sem node for @p ast + const core::type::Type* GetType(const ast::Expression* ast) const { + auto* expr = AsTypeExpression(Get(ast)); + if (DAWN_LIKELY(expr)) { + return expr->Type(); + } + return nullptr; + } + + /// @param expr the semantic node + /// @returns nullptr if @p expr is nullptr, or @p expr cast to sem::Function if the cast is + /// successful, otherwise an error diagnostic is raised. + sem::FunctionExpression* AsFunctionExpression(sem::Expression* expr) const { + if (DAWN_LIKELY(expr)) { + auto* fn_expr = expr->As(); + if (DAWN_LIKELY(fn_expr)) { + return fn_expr; + } + ErrorUnexpectedExprKind(expr, "function"); + } + return nullptr; + } + + /// @param expr the semantic node + /// @returns nullptr if @p expr is nullptr, or @p expr cast to + /// sem::BuiltinEnumExpression if the cast is successful, otherwise an + /// error diagnostic is raised. + sem::BuiltinEnumExpression* AsAddressSpace(sem::Expression* expr) const { + if (DAWN_LIKELY(expr)) { + auto* enum_expr = expr->As>(); + if (DAWN_LIKELY(enum_expr)) { + return enum_expr; + } + ErrorUnexpectedExprKind(expr, "address space", core::kAddressSpaceStrings); + } + return nullptr; + } + + /// GetAddressSpace is a helper for obtaining the address space for the given AST expression. + /// Raises an error diagnostic and returns core::AddressSpace::kUndefined if the semantic node + /// is not a sem::BuiltinEnumExpression + /// @param ast the ast node to get the address space + /// @returns the sem node for @p ast + core::AddressSpace GetAddressSpace(const ast::Expression* ast) const { + auto* expr = AsAddressSpace(Get(ast)); + if (DAWN_LIKELY(expr)) { + return expr->Value(); + } + return core::AddressSpace::kUndefined; + } + + /// @param expr the semantic node + /// @returns nullptr if @p expr is nullptr, or @p expr cast to + /// sem::BuiltinEnumExpression if the cast is successful, otherwise an + /// error diagnostic is raised. + sem::BuiltinEnumExpression* AsTexelFormat(sem::Expression* expr) const { + if (DAWN_LIKELY(expr)) { + auto* enum_expr = expr->As>(); + if (DAWN_LIKELY(enum_expr)) { + return enum_expr; + } + ErrorUnexpectedExprKind(expr, "texel format", core::kTexelFormatStrings); + } + return nullptr; + } + + /// GetTexelFormat is a helper for obtaining the texel format for the given AST expression. + /// Raises an error diagnostic and returns core::TexelFormat::kUndefined if the semantic node + /// is not a sem::BuiltinEnumExpression + /// @param ast the ast node to get the texel format + /// @returns the sem node for @p ast + core::TexelFormat GetTexelFormat(const ast::Expression* ast) const { + auto* expr = AsTexelFormat(Get(ast)); + if (DAWN_LIKELY(expr)) { + return expr->Value(); + } + return core::TexelFormat::kUndefined; + } + + /// @param expr the semantic node + /// @returns nullptr if @p expr is nullptr, or @p expr cast to + /// sem::BuiltinEnumExpression if the cast is successful, otherwise an error + /// diagnostic is raised. + sem::BuiltinEnumExpression* AsAccess(sem::Expression* expr) const { + if (DAWN_LIKELY(expr)) { + auto* enum_expr = expr->As>(); + if (DAWN_LIKELY(enum_expr)) { + return enum_expr; + } + ErrorUnexpectedExprKind(expr, "access", core::kAccessStrings); + } + return nullptr; + } + + /// GetAccess is a helper for obtaining the access mode for the given AST expression. + /// Raises an error diagnostic and returns core::Access::kUndefined if the semantic node + /// is not a sem::BuiltinEnumExpression + /// @param ast the ast node to get the access mode + /// @returns the sem node for @p ast + core::Access GetAccess(const ast::Expression* ast) const { + auto* expr = AsAccess(Get(ast)); + if (DAWN_LIKELY(expr)) { + return expr->Value(); + } + return core::Access::kUndefined; + } + + /// @returns the resolved type of the ast::Expression @p expr + /// @param expr the expression + core::type::Type* TypeOf(const ast::Expression* expr) const; + + /// @returns the type name of the given semantic type, unwrapping references. + /// @param ty the type to look up + std::string TypeNameOf(const core::type::Type* ty) const; + + /// @returns the type name of the given semantic type, without unwrapping references. + /// @param ty the type to look up + std::string RawTypeNameOf(const core::type::Type* ty) const; + + /// Raises an error diagnostic that the expression @p got was expected to be a + /// sem::ValueExpression, but the expression evaluated to something different. + /// @param expr the expression + void ErrorExpectedValueExpr(const sem::Expression* expr) const; + + /// Raises an error diagnostic that the identifier @p got was not of the kind @p wanted. + /// @param ident the identifier + /// @param wanted the expected identifier kind + /// @param suggestions suggested valid identifiers + void ErrorUnexpectedIdent(const ast::Identifier* ident, + std::string_view wanted, + tint::Slice suggestions = Empty) const; + + /// Raises an error diagnostic that the expression @p got was not of the kind @p wanted. + /// @param expr the expression + /// @param wanted the expected expression kind + /// @param suggestions suggested valid identifiers + void ErrorUnexpectedExprKind(const sem::Expression* expr, + std::string_view wanted, + tint::Slice suggestions = Empty) const; + + /// If @p node is a module-scope type, variable or function declaration, then appends a note + /// diagnostic where this declaration was declared, otherwise the function does nothing. + /// @param node the AST node. + void NoteDeclarationSource(const ast::Node* node) const; + + /// @param expr the expression to describe + /// @return a string that describes @p expr. Useful for diagnostics. + StyledText Describe(const sem::Expression* expr) const; + + private: + /// @returns a new error diagnostics + diag::Diagnostic& AddError(const Source& source) const; + + /// @returns a new warning diagnostics + diag::Diagnostic& AddWarning(const Source& source) const; + + /// @returns a new note diagnostics + diag::Diagnostic& AddNote(const Source& source) const; + + ProgramBuilder* builder_; +}; + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_SEM_HELPER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.cc new file mode 100644 index 000000000..4702ba27e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.cc @@ -0,0 +1,2341 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/uniformity.h" + +#include +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/resolver/dependency_graph.h" +#include "src/tint/lang/wgsl/sem/block_statement.h" +#include "src/tint/lang/wgsl/sem/builtin_fn.h" +#include "src/tint/lang/wgsl/sem/for_loop_statement.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/if_statement.h" +#include "src/tint/lang/wgsl/sem/info.h" +#include "src/tint/lang/wgsl/sem/load.h" +#include "src/tint/lang/wgsl/sem/loop_statement.h" +#include "src/tint/lang/wgsl/sem/statement.h" +#include "src/tint/lang/wgsl/sem/switch_statement.h" +#include "src/tint/lang/wgsl/sem/value_constructor.h" +#include "src/tint/lang/wgsl/sem/value_conversion.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/lang/wgsl/sem/while_statement.h" +#include "src/tint/utils/containers/scope_stack.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/memory/block_allocator.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/text/string_stream.h" + +// Set to `1` to dump the uniformity graph for each function in graphviz format. +#define TINT_DUMP_UNIFORMITY_GRAPH 0 + +#if TINT_DUMP_UNIFORMITY_GRAPH +#include +#endif + +namespace tint::resolver { + +namespace { + +/// Unwraps `u->expr`'s chain of indirect (*) and address-of (&) expressions, returning the first +/// expression that is neither of these. +/// E.g. If `u` is `*(&(*(&p)))`, returns `p`. +const ast::Expression* UnwrapIndirectAndAddressOfChain(const ast::UnaryOpExpression* u) { + auto* e = u->expr; + while (true) { + auto* unary = e->As(); + if (unary && + (unary->op == core::UnaryOp::kIndirection || unary->op == core::UnaryOp::kAddressOf)) { + e = unary->expr; + } else { + break; + } + } + return e; +} + +/// Scope of uniformity analysis. +enum class UniformityScope : uint8_t { + kAll, // workgroup/draw/subgroup + kWorkgroup, // workgroup/draw + kSubgroup, // subgroup +}; + +/// CallSiteTag describes the uniformity requirements on the call sites of a function. +struct CallSiteTag { + enum { + CallSiteRequiredToBeUniform, + CallSiteNoRestriction, + } tag; + wgsl::DiagnosticSeverity severity = wgsl::DiagnosticSeverity::kUndefined; +}; + +/// FunctionTag describes a functions effects on uniformity. +enum FunctionTag { + ReturnValueMayBeNonUniform, + NoRestriction, +}; + +/// ParameterTag describes the uniformity requirements of values passed to a function parameter. +struct ParameterTag { + enum { + ParameterValueRequiredToBeUniform, + ParameterContentsRequiredToBeUniform, + ParameterNoRestriction, + } tag; + wgsl::DiagnosticSeverity severity = wgsl::DiagnosticSeverity::kUndefined; +}; + +/// Node represents a node in the graph of control flow and value nodes within the analysis of a +/// single function. +struct Node { + /// Constructor + /// @param a the corresponding AST node + explicit Node(const ast::Node* a) : ast(a) {} + +#if TINT_DUMP_UNIFORMITY_GRAPH + /// The node tag. + std::string tag; +#endif + + /// Type describes the type of the node, which is used to determine additional diagnostic + /// information. + enum Type { + kRegular, + kFunctionCallArgumentValue, + kFunctionCallArgumentContents, + kFunctionCallPointerArgumentResult, + kFunctionCallReturnValue, + kFunctionPointerParameterContents, + kSubgroupMatrixVariableDeclaration, + }; + + /// The type of the node. + Type type = kRegular; + + /// `true` if this node represents a potential control flow change. + bool affects_control_flow = false; + + /// The corresponding AST node, or nullptr. + const ast::Node* ast = nullptr; + + /// The function call argument index, if applicable. + uint32_t arg_index = 0xffffffffu; + + /// The set of edges from this node to other nodes in the graph. + UniqueVector edges; + + /// The node that this node was visited from, or nullptr if not visited. + Node* visited_from = nullptr; + + /// Add an edge to the `to` node. + /// @param to the destination node + void AddEdge(Node* to) { + TINT_ASSERT(to != nullptr); + edges.Add(to); + } +}; + +/// ParameterInfo holds information about the uniformity requirements and effects for a particular +/// function parameter. +struct ParameterInfo { + /// The semantic node in corresponds to this parameter. + const sem::Parameter* sem; + /// The parameter's direct uniformity requirements. + ParameterTag tag_direct = {ParameterTag::ParameterNoRestriction}; + /// The parameter's uniformity requirements that affect the function return value. + ParameterTag tag_retval = {ParameterTag::ParameterNoRestriction}; + /// Will be `true` if this function may cause the contents of this pointer parameter to become + /// non-uniform. + bool pointer_may_become_non_uniform = false; + /// The parameters that are required to be uniform for the contents of this pointer parameter to + /// be uniform at function exit. + Vector ptr_output_source_param_values; + /// The pointer parameters whose contents are required to be uniform for the contents of this + /// pointer parameter to be uniform at function exit. + Vector ptr_output_source_param_contents; + /// The node in the graph that corresponds to this parameter's (immutable) value. + Node* value; + /// The node in the graph that corresponds to this pointer parameter's initial contents. + Node* ptr_input_contents = nullptr; + /// The node in the graph that corresponds to this pointer parameter's contents on return. + Node* ptr_output_contents = nullptr; +}; + +/// FunctionInfo holds information about the uniformity requirements and effects for a particular +/// function, as well as the control flow graph. +struct FunctionInfo { + /// Constructor + /// @param func the AST function + /// @param b the program builder + FunctionInfo(const ast::Function* func, const ProgramBuilder& b) { + name = func->name->symbol.Name(); + callsite_tag = {CallSiteTag::CallSiteNoRestriction}; + function_tag = NoRestriction; + + // Create special nodes. + required_to_be_uniform_error = CreateNode({"RequiredToBeUniform_Error"}); + required_to_be_uniform_warning = CreateNode({"RequiredToBeUniform_Warning"}); + required_to_be_uniform_info = CreateNode({"RequiredToBeUniform_Info"}); + may_be_non_uniform = CreateNode({"MayBeNonUniform"}); + cf_start = CreateNode({"CF_start"}); + if (func->return_type) { + value_return = CreateNode({"Value_return"}); + } + + // Create nodes for parameters. + parameters.Resize(func->params.Length()); + for (size_t i = 0; i < func->params.Length(); i++) { + auto* param = func->params[i]; + auto param_name = param->name->symbol.Name(); + auto* sem = b.Sem().Get(param); + parameters[i].sem = sem; + + parameters[i].value = CreateNode({"param_", param_name}); + parameters[i].value->ast = param; + if (sem->Type()->Is()) { + // Create extra nodes for a pointer parameter's initial contents and its contents + // when the function returns. + parameters[i].ptr_input_contents = + CreateNode({"ptrparam_", param_name, "_input_contents"}, param); + parameters[i].ptr_output_contents = + CreateNode({"ptrparam_", param_name, "_output_contents"}); + parameters[i].ptr_input_contents->type = Node::kFunctionPointerParameterContents; + variables.Set(sem, parameters[i].ptr_input_contents); + local_var_decls.Add(sem); + } else { + variables.Set(sem, parameters[i].value); + } + } + } + + /// The name of the function. + std::string name; + + /// The call site uniformity requirements. + CallSiteTag callsite_tag; + /// The function's uniformity effects. + FunctionTag function_tag; + /// The uniformity requirements of the function's parameters. + Vector parameters; + + /// The control flow graph. + BlockAllocator nodes; + + /// Special `RequiredToBeUniform` nodes. + Node* required_to_be_uniform_error = nullptr; + Node* required_to_be_uniform_warning = nullptr; + Node* required_to_be_uniform_info = nullptr; + /// Special `MayBeNonUniform` node. + Node* may_be_non_uniform = nullptr; + /// Special `CF_start` node. + Node* cf_start = nullptr; + /// Special `Value_return` node. + Node* value_return = nullptr; + + /// Map from variables to their value nodes in the graph, scoped with respect to control flow. + ScopeStack variables; + + /// The set of mutable variables declared in the function that are in scope at any given point + /// in the analysis. This includes the contents of parameters to the function that are pointers. + /// This is used by the analysis for if statements and loops to know which variables need extra + /// nodes to capture their state when entering/exiting those constructs. + Hashset local_var_decls; + + /// The set of partial pointer variables - pointers that point to a subobject (into an array or + /// struct). + Hashset partial_ptrs; + + /// LoopSwitchInfo tracks information about the value of variables for a control flow construct. + struct LoopSwitchInfo { + /// The type of this control flow construct. + std::string type; + /// The input values for local variables at the start of this construct. + Hashmap var_in_nodes; + /// The values for local variables at the start of the continuing construct, if present. + Hashmap var_continuing_nodes; + /// The exit values for local variables at the end of this construct. + Hashmap var_exit_nodes; + }; + + /// @returns the RequiredToBeUniform node that corresponds to `severity` + Node* RequiredToBeUniform(wgsl::DiagnosticSeverity severity) { + switch (severity) { + case wgsl::DiagnosticSeverity::kError: + return required_to_be_uniform_error; + case wgsl::DiagnosticSeverity::kWarning: + return required_to_be_uniform_warning; + case wgsl::DiagnosticSeverity::kInfo: + return required_to_be_uniform_info; + default: + TINT_UNREACHABLE() << "unhandled severity"; + } + } + + /// @returns a LoopSwitchInfo for the given statement, allocating the LoopSwitchInfo if this is + /// the first call with the given statement. + LoopSwitchInfo& LoopSwitchInfoFor(const sem::Statement* stmt) { + return *loop_switch_infos.GetOrAdd(stmt, + [&] { return loop_switch_info_allocator.Create(); }); + } + + /// Disassociates the LoopSwitchInfo for the given statement. + void RemoveLoopSwitchInfoFor(const sem::Statement* stmt) { loop_switch_infos.Remove(stmt); } + + /// Create a new node. + /// @param tag_list a string list that will be used to identify the node for debugging purposes + /// @param ast the optional AST node that this node corresponds to + /// @returns the new node + Node* CreateNode([[maybe_unused]] std::initializer_list tag_list, + const ast::Node* ast = nullptr) { + auto* node = nodes.Create(ast); + +#if TINT_DUMP_UNIFORMITY_GRAPH + // Make the tag unique and set it. + // This only matters if we're dumping the graph. + std::string tag = ""; + for (auto& t : tag_list) { + tag += t; + } + std::string unique_tag = tag; + int suffix = 0; + while (tags_.Contains(unique_tag)) { + unique_tag = tag + "_$" + std::to_string(++suffix); + } + tags_.Add(unique_tag); + node->tag = name + "." + unique_tag; +#endif + + return node; + } + + /// Reset the visited status of every node in the graph. + void ResetVisited() { + for (auto* node : nodes.Objects()) { + node->visited_from = nullptr; + } + } + + private: + /// A list of tags that have already been used within the current function. + Hashset tags_; + + /// Map from control flow statements to the corresponding LoopSwitchInfo structure. + Hashmap loop_switch_infos; + + /// Allocator of LoopSwitchInfos + BlockAllocator loop_switch_info_allocator; +}; + +/// UniformityGraph is used to analyze the uniformity requirements and effects of functions in a +/// module. +class UniformityGraph { + public: + /// Constructor. + /// @param builder the program to analyze + explicit UniformityGraph(ProgramBuilder& builder, UniformityScope scope = UniformityScope::kAll) + : b(builder), sem_(b.Sem()), diagnostics_(builder.Diagnostics()), scope_(scope) {} + + /// Destructor. + ~UniformityGraph() {} + + /// Build and analyze the graph to determine whether the program satisfies the uniformity + /// constraints of WGSL. + /// @param dependency_graph the dependency-ordered module-scope declarations + /// @returns true if all uniformity constraints are satisfied, otherise false + bool Build(const DependencyGraph& dependency_graph) { +#if TINT_DUMP_UNIFORMITY_GRAPH + std::string graphName = "G_"; + switch (scope_) { + case UniformityScope::kAll: + graphName += "all"; + break; + case UniformityScope::kWorkgroup: + graphName += "workgroup"; + break; + case UniformityScope::kSubgroup: + graphName += "subgroup"; + break; + } + std::cout << "digraph " << graphName << " {\n"; + std::cout << "rankdir=BT\n"; +#endif + + // Process all functions in the module. + bool success = true; + for (auto* decl : dependency_graph.ordered_globals) { + if (auto* func = decl->As()) { + if (!ProcessFunction(func)) { + success = false; + break; + } + } + } + +#if TINT_DUMP_UNIFORMITY_GRAPH + std::cout << "\n}\n"; +#endif + + return success; + } + + private: + const ProgramBuilder& b; + const sem::Info& sem_; + diag::List& diagnostics_; + const UniformityScope scope_; + + /// Map of analyzed function results. + Hashmap functions_; + + /// The function currently being analyzed. + FunctionInfo* current_function_; + + /// A map from composite type to true/false to indicate whether it contains a subgroup matrix. + Hashmap composite_subgroup_matrix_info_; + + /// Create a new node. + /// @param tag_list a string list that will be used to identify the node for debugging purposes + /// @param ast the optional AST node that this node corresponds to + /// @returns the new node + inline Node* CreateNode(std::initializer_list tag_list, + const ast::Node* ast = nullptr) { + return current_function_->CreateNode(std::move(tag_list), ast); + } + + /// Get the symbol name of an AST expression. + /// @param expr the expression to get the symbol name of + /// @returns the symbol name + inline std::string NameFor(const ast::IdentifierExpression* expr) { + return expr->identifier->symbol.Name(); + } + + /// @param var the variable to get the name of + /// @returns the name of the variable @p var + inline std::string NameFor(const ast::Variable* var) { return var->name->symbol.Name(); } + + /// @param var the variable to get the name of + /// @returns the name of the variable @p var + inline std::string NameFor(const sem::Variable* var) { return NameFor(var->Declaration()); } + + /// @param fn the function to get the name of + /// @returns the name of the function @p fn + inline std::string NameFor(const sem::Function* fn) { + return fn->Declaration()->name->symbol.Name(); + } + + /// Process a function. + /// @param func the function to process + /// @returns true if there are no uniformity issues, false otherwise + bool ProcessFunction(const ast::Function* func) { + current_function_ = &functions_.Add(func, FunctionInfo(func, b)).value; + + // Process function body. + if (func->body) { + ProcessStatement(current_function_->cf_start, func->body); + } + +#if TINT_DUMP_UNIFORMITY_GRAPH + // Dump the graph for this function as a subgraph. + std::cout << "\nsubgraph cluster_" << current_function_->name << " {\n"; + std::cout << " label=" << current_function_->name << ";"; + for (auto* node : current_function_->nodes.Objects()) { + std::cout << "\n \"" << node->tag << "\";"; + for (auto* edge : node->edges) { + std::cout << "\n \"" << node->tag << "\" -> \"" << edge->tag << "\";"; + } + } + std::cout << "\n}\n"; +#endif + + /// Helper to generate a tag for the uniformity requirements of the parameter at `index`. + auto get_param_tag = [&](UniqueVector& reachable, size_t index) { + auto* param = sem_.Get(func->params[index]); + auto& param_info = current_function_->parameters[index]; + if (param->Type()->Is()) { + // For pointers, we distinguish between requiring uniformity of the contents versus + // the pointer itself. + if (reachable.Contains(param_info.ptr_input_contents)) { + return ParameterTag::ParameterContentsRequiredToBeUniform; + } else if (reachable.Contains(param_info.value)) { + return ParameterTag::ParameterValueRequiredToBeUniform; + } + } else if (reachable.Contains(current_function_->variables.Get(param))) { + // For non-pointers, the requirement is always on the value. + return ParameterTag::ParameterValueRequiredToBeUniform; + } + return ParameterTag::ParameterNoRestriction; + }; + + // Look at which nodes are reachable from "RequiredToBeUniform". + { + UniqueVector reachable; + auto traverse = [&](wgsl::DiagnosticSeverity severity) { + Traverse(current_function_->RequiredToBeUniform(severity), &reachable); + if (reachable.Contains(current_function_->may_be_non_uniform)) { + MakeError(*current_function_, current_function_->may_be_non_uniform, severity); + return false; + } + if (reachable.Contains(current_function_->cf_start)) { + if (current_function_->callsite_tag.tag == CallSiteTag::CallSiteNoRestriction) { + current_function_->callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, + severity}; + } + } + + // Set the tags to capture the direct uniformity requirements of each parameter. + for (size_t i = 0; i < func->params.Length(); i++) { + if (current_function_->parameters[i].tag_direct.tag == + ParameterTag::ParameterNoRestriction) { + current_function_->parameters[i].tag_direct = {get_param_tag(reachable, i), + severity}; + } + } + return true; + }; + if (!traverse(wgsl::DiagnosticSeverity::kError)) { + return false; + } else { + if (traverse(wgsl::DiagnosticSeverity::kWarning)) { + traverse(wgsl::DiagnosticSeverity::kInfo); + } + } + } + + // If "Value_return" exists, look at which nodes are reachable from it. + if (current_function_->value_return) { + current_function_->ResetVisited(); + + UniqueVector reachable; + Traverse(current_function_->value_return, &reachable); + if (reachable.Contains(current_function_->may_be_non_uniform)) { + current_function_->function_tag = ReturnValueMayBeNonUniform; + } + + // Set the tags to capture the uniformity requirements of each parameter with respect to + // the function return value. + for (size_t i = 0; i < func->params.Length(); i++) { + current_function_->parameters[i].tag_retval = {get_param_tag(reachable, i)}; + } + } + + // Traverse the graph for each pointer parameter. + for (size_t i = 0; i < func->params.Length(); i++) { + auto& param_info = current_function_->parameters[i]; + if (param_info.ptr_output_contents == nullptr) { + continue; + } + + // Reset "visited" state for all nodes. + current_function_->ResetVisited(); + + UniqueVector reachable; + Traverse(param_info.ptr_output_contents, &reachable); + if (reachable.Contains(current_function_->may_be_non_uniform)) { + param_info.pointer_may_become_non_uniform = true; + } + + // Check every parameter to see if it feeds into this parameter's output value. + // This includes checking this parameter (as it may feed into its own output value), so + // we do not skip the `i==j` case. + for (size_t j = 0; j < func->params.Length(); j++) { + auto tag = get_param_tag(reachable, j); + auto* source_param = sem_.Get(func->params[j]); + if (tag == ParameterTag::ParameterContentsRequiredToBeUniform) { + param_info.ptr_output_source_param_contents.Push(source_param); + } else if (tag == ParameterTag::ParameterValueRequiredToBeUniform) { + param_info.ptr_output_source_param_values.Push(source_param); + } + } + } + + return true; + } + + /// Process a statement, returning the new control flow node. + /// @param cf the input control flow node + /// @param stmt the statement to process d + /// @returns the new control flow node + Node* ProcessStatement(Node* cf, const ast::Statement* stmt) { + return Switch( + stmt, + + [&](const ast::AssignmentStatement* a) { + if (a->lhs->Is()) { + auto [cf_r, _] = ProcessExpression(cf, a->rhs); + return cf_r; + } + auto [cf_l, v_l, ident] = ProcessLValueExpression(cf, a->lhs); + auto [cf_r, v_r] = ProcessExpression(cf_l, a->rhs); + v_l->AddEdge(v_r); + + // Update the variable node for the LHS variable. + current_function_->variables.Set(ident, v_l); + + return cf_r; + }, + + [&](const ast::BlockStatement* block) { + Hashmap scoped_assignments; + auto* sem = sem_.Get(block); + { + // Push a new scope for variable assignments in the block. + current_function_->variables.Push(); + TINT_DEFER(current_function_->variables.Pop()); + + for (auto* s : block->statements) { + cf = ProcessStatement(cf, s); + if (!sem_.Get(s)->Behaviors().Contains(sem::Behavior::kNext)) { + break; + } + } + + auto* parent = sem->Parent(); + auto* loop = parent ? parent->As() : nullptr; + if (loop) { + auto& info = current_function_->LoopSwitchInfoFor(loop); + auto& loop_body_behavior = sem->Behaviors(); + + // We've reached the end of a loop body. If the loop does not + // unconditionally exit, handle the loop continuing block and propagate + // variable values to the next iteration. + if (loop_body_behavior.Contains(sem::Behavior::kNext) || + loop_body_behavior.Contains(sem::Behavior::kContinue)) { + // If there is a continuing block, process it before ending the block so + // that any variables declared in the loop body are visible to the + // continuing block. + if (auto* continuing = + loop->Declaration()->As()->continuing) { + // Set up input nodes for the continuing block, to merge data flow + // paths from all blocks that branch to the continuing block. + for (auto v : info.var_continuing_nodes) { + // If the loop body just falls through to the continuing block, + // add an edge to the node that represents the value at the end + // of the loop body. + if (loop_body_behavior.Contains(sem::Behavior::kNext)) { + auto* end_of_body = current_function_->variables.Get(v.key); + if (end_of_body) { + v.value->AddEdge(end_of_body); + } + } + + // Any references to this declaration from inside the continuing + // block should use the continuing input node. + current_function_->variables.Set(v.key, v.value); + } + + // Process the continuing block. + cf = ProcessStatement(cf, continuing); + } + + // Add edges from variable loop input nodes to their values at the end + // of the loop body/continuing. + for (auto v : info.var_in_nodes) { + auto* in_node = v.value; + auto* out_node = current_function_->variables.Get(v.key); + if (out_node != in_node) { + in_node->AddEdge(out_node); + } + } + } + } + + if (sem_.Get(block)) { + // We've reached the end of the function body. + // Add edges from pointer parameter outputs to their current value. + for (auto& param : current_function_->parameters) { + if (param.ptr_output_contents) { + param.ptr_output_contents->AddEdge( + current_function_->variables.Get(param.sem)); + } + } + } + + scoped_assignments = std::move(current_function_->variables.Top()); + } + + // Propagate all variables assignments to the containing scope if the behavior is + // 'Next'. + auto& behaviors = sem->Behaviors(); + if (behaviors.Contains(sem::Behavior::kNext)) { + for (auto& var : scoped_assignments) { + current_function_->variables.Set(var.key, var.value); + } + } + + // Remove any variables declared in this scope from the set of in-scope variables. + for (auto decl : sem->Decls()) { + current_function_->local_var_decls.Remove(decl.value.variable); + } + + return cf; + }, + + [&](const ast::BreakStatement* brk) { + // Find the loop or switch statement that we are in. + auto* parent = sem_.Get(brk) + ->FindFirstParent(); + + auto& info = current_function_->LoopSwitchInfoFor(parent); + + // Propagate variable values to the loop/switch exit nodes. + for (auto& var : current_function_->local_var_decls) { + // Skip variables that were declared inside this loop/switch. + if (auto* lv = var->As(); + lv && + lv->Statement()->FindFirstParent([&](auto* s) { return s == parent; })) { + continue; + } + + // Add an edge from the variable exit node to its value at this point. + auto* exit_node = info.var_exit_nodes.GetOrAdd(var, [&] { + auto name = NameFor(var); + return CreateNode({name, "_value_", info.type, "_exit"}); + }); + exit_node->AddEdge(current_function_->variables.Get(var)); + } + + return cf; + }, + + [&](const ast::BreakIfStatement* brk) { + // This works very similar to the IfStatement uniformity below, execpt instead of + // processing the body, we directly inline the BreakStatement uniformity from + // above. + auto* sem = sem_.Get(brk); + + auto [_, v_cond] = ProcessExpression(cf, brk->condition); + + // Add a diagnostic node to capture the control flow change. + auto* v = CreateNode({"break_if_stmt"}, brk); + v->affects_control_flow = true; + v->AddEdge(v_cond); + + { + auto* parent = sem->FindFirstParent(); + auto& info = current_function_->LoopSwitchInfoFor(parent); + + // Propagate variable values to the loop exit nodes. + for (auto& var : current_function_->local_var_decls) { + // Skip variables that were declared inside this loop. + if (auto* lv = var->As(); + lv && lv->Statement()->FindFirstParent( + [&](auto* s) { return s == parent; })) { + continue; + } + + // Add an edge from the variable exit node to its value at this point. + auto* exit_node = info.var_exit_nodes.GetOrAdd(var, [&] { + auto name = NameFor(var); + return CreateNode({name, "_value_", info.type, "_exit"}); + }); + + exit_node->AddEdge(current_function_->variables.Get(var)); + } + } + + if (sem->Behaviors() != sem::Behaviors{sem::Behavior::kNext}) { + auto* cf_end = CreateNode({"break_if_CFend"}); + cf_end->AddEdge(v); + return cf_end; + } + return cf; + }, + + [&](const ast::CallStatement* c) { + auto [cf1, _] = ProcessCall(cf, c->expr); + return cf1; + }, + + [&](const ast::CompoundAssignmentStatement* c) { + // The compound assignment statement `a += b` is equivalent to: + // let p = &a; + // *p = *p + b; + + // Evaluate the LHS. + auto [cf1, l1, ident] = ProcessLValueExpression(cf, c->lhs); + + // Get the current value loaded from the LHS reference before evaluating the RHS. + auto* lhs_load = current_function_->variables.Get(ident); + + // Evaluate the RHS. + auto [cf2, v2] = ProcessExpression(cf1, c->rhs); + + // Create a node for the resulting value. + auto* result = CreateNode({"binary_expr_result"}); + result->AddEdge(v2); + if (lhs_load) { + result->AddEdge(lhs_load); + } + + // Update the variable node for the LHS variable. + l1->AddEdge(result); + current_function_->variables.Set(ident, l1); + + return cf2; + }, + + [&](const ast::ContinueStatement* c) { + // Find the loop statement that we are in. + auto* parent = sem_.Get(c) + ->FindFirstParent(); + auto& info = current_function_->LoopSwitchInfoFor(parent); + + // Check if the loop statement has a continuing statement that we will branch to. + bool has_continuing = false; + if (auto* loop = parent->As()) { + auto* continuing = loop->Declaration()->As()->continuing; + has_continuing = continuing && !continuing->Empty(); + } else if (auto* for_loop = parent->As()) { + has_continuing = for_loop->Declaration()->continuing != nullptr; + } + + if (has_continuing) { + // Create continuing statement input nodes for any variables in scope before + // this continue statement. + for (auto& v : current_function_->local_var_decls) { + // Only create the node the first time we see the variable. + auto* in_node = info.var_continuing_nodes.GetOrAdd(v, [&] { + auto name = NameFor(v); + return CreateNode({name, "_value_loop_continuing_in"}, + v->Declaration()); + }); + in_node->AddEdge(current_function_->variables.Get(v)); + } + } else { + // There is no continuing statement, so propagate values directly to the loop + // input nodes. This only needs to be done for variables that were in scope + // before the start of the loop. + for (auto v : info.var_in_nodes) { + auto* in_node = v.value; + auto* out_node = current_function_->variables.Get(v.key); + if (out_node != in_node) { + in_node->AddEdge(out_node); + } + } + } + + return cf; + }, + + [&](const ast::DiscardStatement*) { return cf; }, + + [&](const ast::ForLoopStatement* f) { + auto* sem_loop = sem_.Get(f); + auto* cf_iter_start = CreateNode({"loop_start"}); + + // Insert the initializer before the loop. + auto* cf_init_end = cf; + if (f->initializer) { + cf_init_end = ProcessStatement(cf, f->initializer); + } + auto* cf_body_start = cf_iter_start; + + auto& info = current_function_->LoopSwitchInfoFor(sem_loop); + info.type = "forloop"; + + // Create input nodes for any variables declared before this loop. + for (auto& v : current_function_->local_var_decls) { + auto* in_node = CreateNode({NameFor(v), "_value_forloop_in"}); + in_node->AddEdge(current_function_->variables.Get(v)); + info.var_in_nodes.Replace(v, in_node); + current_function_->variables.Set(v, in_node); + } + + // Insert the condition at the start of the loop body. + if (f->condition) { + auto [cf_cond, v] = ProcessExpression(cf_iter_start, f->condition); + auto* cf_condition_end = CreateNode({"for_condition_CFend"}, f); + cf_condition_end->affects_control_flow = true; + cf_condition_end->AddEdge(v); + cf_body_start = cf_condition_end; + + // Propagate assignments to the loop exit nodes. + for (auto& var : current_function_->local_var_decls) { + auto* exit_node = info.var_exit_nodes.GetOrAdd(var, [&] { + auto name = NameFor(var); + return CreateNode({name, "_value_", info.type, "_exit"}); + }); + exit_node->AddEdge(current_function_->variables.Get(var)); + } + } + auto* cf1 = ProcessStatement(cf_body_start, f->body); + + auto& loop_body_behavior = sem_.Get(f->body)->Behaviors(); + const bool body_has_next_or_continue = + loop_body_behavior.Contains(sem::Behavior::kNext) || + loop_body_behavior.Contains(sem::Behavior::kContinue); + const bool body_has_return = loop_body_behavior.Contains(sem::Behavior::kReturn); + + auto* cf_end_of_iter = cf1; + // Insert the continuing statement at the end of the loop body, if it is reachable. + if (f->continuing && body_has_next_or_continue) { + // Set up input nodes for the continuing block, to merge data flow paths from + // all blocks that branch to the continuing block. + for (auto v : info.var_continuing_nodes) { + // If the loop body just falls through to the continuing block, add an edge + // to the node that represents the value at the end of the loop body. + if (loop_body_behavior.Contains(sem::Behavior::kNext)) { + auto* end_of_body = current_function_->variables.Get(v.key); + if (end_of_body) { + v.value->AddEdge(end_of_body); + } + } + + // Any references to this declaration from inside the continuing block + // should use the continuing input node. + current_function_->variables.Set(v.key, v.value); + } + + auto* cf2 = ProcessStatement(cf1, f->continuing); + cf_end_of_iter = cf2; + } + if (body_has_next_or_continue) { + // The backedge of the loop is reachable in a static sense. + // This edge allows non-uniformity present at the end of the + // iteration to affect the next iteration. + cf_iter_start->AddEdge(cf_end_of_iter); + } + // Desugaring the for-loop to a loop-loop moves the initializer + // to just before the loop construct. So 'CF' in the spec rules for + // loop{} is represented by cf_init_end. + cf_iter_start->AddEdge(cf_init_end); + + // Add edges from variable loop input nodes to their values at the end of the loop + // (including the loop continuing statement). + for (auto& v : info.var_in_nodes) { + auto* in_node = v.value; + auto* out_node = current_function_->variables.Get(v.key); + if (out_node != in_node) { + in_node->AddEdge(out_node); + } + } + + // Set each variable's exit node as its value in the outer scope. + for (auto& v : info.var_exit_nodes) { + current_function_->variables.Set(v.key, v.value); + } + + if (f->initializer) { + // Remove variables declared in the for-loop initializer from the current scope. + if (auto* decl = f->initializer->As()) { + current_function_->local_var_decls.Remove(sem_.Get(decl->variable)); + } + } + + current_function_->RemoveLoopSwitchInfoFor(sem_loop); + + // Return the resulting control flow node. + // This structures the case analysis differently from the spec + // text in https://github.com/gpuweb/gpuweb/pull/5419 + if (body_has_return) { + if (body_has_next_or_continue) { + // Control (statically) reaches the end of the iteration, + // and then back to the top of the next iteration. + return cf_iter_start; + } else { + // Control does not statically reach the end of the + // iteration, nor the continuing block (update clause). + return cf1; + } + } + // When the loop does not include a return, divergence introduced + // by the loop resolves at the end of the loop. + return cf; + }, + + [&](const ast::WhileStatement* w) { + auto* sem_loop = sem_.Get(w); + auto* cfx = CreateNode({"loop_start"}); + + auto* cf_start = cf; + + auto& info = current_function_->LoopSwitchInfoFor(sem_loop); + info.type = "whileloop"; + + // Create input nodes for any variables declared before this loop. + for (auto& v : current_function_->local_var_decls) { + auto* in_node = CreateNode({NameFor(v), "_value_forloop_in"}); + in_node->AddEdge(current_function_->variables.Get(v)); + info.var_in_nodes.Replace(v, in_node); + current_function_->variables.Set(v, in_node); + } + + // Insert the condition at the start of the loop body. + { + auto [cf_cond, v] = ProcessExpression(cfx, w->condition); + auto* cf_condition_end = CreateNode({"while_condition_CFend"}, w); + cf_condition_end->affects_control_flow = true; + cf_condition_end->AddEdge(v); + cf_start = cf_condition_end; + } + + // Propagate assignments to the loop exit nodes. + for (auto& var : current_function_->local_var_decls) { + auto* exit_node = info.var_exit_nodes.GetOrAdd(var, [&] { + auto name = NameFor(var); + return CreateNode({name, "_value_", info.type, "_exit"}); + }); + exit_node->AddEdge(current_function_->variables.Get(var)); + } + auto* cf1 = ProcessStatement(cf_start, w->body); + cfx->AddEdge(cf1); + cfx->AddEdge(cf); + + // Add edges from variable loop input nodes to their values at the end of the loop. + for (auto v : info.var_in_nodes) { + auto* in_node = v.value; + auto* out_node = current_function_->variables.Get(v.key); + if (out_node != in_node) { + in_node->AddEdge(out_node); + } + } + + // Set each variable's exit node as its value in the outer scope. + for (auto v : info.var_exit_nodes) { + current_function_->variables.Set(v.key, v.value); + } + + current_function_->RemoveLoopSwitchInfoFor(sem_loop); + + if (sem_loop->Behaviors() == sem::Behaviors{sem::Behavior::kNext}) { + return cf; + } else { + return cfx; + } + }, + + [&](const ast::IfStatement* i) { + auto* sem_if = sem_.Get(i); + auto [_, v_cond] = ProcessExpression(cf, i->condition); + + // Add a diagnostic node to capture the control flow change. + auto* v = CreateNode({"if_stmt"}, i); + v->affects_control_flow = true; + v->AddEdge(v_cond); + + Hashmap true_vars; + Hashmap false_vars; + + // Helper to process a statement with a new scope for variable assignments. + // Populates `assigned_vars` with new nodes for any variables that are assigned in + // this statement. + auto process_in_scope = + [&](Node* cf_in, const ast::Statement* s, + Hashmap& assigned_vars) { + // Push a new scope for variable assignments. + current_function_->variables.Push(); + + // Process the statement. + auto* cf_out = ProcessStatement(cf_in, s); + + assigned_vars = current_function_->variables.Top(); + + // Pop the scope and return. + current_function_->variables.Pop(); + return cf_out; + }; + + auto* cf1 = process_in_scope(v, i->body, true_vars); + + bool true_has_next = sem_.Get(i->body)->Behaviors().Contains(sem::Behavior::kNext); + bool false_has_next = true; + + Node* cf2 = nullptr; + if (i->else_statement) { + cf2 = process_in_scope(v, i->else_statement, false_vars); + + false_has_next = + sem_.Get(i->else_statement)->Behaviors().Contains(sem::Behavior::kNext); + } + + // Update values for any variables assigned in the if or else blocks. + for (auto& var : current_function_->local_var_decls) { + // Skip variables not assigned in either block. + if (!true_vars.Contains(var) && !false_vars.Contains(var)) { + continue; + } + + // Create an exit node for the variable. + auto* out_node = CreateNode({NameFor(var), "_value_if_exit"}); + + // Add edges to the assigned value or the initial value. + // Only add edges if the behavior for that block contains 'Next'. + if (true_has_next) { + if (true_vars.Contains(var)) { + out_node->AddEdge(*true_vars.Get(var)); + } else { + out_node->AddEdge(current_function_->variables.Get(var)); + } + } + if (false_has_next) { + if (false_vars.Contains(var)) { + out_node->AddEdge(*false_vars.Get(var)); + } else { + out_node->AddEdge(current_function_->variables.Get(var)); + } + } + + current_function_->variables.Set(var, out_node); + } + + if (sem_if->Behaviors() != sem::Behaviors{sem::Behavior::kNext}) { + auto* cf_end = CreateNode({"if_CFend"}); + cf_end->AddEdge(cf1); + if (cf2) { + cf_end->AddEdge(cf2); + } + return cf_end; + } + return cf; + }, + + [&](const ast::IncrementDecrementStatement* i) { + // The increment/decrement statement `i++` is equivalent to `i = i + 1`. + + // Evaluate the LHS. + auto [cf1, l1, ident] = ProcessLValueExpression(cf, i->lhs); + + // Get the current value loaded from the LHS reference. + auto* lhs_load = current_function_->variables.Get(ident); + + // Create a node for the resulting value. + auto* result = CreateNode({"incdec_result"}); + result->AddEdge(cf1); + if (lhs_load) { + result->AddEdge(lhs_load); + } + + // Update the variable node for the LHS variable. + l1->AddEdge(result); + current_function_->variables.Set(ident, l1); + + return cf1; + }, + + [&](const ast::LoopStatement* l) { + auto* sem_loop = sem_.Get(l); + auto* cfx = CreateNode({"loop_start"}); + + auto& info = current_function_->LoopSwitchInfoFor(sem_loop); + info.type = "loop"; + + // Create input nodes for any variables declared before this loop. + for (auto& v : current_function_->local_var_decls) { + auto name = NameFor(v); + auto* in_node = CreateNode({name, "_value_loop_in"}, v->Declaration()); + in_node->AddEdge(current_function_->variables.Get(v)); + info.var_in_nodes.Replace(v, in_node); + current_function_->variables.Set(v, in_node); + } + + // Note: The continuing block is processed as a special case at the end of + // processing the loop body BlockStatement. This is so that variable declarations + // inside the loop body are visible to the continuing statement. + auto* cf1 = ProcessStatement(cfx, l->body); + const auto& body_behaviors = sem_.Get(l->body)->Behaviors(); + if (body_behaviors.Contains(sem::Behavior::kNext) || + body_behaviors.Contains(sem::Behavior::kContinue)) { + // Control reaches the backedge, so add an edge from the top + // of the loop to the latch block. + cfx->AddEdge(cf1); + } + cfx->AddEdge(cf); + + // Set each variable's exit node as its value in the outer scope. + for (auto v : info.var_exit_nodes) { + current_function_->variables.Set(v.key, v.value); + } + + current_function_->RemoveLoopSwitchInfoFor(sem_loop); + + if (sem_loop->Behaviors().Contains(sem::Behavior::kReturn)) { + return cf1; + } else { + return cf; + } + }, + + [&](const ast::ReturnStatement* r) { + Node* cf_ret; + if (r->value) { + auto [cf1, v] = ProcessExpression(cf, r->value); + current_function_->value_return->AddEdge(v); + cf_ret = cf1; + } else { + TINT_ASSERT(cf != nullptr); + cf_ret = cf; + } + + // Add edges from each pointer parameter output to its current value. + for (auto& param : current_function_->parameters) { + if (param.ptr_output_contents) { + param.ptr_output_contents->AddEdge( + current_function_->variables.Get(param.sem)); + } + } + + return cf_ret; + }, + + [&](const ast::SwitchStatement* s) { + auto* sem_switch = sem_.Get(s); + auto [cfx, v_cond] = ProcessExpression(cf, s->condition); + + // Add a diagnostic node to capture the control flow change. + auto* v = CreateNode({"switch_stmt"}, s); + v->affects_control_flow = true; + v->AddEdge(v_cond); + + Node* cf_end = nullptr; + if (sem_switch->Behaviors() != sem::Behaviors{sem::Behavior::kNext}) { + cf_end = CreateNode({"switch_CFend"}); + } + + auto& info = current_function_->LoopSwitchInfoFor(sem_switch); + info.type = "switch"; + + auto* cf_n = v; + for (auto* c : s->body) { + auto* sem_case = sem_.Get(c); + + current_function_->variables.Push(); + cf_n = ProcessStatement(v, c->body); + + if (cf_end) { + cf_end->AddEdge(cf_n); + } + + if (sem_case->Behaviors().Contains(sem::Behavior::kNext)) { + // Propagate variable values to the switch exit nodes. + for (auto& var : current_function_->local_var_decls) { + // Skip variables that were declared inside the switch. + if (auto* lv = var->As(); + lv && lv->Statement()->FindFirstParent( + [&](auto* st) { return st == sem_switch; })) { + continue; + } + + // Add an edge from the variable exit node to its new value. + auto* exit_node = info.var_exit_nodes.GetOrAdd(var, [&] { + auto name = NameFor(var); + return CreateNode({name, "_value_", info.type, "_exit"}); + }); + exit_node->AddEdge(current_function_->variables.Get(var)); + } + } + current_function_->variables.Pop(); + } + + // Update nodes for any variables assigned in the switch statement. + for (auto var : info.var_exit_nodes) { + current_function_->variables.Set(var.key, var.value); + } + + return cf_end ? cf_end : cf; + }, + + [&](const ast::VariableDeclStatement* decl) { + Node* node; + auto* sem_var = sem_.Get(decl->variable); + if (decl->variable->initializer) { + auto [cf1, v] = ProcessExpression(cf, decl->variable->initializer); + cf = cf1; + node = v; + + // Store if lhs is a partial pointer + if (sem_var->Type()->Is()) { + auto* init = sem_.Get(decl->variable->initializer); + if (auto* unary_init = init->Declaration()->As()) { + auto* e = UnwrapIndirectAndAddressOfChain(unary_init); + if (e->Is()) { + current_function_->partial_ptrs.Add(sem_var); + } + } + } + } else { + node = cf; + + // Subgroup matrix variables cannot be declared in non-uniform control flow. + if (ContainsSubgroupMatrix(sem_var->Type()->UnwrapRef())) { + auto severity = sem_.DiagnosticSeverity( + decl, wgsl::ChromiumDiagnosticRule::kSubgroupMatrixUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kWorkgroup) { + // Create an extra node so that we can produce good diagnostics. + node = CreateNode({NameFor(sem_var), "_decl"}, decl); + node->type = Node::kSubgroupMatrixVariableDeclaration; + node->AddEdge(cf); + current_function_->RequiredToBeUniform(severity)->AddEdge(node); + } + } + } + current_function_->variables.Set(sem_var, node); + + if (decl->variable->Is()) { + current_function_->local_var_decls.Add( + sem_.Get(decl->variable)); + } + + return cf; + }, + + [&](const ast::ConstAssert*) { + return cf; // No impact on uniformity + }, + + TINT_ICE_ON_NO_MATCH); + } + + /// @returns true if @p builtin is workgroup-uniform + bool IsWorkgroupUniform(core::BuiltinValue builtin) { + switch (builtin) { + case core::BuiltinValue::kNumSubgroups: + case core::BuiltinValue::kNumWorkgroups: + case core::BuiltinValue::kSubgroupSize: + case core::BuiltinValue::kWorkgroupId: + return true; + case core::BuiltinValue::kSubgroupId: + return scope_ == UniformityScope::kSubgroup; + default: + return false; + } + } + + /// Process an identifier expression. + /// @param cf the input control flow node + /// @param ident the identifier expression to process + /// @param load_rule true if the load rule is being invoked on this identifier + /// @returns a pair of (control flow node, value node) + std::pair ProcessIdentExpression(Node* cf, + const ast::IdentifierExpression* ident, + bool load_rule = false) { + // Helper to check if the entry point attribute of `obj` indicates non-uniformity. + auto has_nonuniform_entry_point_attribute = [&](auto* obj, auto* entry_point) { + // Only the num_subgroups, num_workgroups and workgroup_id builtins, and subgroup_size + // builtin used in compute stage are uniform. + if (auto* builtin_attr = ast::GetAttribute(obj->attributes)) { + // Some builtins are workgroup-uniform in compute stages. + // All builtins are non-uniform in non-compute stages. + // Notably, we consider `subgroup_size` to be non-uniform in fragment shaders. + if (entry_point->PipelineStage() == ast::PipelineStage::kCompute) { + return !IsWorkgroupUniform(builtin_attr->builtin); + } + } + return true; + }; + + auto* node = CreateNode({NameFor(ident), "_ident_expr"}, ident); + auto* sem_ident = sem_.GetVal(ident); + TINT_ASSERT(sem_ident); + auto* var_user = sem_ident->Unwrap()->As(); + auto* sem = var_user->Variable(); + return Switch( + sem, + + [&](const sem::Parameter* param) { + auto* user_func = param->Owner()->As(); + if (user_func && user_func->Declaration()->IsEntryPoint()) { + if (auto* str = param->Type()->As()) { + // We consider the whole struct to be non-uniform if any one of its members + // is non-uniform. + bool uniform = true; + for (auto* member : str->Members()) { + if (has_nonuniform_entry_point_attribute(member->Declaration(), + user_func->Declaration())) { + uniform = false; + } + } + node->AddEdge(uniform ? cf : current_function_->may_be_non_uniform); + return std::make_pair(cf, node); + } else { + if (has_nonuniform_entry_point_attribute(param->Declaration(), + user_func->Declaration())) { + node->AddEdge(current_function_->may_be_non_uniform); + } else { + node->AddEdge(cf); + } + return std::make_pair(cf, node); + } + } else { + node->AddEdge(cf); + + auto* current_value = current_function_->variables.Get(param); + if (auto* ptr = param->Type()->As()) { + if (load_rule) { + if (ptr->AddressSpace() == core::AddressSpace::kFunction || + ptr->Access() == core::Access::kRead) { + // We are loading from a pointer to a function-scope variable or an + // immutable module-scope variable, so add an edge to its contents. + node->AddEdge(current_value); + } else { + // We are loading from a pointer to a mutable module-scope variable, + // which always has non-uniform contents. + node->AddEdge(current_function_->may_be_non_uniform); + } + } else { + // This is a pointer parameter that we are not loading from, so add an + // edge to the pointer value itself. + node->AddEdge(current_function_->parameters[param->Index()].value); + } + } else { + // The parameter is a value, so add an edge to it. + node->AddEdge(current_value); + } + + return std::make_pair(cf, node); + } + }, + + [&](const sem::GlobalVariable* global) { + // Loads from global read-write variables may be non-uniform. + if (global->Declaration()->Is() && + global->Access() != core::Access::kRead && load_rule) { + node->AddEdge(current_function_->may_be_non_uniform); + } else { + node->AddEdge(cf); + } + return std::make_pair(cf, node); + }, + + [&](const sem::LocalVariable* local) { + node->AddEdge(cf); + + auto* local_value = current_function_->variables.Get(local); + if (local->Type()->Is()) { + if (load_rule) { + // We are loading from the pointer, so add an edge to its contents. + auto* root = var_user->RootIdentifier(); + if (root->Is()) { + if (root->Access() != core::Access::kRead) { + // The contents of a mutable global variable is always non-uniform. + node->AddEdge(current_function_->may_be_non_uniform); + } + } else { + node->AddEdge(current_function_->variables.Get(root)); + } + + // The uniformity of the contents also depends on the uniformity of the + // pointer itself. For a pointer captured in a let declaration, this will + // come from the value node of that declaration. + node->AddEdge(local_value); + } else { + // The variable is a pointer that we are not loading from, so add an edge to + // the pointer value itself. + node->AddEdge(local_value); + } + } else if (local->Type()->Is()) { + if (load_rule) { + // We are loading from the reference, so add an edge to its contents. + node->AddEdge(local_value); + } else { + // References to local variables (i.e. var declarations) are always uniform, + // so no other edges needed. + } + } else { + // The identifier is a value declaration, so add an edge to it. + node->AddEdge(local_value); + } + + return std::make_pair(cf, node); + }, + + TINT_ICE_ON_NO_MATCH); + } + + /// Process an expression. + /// @param cf the input control flow node + /// @param expr the expression to process + /// @param load_rule true if the load rule is being invoked on this expression + /// @returns a pair of (control flow node, value node) + std::pair ProcessExpression(Node* cf, + const ast::Expression* expr, + bool load_rule = false) { + if (sem_.Get(expr)) { + // Set the load-rule flag to indicate that identifier expressions in this sub-tree + // should add edges to the contents of the variables that they refer to. + load_rule = true; + } + + return Switch( + expr, + + [&](const ast::BinaryExpression* e) { + if (e->IsLogical()) { + // Short-circuiting binary operators are a special case. + auto [cf1, v1] = ProcessExpression(cf, e->lhs); + + // Add a diagnostic node to capture the control flow change. + auto* v1_cf = CreateNode({"short_circuit_op"}, e); + v1_cf->affects_control_flow = true; + v1_cf->AddEdge(v1); + + auto [cf2, v2] = ProcessExpression(v1_cf, e->rhs); + return std::pair(cf, v2); + } else { + auto [cf1, v1] = ProcessExpression(cf, e->lhs); + auto [cf2, v2] = ProcessExpression(cf1, e->rhs); + auto* result = CreateNode({"binary_expr_result"}, e); + result->AddEdge(v1); + result->AddEdge(v2); + return std::pair(cf2, result); + } + }, + + [&](const ast::CallExpression* c) { return ProcessCall(cf, c); }, + + [&](const ast::IdentifierExpression* i) { + return ProcessIdentExpression(cf, i, load_rule); + }, + + [&](const ast::IndexAccessorExpression* i) { + auto [cf1, v1] = ProcessExpression(cf, i->object, load_rule); + auto [cf2, v2] = ProcessExpression(cf1, i->index); + auto* result = CreateNode({"index_accessor_result"}); + result->AddEdge(v1); + result->AddEdge(v2); + return std::pair(cf2, result); + }, + + [&](const ast::LiteralExpression*) { return std::make_pair(cf, cf); }, + + [&](const ast::MemberAccessorExpression* m) { + return ProcessExpression(cf, m->object, load_rule); + }, + + [&](const ast::UnaryOpExpression* u) { + return ProcessExpression(cf, u->expr, load_rule); + }, + + TINT_ICE_ON_NO_MATCH); + } + + /// @param u unary expression with op == kIndirection + /// @returns true if `u` is an indirection unary expression that ultimately dereferences a + /// partial pointer, false otherwise. + bool IsDerefOfPartialPointer(const ast::UnaryOpExpression* u) { + TINT_ASSERT(u->op == core::UnaryOp::kIndirection); + + // To determine if we're dereferencing a partial pointer, unwrap *& + // chains; if the final expression is an identifier, see if it's a + // partial pointer. If it's not an identifier, then it must be an + // index/member accessor expression, and thus a partial pointer. + auto* e = UnwrapIndirectAndAddressOfChain(u); + if (auto* var_user = sem_.Get(e)) { + if (current_function_->partial_ptrs.Contains(var_user->Variable())) { + return true; + } + } else { + TINT_ASSERT(e->Is()); + return true; + } + return false; + } + + /// LValue holds the Nodes returned by ProcessLValueExpression() + struct LValue { + /// The control-flow node for an LValue expression + Node* cf = nullptr; + + /// The new value node for an LValue expression + Node* new_val = nullptr; + + /// The root identifier for an LValue expression. + const sem::Variable* root_identifier = nullptr; + }; + + /// Process an LValue expression. + /// @param cf the input control flow node + /// @param expr the expression to process + /// @param is_dereferencing `true` if we are dereferencing a pointer + /// @param is_partial_reference `true` if we are referencing a subset of a variable + /// @returns a tuple of (control flow node, variable node, root identifier) + LValue ProcessLValueExpression(Node* cf, + const ast::Expression* expr, + bool is_dereferencing = false, + bool is_partial_reference = false) { + return Switch( + expr, + + [&](const ast::IdentifierExpression* i) { + auto* sem = sem_.GetVal(i)->UnwrapLoad()->As(); + auto result = Switch( + sem->Variable(), + [&](const sem::GlobalVariable*) { + // Pointers cannot be stored in module-scope variables, so we should never + // be dereferencing here. + TINT_ASSERT(!is_dereferencing); + + return LValue{cf, current_function_->may_be_non_uniform, nullptr}; + }, + [&](const sem::LocalVariable* local) { + Node* value = nullptr; + const sem::Variable* root_ident = local; + if (is_dereferencing) { + // If we are dereferencing then we must have a pointer, and the only + // declaration that can hold a pointer is a `let`. + TINT_ASSERT(local->Declaration()->Is() && + local->Type()->Is()); + + // Determine the root identifier for the contents of the pointer. + root_ident = local->Initializer()->RootIdentifier(); + + // Create a new value node for the contents of the pointer. + value = CreateNode({NameFor(root_ident), "_contents"}); + + // The uniformity of the value depends on the pointer itself. + value->AddEdge(current_function_->variables.Get(local)); + } else { + // Create a new value node for this variable. + value = CreateNode({NameFor(i), "_lvalue"}); + } + + return LValue{cf, value, root_ident}; + }, + [&](const sem::Parameter* param) { + // Parameters can only be LValues when we are dereferencing a pointer. + TINT_ASSERT(is_dereferencing && param->Type()->Is()); + + // Create a new value node for the contents of the pointer. + auto* value = CreateNode({NameFor(i), "_contents"}); + + // The uniformity of the value depends on the pointer itself. + value->AddEdge(current_function_->parameters[param->Index()].value); + + return LValue{cf, value, param}; + }, + [&](Default) -> LValue { + TINT_ICE() << "unknown lvalue identifier expression type: " + << std::string(sem->Variable()->TypeInfo().name); + }); + + // If the identifier is part of an expression that is a partial reference to a + // variable (e.g. index or member access), we link back to the variable's previous + // value. If the previous value was non-uniform, a partial assignment will not make + // it uniform. + auto* old_value = current_function_->variables.Get(result.root_identifier); + if (is_partial_reference && old_value) { + result.new_val->AddEdge(old_value); + } + + return result; + }, + + [&](const ast::IndexAccessorExpression* i) { + // If the source object is a pointer, there is an implicit dereference due to the + // pointer_composite_access language feature. + is_dereferencing = + is_dereferencing || sem_.GetVal(i->object)->Type()->Is(); + + auto [cf1, l1, root_ident] = + ProcessLValueExpression(cf, i->object, is_dereferencing, + /*is_partial_reference*/ true); + auto [cf2, v2] = ProcessExpression(cf1, i->index); + l1->AddEdge(v2); + return LValue{cf2, l1, root_ident}; + }, + + [&](const ast::MemberAccessorExpression* m) { + // If the source object is a pointer, there is an implicit dereference due to the + // pointer_composite_access language feature. + is_dereferencing = + is_dereferencing || sem_.GetVal(m->object)->Type()->Is(); + + return ProcessLValueExpression(cf, m->object, is_dereferencing, + /*is_partial_reference*/ true); + }, + + [&](const ast::UnaryOpExpression* u) { + if (u->op == core::UnaryOp::kIndirection) { + return ProcessLValueExpression( + cf, u->expr, + /* is_dereferencing */ true, + /* is_partial_reference */ is_partial_reference || + IsDerefOfPartialPointer(u)); + } + return ProcessLValueExpression(cf, u->expr, + /* is_dereferencing */ false, + /* is_partial_reference */ is_partial_reference); + }, + + TINT_ICE_ON_NO_MATCH); + } + + /// Process a function call expression. + /// @param cf the input control flow node + /// @param call the function call to process + /// @returns a pair of (control flow node, value node) + std::pair ProcessCall(Node* cf, const ast::CallExpression* call) { + std::string name = NameFor(call->target); + + // Process call arguments + Node* cf_last_arg = cf; + Vector args; + Vector ptrarg_contents; + ptrarg_contents.Resize(call->args.Length()); + for (size_t i = 0; i < call->args.Length(); i++) { + auto [cf_i, arg_i] = ProcessExpression(cf_last_arg, call->args[i]); + + // Capture the index of this argument in a new node. + // Note: This is an additional node that isn't described in the specification, for the + // purpose of providing diagnostic information. + Node* arg_node = CreateNode({name, "_arg_", std::to_string(i)}, call); + arg_node->type = Node::kFunctionCallArgumentValue; + arg_node->arg_index = static_cast(i); + arg_node->AddEdge(arg_i); + + // For pointer arguments, create an additional node to represent the contents of that + // pointer prior to the function call. + auto* sem_arg = sem_.GetVal(call->args[i]); + if (sem_arg->Type()->Is()) { + auto* arg_contents = + CreateNode({name, "_ptrarg_", std::to_string(i), "_contents"}, call); + arg_contents->type = Node::kFunctionCallArgumentContents; + arg_contents->arg_index = static_cast(i); + + auto* root = sem_arg->RootIdentifier(); + if (root->Is()) { + if (root->Access() != core::Access::kRead) { + // The contents of a mutable global variable is always non-uniform. + arg_contents->AddEdge(current_function_->may_be_non_uniform); + } + } else { + arg_contents->AddEdge(current_function_->variables.Get(root)); + } + arg_contents->AddEdge(arg_node); + ptrarg_contents[i] = arg_contents; + } + + cf_last_arg = cf_i; + args.Push(arg_node); + } + + // Note: This is an additional node that isn't described in the specification, for the + // purpose of providing diagnostic information. + Node* call_node = CreateNode({name, "_call"}, call); + call_node->AddEdge(cf_last_arg); + + Node* result = CreateNode({name, "_return_value"}, call); + result->type = Node::kFunctionCallReturnValue; + Node* cf_after = CreateNode({"CF_after_", name}, call); + + auto default_severity = kUniformityFailuresAsError ? wgsl::DiagnosticSeverity::kError + : wgsl::DiagnosticSeverity::kWarning; + + // Get tags for the callee. + CallSiteTag callsite_tag = {CallSiteTag::CallSiteNoRestriction}; + FunctionTag function_tag = NoRestriction; + auto* sem = SemCall(call); + const FunctionInfo* func_info = nullptr; + Switch( + sem->Target(), + [&](const sem::BuiltinFn* builtin) { + // Most builtins have no restrictions. The exceptions are barriers, derivatives, + // some texture sampling builtins, and atomics. + if (builtin->IsBarrier() && scope_ != UniformityScope::kSubgroup) { + callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, default_severity}; + } else if (builtin->Fn() == wgsl::BuiltinFn::kWorkgroupUniformLoad && + scope_ != UniformityScope::kSubgroup) { + callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, default_severity}; + } else if (builtin->IsDerivative() || + builtin->Fn() == wgsl::BuiltinFn::kTextureSample || + builtin->Fn() == wgsl::BuiltinFn::kTextureSampleBias || + builtin->Fn() == wgsl::BuiltinFn::kTextureSampleCompare) { + // Get the severity of derivative uniformity violations in this context. + auto severity = sem_.DiagnosticSeverity( + call, wgsl::CoreDiagnosticRule::kDerivativeUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kSubgroup) { + callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity}; + } + function_tag = ReturnValueMayBeNonUniform; + } else if (builtin->IsAtomic()) { + callsite_tag = {CallSiteTag::CallSiteNoRestriction}; + function_tag = ReturnValueMayBeNonUniform; + } else if (builtin->Fn() == wgsl::BuiltinFn::kTextureLoad) { + // Loading from a read-write storage texture may produce a non-uniform value. + auto* storage = + builtin->Parameters()[0]->Type()->As(); + if (storage && storage->Access() == core::Access::kReadWrite) { + callsite_tag = {CallSiteTag::CallSiteNoRestriction}; + function_tag = ReturnValueMayBeNonUniform; + } + } else if (builtin->IsSubgroup()) { + // Get the severity of subgroup uniformity violations in this context. + auto severity = sem_.DiagnosticSeverity( + call, wgsl::CoreDiagnosticRule::kSubgroupUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kWorkgroup) { + callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity}; + } + function_tag = ReturnValueMayBeNonUniform; + if (scope_ == UniformityScope::kSubgroup) { + // The following builtins are uniform at subgroup scope. + switch (builtin->Fn()) { + case wgsl::BuiltinFn::kSubgroupAdd: + case wgsl::BuiltinFn::kSubgroupAll: + case wgsl::BuiltinFn::kSubgroupAnd: + case wgsl::BuiltinFn::kSubgroupAny: + case wgsl::BuiltinFn::kSubgroupBallot: + case wgsl::BuiltinFn::kSubgroupBroadcast: + case wgsl::BuiltinFn::kSubgroupBroadcastFirst: + case wgsl::BuiltinFn::kSubgroupMax: + case wgsl::BuiltinFn::kSubgroupMin: + case wgsl::BuiltinFn::kSubgroupMul: + case wgsl::BuiltinFn::kSubgroupOr: + case wgsl::BuiltinFn::kSubgroupXor: + function_tag = NoRestriction; + break; + default: + break; + } + } + } else if (builtin->IsSubgroupMatrix()) { + // Get the severity of subgroup matrix uniformity violations in this context. + auto severity = sem_.DiagnosticSeverity( + call, wgsl::ChromiumDiagnosticRule::kSubgroupMatrixUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kWorkgroup) { + callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity}; + } + } + }, + [&](const sem::Function* func) { + // We must have already analyzed the user-defined function since we process + // functions in dependency order. + auto info = functions_.Get(func->Declaration()); + TINT_ASSERT(info); + callsite_tag = info->callsite_tag; + function_tag = info->function_tag; + func_info = info.value; + }, + [&](const sem::ValueConstructor* construct) { + if (ContainsSubgroupMatrix(construct->ReturnType())) { + // Get the severity of subgroup matrix uniformity violations in this context. + auto severity = sem_.DiagnosticSeverity( + call, wgsl::ChromiumDiagnosticRule::kSubgroupMatrixUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kWorkgroup) { + callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity}; + } + } else { + callsite_tag = {CallSiteTag::CallSiteNoRestriction}; + function_tag = NoRestriction; + } + }, + [&](const sem::ValueConversion*) { + callsite_tag = {CallSiteTag::CallSiteNoRestriction}; + function_tag = NoRestriction; + }, // + TINT_ICE_ON_NO_MATCH); + + cf_after->AddEdge(call_node); + + if (function_tag == ReturnValueMayBeNonUniform) { + result->AddEdge(current_function_->may_be_non_uniform); + } + + result->AddEdge(cf_after); + + // For each argument, add edges based on parameter tags. + for (size_t i = 0; i < args.Length(); i++) { + if (func_info) { + auto& param_info = func_info->parameters[i]; + + // Capture the direct uniformity requirements. + switch (param_info.tag_direct.tag) { + case ParameterTag::ParameterValueRequiredToBeUniform: + current_function_->RequiredToBeUniform(param_info.tag_direct.severity) + ->AddEdge(args[i]); + break; + case ParameterTag::ParameterContentsRequiredToBeUniform: { + current_function_->RequiredToBeUniform(param_info.tag_direct.severity) + ->AddEdge(ptrarg_contents[i]); + break; + } + case ParameterTag::ParameterNoRestriction: + break; + } + // Capture the effects of this parameter on the return value. + switch (param_info.tag_retval.tag) { + case ParameterTag::ParameterValueRequiredToBeUniform: + result->AddEdge(args[i]); + break; + case ParameterTag::ParameterContentsRequiredToBeUniform: { + result->AddEdge(ptrarg_contents[i]); + break; + } + case ParameterTag::ParameterNoRestriction: + break; + } + + // Capture the effects of other call parameters on the contents of this parameter + // after the call returns. + auto* sem_arg = sem_.GetVal(call->args[i]); + if (sem_arg->Type()->Is()) { + auto* ptr_result = + CreateNode({name, "_ptrarg_", std::to_string(i), "_result"}, call); + ptr_result->type = Node::kFunctionCallPointerArgumentResult; + ptr_result->arg_index = static_cast(i); + if (param_info.pointer_may_become_non_uniform) { + ptr_result->AddEdge(current_function_->may_be_non_uniform); + } else { + // Add edge to the call to catch when it's called in non-uniform control + // flow. + ptr_result->AddEdge(call_node); + + // Add edges from the resulting pointer value to any other arguments that + // feed it. We distinguish between requirements on the source arguments + // value versus its contents for pointer arguments. + for (auto* source : param_info.ptr_output_source_param_values) { + ptr_result->AddEdge(args[source->Index()]); + } + for (auto* source : param_info.ptr_output_source_param_contents) { + ptr_result->AddEdge(ptrarg_contents[source->Index()]); + } + } + + // Update the current stored value for this pointer argument. + auto* root_ident = sem_arg->RootIdentifier(); + TINT_ASSERT(root_ident); + current_function_->variables.Set(root_ident, ptr_result); + } + } else { + auto* builtin = sem->Target()->As(); + auto* construct = sem->Target()->As(); + if (builtin && builtin->Fn() == wgsl::BuiltinFn::kWorkgroupUniformLoad && + scope_ != UniformityScope::kSubgroup) { + // The workgroupUniformLoad builtin requires its parameter to be uniform. + current_function_->RequiredToBeUniform(default_severity)->AddEdge(args[i]); + } else if (builtin && + (builtin->Fn() == wgsl::BuiltinFn::kSubgroupShuffleDown || + builtin->Fn() == wgsl::BuiltinFn::kSubgroupShuffleUp || + builtin->Fn() == wgsl::BuiltinFn::kSubgroupShuffleXor) && + i == 1) { + // The subgroupShuffle{Down,Up,Xor} builtins require their `delta` parameters to + // be uniform. + // Get the severity of subgroup uniformity violations in this context. + auto severity = sem_.DiagnosticSeverity( + call->args[i], wgsl::CoreDiagnosticRule::kSubgroupUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kWorkgroup) { + current_function_->RequiredToBeUniform(severity)->AddEdge(args[i]); + } + } else if (((builtin && builtin->IsSubgroupMatrix()) || + (construct && + construct->ReturnType()->Is()))) { + // For all subgroup matrix builtins and constructors, all arguments must be + // uniform. + auto severity = sem_.DiagnosticSeverity( + call->args[i], wgsl::ChromiumDiagnosticRule::kSubgroupMatrixUniformity); + if (severity != wgsl::DiagnosticSeverity::kOff && + scope_ != UniformityScope::kWorkgroup) { + current_function_->RequiredToBeUniform(severity)->AddEdge(args[i]); + } + } else { + // All other builtin function parameters are RequiredToBeUniformForReturnValue, + // as are parameters for value constructors and value conversions. + result->AddEdge(args[i]); + } + } + } + + // Add the callsite requirement last. + // We traverse edges in reverse order, so this makes the callsite requirement take highest + // priority when reporting violations. + if (callsite_tag.tag == CallSiteTag::CallSiteRequiredToBeUniform) { + current_function_->RequiredToBeUniform(callsite_tag.severity)->AddEdge(call_node); + } + + return {cf_after, result}; + } + + /// Traverse a graph starting at `source`, inserting all visited nodes into `reachable` and + /// recording which node they were reached from. + /// @param source the starting node + /// @param reachable the set of reachable nodes to populate, if required + void Traverse(Node* source, UniqueVector* reachable = nullptr) { + Vector to_visit{source}; + + while (!to_visit.IsEmpty()) { + auto* node = to_visit.Back(); + to_visit.Pop(); + + if (reachable) { + reachable->Add(node); + } + for (auto* to : node->edges) { + if (to->visited_from == nullptr) { + to->visited_from = node; + to_visit.Push(to); + } + } + } + } + + /// Trace back along a path from `start` until finding a node that matches a predicate. + /// @param start the starting node + /// @param pred the predicate function + /// @returns the first node found that matches the predicate, or nullptr + template + Node* TraceBackAlongPathUntil(Node* start, F&& pred) { + auto* current = start; + while (current) { + if (pred(current)) { + break; + } + current = current->visited_from; + } + return current; + } + + /// Recursively descend through the function called by `call` and the functions that it calls in + /// order to find a call to a builtin function that requires uniformity with the given severity. + const ast::CallExpression* FindBuiltinThatRequiresUniformity( + const ast::CallExpression* call, + wgsl::DiagnosticSeverity severity) { + auto* target = SemCall(call)->Target(); + if (target->IsAnyOf()) { + // This is a call to a builtin or constructor, so we must be done. + return call; + } else if (auto* user = target->As()) { + // This is a call to a user-defined function, so inspect the functions called by that + // function and look for one whose node has an edge from the RequiredToBeUniform node. + auto target_info = functions_.Get(user->Declaration()); + for (auto* call_node : target_info->RequiredToBeUniform(severity)->edges) { + if (call_node->type == Node::kRegular) { + auto* child_call = call_node->ast->As(); + return FindBuiltinThatRequiresUniformity(child_call, severity); + } + } + TINT_UNREACHABLE() << "unable to find child call with uniformity requirement"; + } else { + TINT_UNREACHABLE() << "unexpected call expression type"; + } + } + + /// Add diagnostic notes to show where control flow became non-uniform on the way to a node. + /// @param function the function being analyzed + /// @param required_to_be_uniform the node to traverse from + /// @param may_be_non_uniform the node to traverse to + void ShowControlFlowDivergence(FunctionInfo& function, + Node* required_to_be_uniform, + Node* may_be_non_uniform) { + // Traverse the graph to generate a path from the node to the source of non-uniformity. + function.ResetVisited(); + Traverse(required_to_be_uniform); + + // Get the source of the non-uniform value. + auto* non_uniform_source = may_be_non_uniform; + if (non_uniform_source == function.may_be_non_uniform) { + non_uniform_source = non_uniform_source->visited_from; + } + TINT_ASSERT(non_uniform_source); + + // Show where the non-uniform value results in non-uniform control flow. + auto* control_flow = TraceBackAlongPathUntil( + non_uniform_source, [](Node* node) { return node->affects_control_flow; }); + if (control_flow) { + diagnostics_.AddNote(control_flow->ast->source) + << "control flow depends on possibly non-uniform value"; + // TODO(jrprice): There are cases where the function with uniformity requirements is not + // actually inside this control flow construct, for example: + // - A conditional interrupt (e.g. break), with a barrier elsewhere in the loop + // - A conditional assignment to a variable, which is later used to guard a barrier + // In these cases, the diagnostics are not entirely accurate as they may not highlight + // the actual cause of divergence. + } + + ShowSourceOfNonUniformity(non_uniform_source); + } + + /// Add a diagnostic note to show the origin of a non-uniform value. + /// @param non_uniform_source the node that represents a non-uniform value + void ShowSourceOfNonUniformity(Node* non_uniform_source) { + TINT_ASSERT(non_uniform_source); + + auto var_type = [&](const sem::Variable* var) { + switch (var->AddressSpace()) { + case core::AddressSpace::kStorage: + return "read_write storage buffer "; + case core::AddressSpace::kWorkgroup: + return "workgroup storage variable "; + case core::AddressSpace::kPrivate: + return "module-scope private variable "; + default: + return ""; + } + }; + auto param_type = [&](const ast::Parameter* param) { + if (ast::HasAttribute(param->attributes)) { + return "builtin "; + } else if (ast::HasAttribute(param->attributes)) { + return "user-defined input "; + } else { + return "parameter "; + } + }; + + // Show the source of the non-uniform value. + Switch( + non_uniform_source->ast, + [&](const ast::IdentifierExpression* ident) { + auto* var = sem_.GetVal(ident)->UnwrapLoad()->As()->Variable(); + if (auto* param = var->As()) { + auto* func = param->Owner()->As(); + diagnostics_.AddNote(ident->source) + << param_type(param->Declaration()) << "'" << NameFor(ident) << "' of '" + << NameFor(func) << "' may be non-uniform"; + } else { + diagnostics_.AddNote(ident->source) + << "reading from " << var_type(var) << "'" << NameFor(ident) + << "' may result in a non-uniform value"; + } + }, + [&](const ast::Parameter* p) { + auto* param = sem_.Get(p); + auto* func = param->Owner()->As(); + if (non_uniform_source->type == Node::kFunctionPointerParameterContents) { + diagnostics_.AddNote(p->source) + << "parameter '" << NameFor(p) << "' of '" << NameFor(func) + << "' may point to a non-uniform value"; + } else { + diagnostics_.AddNote(p->source) + << param_type(p) << "'" << NameFor(p) << "' of '" << NameFor(func) + << "' may be non-uniform"; + } + }, + [&](const ast::Variable* v) { + auto* var = sem_.Get(v); + diagnostics_.AddNote(v->source) + << "reading from " << var_type(var) << "'" << NameFor(v) + << "' may result in a non-uniform value"; + }, + [&](const ast::CallExpression* c) { + auto target_name = NameFor(c->target); + switch (non_uniform_source->type) { + case Node::kFunctionCallReturnValue: { + diagnostics_.AddNote(c->source) + << "return value of '" + target_name + "' may be non-uniform"; + break; + } + case Node::kFunctionCallArgumentContents: { + auto* arg = c->args[non_uniform_source->arg_index]; + auto* var = sem_.GetVal(arg)->RootIdentifier(); + diagnostics_.AddNote(var->Declaration()->source) + << "reading from " << var_type(var) << "'" << NameFor(var) + << "' may result in a non-uniform value"; + break; + } + case Node::kFunctionCallArgumentValue: { + auto* arg = c->args[non_uniform_source->arg_index]; + // TODO(jrprice): Which output? (return value vs another pointer argument). + diagnostics_.AddNote(arg->source) + << "passing non-uniform pointer to '" << target_name + << "' may produce a non-uniform output"; + break; + } + case Node::kFunctionCallPointerArgumentResult: { + diagnostics_.AddNote(c->args[non_uniform_source->arg_index]->source) + << "contents of pointer may become non-uniform after calling '" + << target_name << "'"; + break; + } + default: { + TINT_ICE() << "unhandled source of non-uniformity"; + } + } + }, + [&](const ast::Expression* e) { + diagnostics_.AddNote(e->source) << "result of expression may be non-uniform"; + }, // + TINT_ICE_ON_NO_MATCH); + } + + /// Generate a diagnostic message for a uniformity issue. + /// @param function the function that the diagnostic is being produced for + /// @param source_node the node that has caused a uniformity issue in `function` + /// @param severity the severity of the diagnostic + void MakeError(FunctionInfo& function, Node* source_node, wgsl::DiagnosticSeverity severity) { + // Helper to produce a diagnostic message, as a note or with the global failure severity. + auto report = [&](Source source, std::string msg, bool note) { + diag::Diagnostic error{}; + error.severity = note ? diag::Severity::Note : wgsl::ToSeverity(severity); + error.source = source; + error.message = msg; + diagnostics_.Add(std::move(error)); + }; + + // Traverse the graph to generate a path from RequiredToBeUniform to the source node. + function.ResetVisited(); + Traverse(function.RequiredToBeUniform(severity)); + TINT_ASSERT(source_node->visited_from); + + // Find a node that is required to be uniform that has a path to the source node. + auto* cause = TraceBackAlongPathUntil(source_node, [&](Node* node) { + return node->visited_from == function.RequiredToBeUniform(severity); + }); + + // Special-case error for subgroup-matrix variable declarations, which are the only source + // of uniformity requirements that do not involve function calls. + if (cause->type == Node::kSubgroupMatrixVariableDeclaration) { + report(cause->ast->source, + "variables that contain subgroup matrix types cannot be declared in non-uniform " + "control flow", + /* note */ false); + + // Show the point at which control-flow depends on a non-uniform value. + ShowControlFlowDivergence(function, cause, source_node); + return; + } + + // The node will always have a corresponding call expression. + auto* call = cause->ast->As(); + TINT_ASSERT(call); + auto* target = SemCall(call)->Target(); + auto func_name = NameFor(call->target); + + if (cause->type == Node::kFunctionCallArgumentValue || + cause->type == Node::kFunctionCallArgumentContents) { + bool is_value = (cause->type == Node::kFunctionCallArgumentValue); + + Switch( + target, // + [&](const sem::Function* user_func) { + // Recurse into the called function to show the reason for the requirement. + auto next_function = functions_.Get(user_func->Declaration()); + auto& param_info = next_function->parameters[cause->arg_index]; + MakeError(*next_function, + is_value ? param_info.value : param_info.ptr_input_contents, + severity); + + // Show the place where the non-uniform argument was passed. + // If this is a builtin, this will be the trigger location for the failure. + StringStream ss; + ss << "possibly non-uniform value passed" << (is_value ? "" : " via pointer") + << " here"; + report(call->args[cause->arg_index]->source, ss.str(), /* note */ true); + }, + [&](const sem::BuiltinFn* builtin) { + StringStream ss; + ss << "'" << builtin->Fn() << "' requires argument " << cause->arg_index + << " to " << (is_value ? "be uniform" : "have uniform contents"); + report(call->args[cause->arg_index]->source, ss.str(), /* note */ false); + }, + [&](const sem::ValueConstructor* construct) { + StringStream ss; + ss << construct->ReturnType()->FriendlyName() + << " constructor requires argument " << cause->arg_index << " to " + << (is_value ? "be uniform" : "have uniform contents"); + report(call->args[cause->arg_index]->source, ss.str(), /* note */ false); + }, + TINT_ICE_ON_NO_MATCH); + + // Show the origin of non-uniformity for the value or data that is being passed. + ShowSourceOfNonUniformity(source_node->visited_from); + } else { + auto* builtin_call = FindBuiltinThatRequiresUniformity(call, severity); + { + // Show a builtin was reachable from this call (which may be the call itself). + // This will be the trigger location for the failure. + StringStream ss; + ss << "'" << NameFor(builtin_call->target) << "' must only be called from " + << (scope_ == UniformityScope::kSubgroup ? "subgroup " : "") + << "uniform control flow"; + report(builtin_call->source, ss.str(), /* note */ false); + } + + if (builtin_call != call) { + // The call was to a user function, so show that call too. + StringStream ss; + ss << "called "; + if (target->As() != SemCall(builtin_call)->Stmt()->Function()) { + ss << "indirectly "; + } + ss << "by '" << func_name << "' from '" << function.name << "'"; + report(call->source, ss.str(), /* note */ true); + } + + // Show the point at which control-flow depends on a non-uniform value. + ShowControlFlowDivergence(function, cause, source_node); + } + } + + // Helper for obtaining the sem::Call node for the ast::CallExpression + const sem::Call* SemCall(const ast::CallExpression* expr) const { + return sem_.Get(expr)->UnwrapMaterialize()->As(); + } + + /// @returns true if @p type is or contains a subgroup matrix type + bool ContainsSubgroupMatrix(const core::type::Type* type) { + if (type->Is()) { + return true; + } + return composite_subgroup_matrix_info_.GetOrAdd(type, [&] { + return Switch( + type, // + [&](const core::type::Array* arr) { + return ContainsSubgroupMatrix(arr->ElemType()); + }, + [&](const core::type::Struct* str) { + for (auto* member : str->Members()) { + if (ContainsSubgroupMatrix(member->Type())) { + return true; + } + } + return false; + }); + }); + } +}; + +} // namespace + +bool AnalyzeUniformity(ProgramBuilder& builder, + const DependencyGraph& dependency_graph, + bool subgroup_uniformity) { + if (subgroup_uniformity) { + UniformityGraph workgroupGraph(builder, UniformityScope::kWorkgroup); + if (!workgroupGraph.Build(dependency_graph)) { + return false; + } + UniformityGraph subgroupGraph(builder, UniformityScope::kSubgroup); + return subgroupGraph.Build(dependency_graph); + } else { + UniformityGraph graph(builder, UniformityScope::kAll); + return graph.Build(dependency_graph); + } +} + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.h new file mode 100644 index 000000000..35e29c528 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/uniformity.h @@ -0,0 +1,55 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_UNIFORMITY_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_UNIFORMITY_H_ + +// Forward declarations. +namespace tint::resolver { +struct DependencyGraph; +} // namespace tint::resolver +namespace tint { +class ProgramBuilder; +} // namespace tint + +namespace tint::resolver { + +/// If true, uniformity analysis failures will be treated as an error, else as a warning. +constexpr bool kUniformityFailuresAsError = true; + +/// Analyze the uniformity of a program. +/// @param builder the program to analyze +/// @param dependency_graph the dependency-ordered module-scope declarations +/// @param subgroup_uniformity Whether subgroup_uniformity feature is supported +/// @returns true if there are no uniformity issues, false otherwise +bool AnalyzeUniformity(ProgramBuilder& builder, + const resolver::DependencyGraph& dependency_graph, + bool subgroup_uniformity = false); + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_UNIFORMITY_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.cc new file mode 100644 index 000000000..14fa7f2c0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.cc @@ -0,0 +1,40 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/unresolved_identifier.h" + +TINT_INSTANTIATE_TYPEINFO(tint::resolver::UnresolvedIdentifier); + +namespace tint::resolver { + +UnresolvedIdentifier::UnresolvedIdentifier(const ast::IdentifierExpression* i, + const sem::Statement* stmt) + : Base(i, stmt) {} + +UnresolvedIdentifier::~UnresolvedIdentifier() = default; + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.h new file mode 100644 index 000000000..a5732bd8c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/unresolved_identifier.h @@ -0,0 +1,55 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_UNRESOLVED_IDENTIFIER_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_UNRESOLVED_IDENTIFIER_H_ + +#include "src/tint/lang/wgsl/ast/identifier_expression.h" +#include "src/tint/lang/wgsl/sem/expression.h" + +namespace tint::resolver { + +/// Represents an identifier that could not be resolved. +class UnresolvedIdentifier : public Castable { + public: + /// Constructor + /// @param i the identifier that could not be resolved + /// @param statement the statement that owns this expression + UnresolvedIdentifier(const ast::IdentifierExpression* i, const sem::Statement* statement); + + /// Destructor + ~UnresolvedIdentifier() override; + + /// @returns the identifier that could not be resolved + const ast::IdentifierExpression* Identifier() const { + return static_cast(declaration_); + } +}; + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_UNRESOLVED_IDENTIFIER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.cc b/3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.cc new file mode 100644 index 000000000..59bdf9e9b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.cc @@ -0,0 +1,3513 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/resolver/validator.h" + +#include +#include +#include +#include +#include + +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/type/abstract_numeric.h" +#include "src/tint/lang/core/type/atomic.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/i8.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampled_texture.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/subgroup_matrix.h" +#include "src/tint/lang/core/type/texture_dimension.h" +#include "src/tint/lang/core/type/u8.h" +#include "src/tint/lang/wgsl/ast/alias.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/blend_src_attribute.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/traverse_expressions.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/sem/array.h" +#include "src/tint/lang/wgsl/sem/break_if_statement.h" +#include "src/tint/lang/wgsl/sem/builtin_fn.h" +#include "src/tint/lang/wgsl/sem/call.h" +#include "src/tint/lang/wgsl/sem/for_loop_statement.h" +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/if_statement.h" +#include "src/tint/lang/wgsl/sem/loop_statement.h" +#include "src/tint/lang/wgsl/sem/member_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/statement.h" +#include "src/tint/lang/wgsl/sem/struct.h" +#include "src/tint/lang/wgsl/sem/switch_statement.h" +#include "src/tint/lang/wgsl/sem/value_constructor.h" +#include "src/tint/lang/wgsl/sem/value_conversion.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/lang/wgsl/sem/while_statement.h" +#include "src/tint/utils/internal_limits.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/text_style.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::resolver { +namespace { + +constexpr size_t kMaxFunctionParameters = 255; +constexpr size_t kMaxSwitchCaseSelectors = 16383; +constexpr size_t kMaxClipDistancesSize = 8; + +bool IsValidStorageTextureDimension(core::type::TextureDimension dim) { + switch (dim) { + case core::type::TextureDimension::k1d: + case core::type::TextureDimension::k2d: + case core::type::TextureDimension::k2dArray: + case core::type::TextureDimension::k3d: + return true; + default: + return false; + } +} + +bool IsValidStorageTextureTexelFormat(core::TexelFormat format) { + switch (format) { + case core::TexelFormat::kR8Unorm: + case core::TexelFormat::kR8Snorm: + case core::TexelFormat::kR8Uint: + case core::TexelFormat::kR8Sint: + case core::TexelFormat::kRg8Unorm: + case core::TexelFormat::kRg8Snorm: + case core::TexelFormat::kRg8Uint: + case core::TexelFormat::kRg8Sint: + case core::TexelFormat::kR16Unorm: + case core::TexelFormat::kR16Snorm: + case core::TexelFormat::kR16Uint: + case core::TexelFormat::kR16Sint: + case core::TexelFormat::kR16Float: + case core::TexelFormat::kRg16Unorm: + case core::TexelFormat::kRg16Snorm: + case core::TexelFormat::kRg16Uint: + case core::TexelFormat::kRg16Sint: + case core::TexelFormat::kRg16Float: + case core::TexelFormat::kBgra8Unorm: + case core::TexelFormat::kR32Float: + case core::TexelFormat::kR32Sint: + case core::TexelFormat::kR32Uint: + case core::TexelFormat::kRg32Float: + case core::TexelFormat::kRg32Sint: + case core::TexelFormat::kRg32Uint: + case core::TexelFormat::kRgba16Unorm: + case core::TexelFormat::kRgba16Snorm: + case core::TexelFormat::kRgba16Float: + case core::TexelFormat::kRgba16Sint: + case core::TexelFormat::kRgba16Uint: + case core::TexelFormat::kRgba32Float: + case core::TexelFormat::kRgba32Sint: + case core::TexelFormat::kRgba32Uint: + case core::TexelFormat::kRgba8Sint: + case core::TexelFormat::kRgba8Snorm: + case core::TexelFormat::kRgba8Uint: + case core::TexelFormat::kRgba8Unorm: + case core::TexelFormat::kRgb10A2Uint: + case core::TexelFormat::kRgb10A2Unorm: + case core::TexelFormat::kRg11B10Ufloat: + return true; + default: + return false; + } +} + +template +void TraverseCallChain(const sem::Function* from, const sem::Function* to, CALLBACK&& callback) { + for (auto* f : from->TransitivelyCalledFunctions()) { + if (f == to) { + callback(f); + return; + } + if (f->TransitivelyCalledFunctions().Contains(to)) { + TraverseCallChain(f, to, callback); + callback(f); + return; + } + } + TINT_ICE() << "TraverseCallChain() 'from' does not transitively call 'to'"; +} + +} // namespace + +Validator::Validator( + ProgramBuilder* builder, + SemHelper& sem, + const wgsl::Extensions& enabled_extensions, + const wgsl::AllowedFeatures& allowed_features, + const Hashmap& atomic_composite_info, + Hashset& valid_type_storage_layouts) + : symbols_(builder->Symbols()), + diagnostics_(builder->Diagnostics()), + sem_(sem), + enabled_extensions_(enabled_extensions), + allowed_features_(allowed_features), + atomic_composite_info_(atomic_composite_info), + valid_type_storage_layouts_(valid_type_storage_layouts) { + // Set default severities for filterable diagnostic rules. + diagnostic_filters_.Set(wgsl::CoreDiagnosticRule::kDerivativeUniformity, + wgsl::DiagnosticSeverity::kError); + diagnostic_filters_.Set(wgsl::CoreDiagnosticRule::kSubgroupUniformity, + wgsl::DiagnosticSeverity::kError); + diagnostic_filters_.Set(wgsl::ChromiumDiagnosticRule::kSubgroupMatrixUniformity, + wgsl::DiagnosticSeverity::kError); + diagnostic_filters_.Set(wgsl::ChromiumDiagnosticRule::kUnreachableCode, + wgsl::DiagnosticSeverity::kWarning); +} + +Validator::~Validator() = default; + +diag::Diagnostic& Validator::AddError(const Source& source) const { + return diagnostics_.AddError(source); +} + +diag::Diagnostic& Validator::AddWarning(const Source& source) const { + return diagnostics_.AddWarning(source); +} + +diag::Diagnostic& Validator::AddNote(const Source& source) const { + return diagnostics_.AddNote(source); +} + +diag::Diagnostic* Validator::MaybeAddDiagnostic(wgsl::DiagnosticRule rule, + const Source& source) const { + auto severity = diagnostic_filters_.Get(rule); + if (severity != wgsl::DiagnosticSeverity::kOff) { + diag::Diagnostic d{}; + d.severity = ToSeverity(severity); + d.source = source; + return &diagnostics_.Add(std::move(d)); + } + return nullptr; +} + +// https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section +bool Validator::IsPlain(const core::type::Type* type) const { + return type->IsAnyOf() && + !type->IsAnyOf(); +} + +// https://gpuweb.github.io/gpuweb/wgsl.html#storable-types +bool Validator::IsStorable(const core::type::Type* type) const { + return IsPlain(type) || type->IsAnyOf(); +} + +const ast::Statement* Validator::ClosestContinuing(bool stop_at_loop, + bool stop_at_switch, + sem::Statement* current_statement) const { + for (const auto* s = current_statement; s != nullptr; s = s->Parent()) { + if (stop_at_loop && s->Is()) { + break; + } + if (stop_at_switch && s->Is()) { + break; + } + if (s->Is()) { + return s->Declaration(); + } + if (auto* f = As(s->Parent())) { + if (f->Declaration()->continuing == s->Declaration()) { + return s->Declaration(); + } + if (stop_at_loop) { + break; + } + } + if (Is(s->Parent())) { + if (stop_at_loop) { + break; + } + } + } + return nullptr; +} + +bool Validator::Enables(VectorRef enables) const { + auto source_of = [&](wgsl::Extension ext) { + for (auto* enable : enables) { + for (auto* extension : enable->extensions) { + if (extension->name == ext) { + return extension->source; + } + } + } + return Source{}; + }; + + // List of extensions that cannot be used together. + std::pair incompatible[] = { + { + wgsl::Extension::kChromiumExperimentalPixelLocal, + wgsl::Extension::kChromiumExperimentalFramebufferFetch, + }, + }; + + for (auto pair : incompatible) { + if (enabled_extensions_.Contains(pair.first) && enabled_extensions_.Contains(pair.second)) { + AddError(source_of(pair.first)) + << "extension " << style::Code(pair.first) << " cannot be used with extension " + << style::Code(pair.second); + AddNote(source_of(pair.second)) << style::Code(pair.second) << " enabled here"; + return false; + } + } + + if (enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalSubgroupSizeControl) && + !enabled_extensions_.Contains(wgsl::Extension::kSubgroups)) { + AddError(source_of(wgsl::Extension::kChromiumExperimentalSubgroupSizeControl)) + << "extension " + << style::Code(wgsl::Extension::kChromiumExperimentalSubgroupSizeControl) + << " cannot be used without extension " << style::Code(wgsl::Extension::kSubgroups); + return false; + } + + return true; +} + +bool Validator::Atomic(const ast::TemplatedIdentifier* a, const core::type::Atomic* s) const { + // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types + // T must be either u32 or i32. + if (!s->Type()->IsAnyOf()) { + AddError(a->arguments[0]->source) + << style::Type("atomic") << " only supports " << style::Type("i32") << " or " + << style::Type("u32") << " types"; + return false; + } + return true; +} + +bool Validator::Pointer(const ast::TemplatedIdentifier* a, const core::type::Pointer* s) const { + if (s->AddressSpace() == core::AddressSpace::kUndefined) { + AddError(a->source) << "ptr missing address space"; + return false; + } + + if (s->AddressSpace() != core::AddressSpace::kHandle) { + if (s->StoreType()->IsHandle()) { + AddError(a->source) << "pointer can not be formed to handle type " + << sem_.TypeNameOf(s->StoreType()); + return false; + } + } + + if (a->arguments.Length() > 2) { // ptr + // https://www.w3.org/TR/WGSL/#access-mode-defaults + // When writing a variable declaration or a pointer type in WGSL source: + // * For the storage address space, the access mode is optional, and defaults to read. + // * For other address spaces, the access mode must not be written. + if (s->AddressSpace() != core::AddressSpace::kStorage) { + AddError(a->source) + << "only pointers in address space may specify an access mode"; + return false; + } + } + + if (auto* store_ty = s->StoreType(); !IsStorable(store_ty)) { + AddError(a->arguments[1]->source) + << sem_.TypeNameOf(store_ty) + " cannot be used as the store type of a pointer"; + return false; + } + + return CheckTypeAccessAddressSpace(s->StoreType(), s->Access(), s->AddressSpace(), a->source); +} + +bool Validator::StorageTexture(const core::type::StorageTexture* t, const Source& source) const { + switch (t->Access()) { + case core::Access::kRead: + if (allowed_features_.features.count( + wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures) == 0u) { + AddError(source) << "read-only storage textures require the " + "readonly_and_readwrite_storage_textures language feature, " + "which is not allowed in the current environment"; + return false; + } + break; + case core::Access::kReadWrite: + if (allowed_features_.features.count( + wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures) == 0u) { + AddError(source) << "read-write storage textures require the " + "readonly_and_readwrite_storage_textures language feature, " + "which is not allowed in the current environment"; + return false; + } + break; + case core::Access::kWrite: + break; + case core::Access::kUndefined: + AddError(source) << "storage texture missing access control"; + return false; + } + + if (!IsValidStorageTextureDimension(t->Dim())) { + AddError(source) << "cube dimensions for storage textures are not supported"; + return false; + } + + if (!IsValidStorageTextureTexelFormat(t->TexelFormat())) { + AddError(source) << "image format must be one of the texel formats specified for storage " + "textures in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats"; + return false; + } + + return true; +} + +bool Validator::SampledTexture(const core::type::SampledTexture* t, const Source& source) const { + if (!t->Type()->UnwrapRef()->IsAnyOf()) { + AddError(source) << "texture_2d: type must be f32, i32 or u32"; + return false; + } + + return true; +} + +bool Validator::MultisampledTexture(const core::type::MultisampledTexture* t, + const Source& source) const { + if (t->Dim() != core::type::TextureDimension::k2d) { + AddError(source) << "only 2d multisampled textures are supported"; + return false; + } + + if (!t->Type()->UnwrapRef()->IsAnyOf()) { + AddError(source) << "texture_multisampled_2d: type must be f32, i32 or u32"; + return false; + } + + return true; +} + +bool Validator::InputAttachment(const core::type::InputAttachment* t, const Source& source) const { + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumInternalInputAttachments)) { + AddError(source) << "use of " << style::Type("input_attachment") + << " requires enabling extension " + << style::Code("chromium_internal_input_attachments"); + return false; + } + if (!t->Type()->UnwrapRef()->IsAnyOf()) { + AddError(source) << "input_attachment: type must be f32, i32 or u32"; + return false; + } + + return true; +} + +bool Validator::InputAttachmentIndexAttribute(const ast::InputAttachmentIndexAttribute* attr, + const core::type::Type* type, + const Source& source) const { + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumInternalInputAttachments)) { + AddError(source) << "use of " << style::Attribute("@input_attachment_index") + << " requires enabling extension " + << style::Code("chromium_internal_input_attachments"); + return false; + } + + if (!type->Is()) { + std::string invalid_type = sem_.TypeNameOf(type); + AddError(source) << "cannot apply " << style::Attribute("@input_attachment_index") + << " to declaration of type " << style::Type(invalid_type); + AddNote(attr->source) << style::Attribute("@input_attachment_index") + << " must only be applied to declarations of " + << style::Type("input_attachment") << " type"; + return false; + } + + return true; +} + +bool Validator::BindingArray(const core::type::BindingArray* t, const Source& source) const { + if (allowed_features_.features.count(wgsl::LanguageFeature::kSizedBindingArray) == 0) { + AddError(source) << "use of " << style::Type("binding_array") << " requires the " + << style::Code("sized_binding_array") + << "language feature, which is not allowed in the current environment"; + return false; + } + + if (!t->Count()->Is()) { + AddError(source) << "binding_array count must be a constant expression"; + return false; + } + + if (!t->ElemType()->Is()) { + AddError(source) << "binding_array element type must be a sampled texture type"; + return false; + } + + return true; +} + +bool Validator::SubgroupMatrix(const core::type::SubgroupMatrix* t, const Source& source) const { + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalSubgroupMatrix)) { + AddError(source) << "use of " << style::Type("subgroup_matrix_*") + << " requires enabling extension " + << style::Code("chromium_experimental_subgroup_matrix"); + return false; + } + if (!t->Type() + ->IsAnyOf()) { + AddError(source) << "subgroup_matrix element type must be f32, f16, i32, u32, i8 or u8"; + return false; + } + + return true; +} + +bool Validator::Buffer(const core::type::Buffer*, const Source& source) const { + if (!allowed_features_.features.count(wgsl::LanguageFeature::kBufferView)) { + AddError(source) << "use of " << style::Type("buffer") + << " requires the buffer_view language feature, which is not allowed in " + "the current environment"; + return false; + } + + return true; +} + +bool Validator::TexelBuffer(const core::type::TexelBuffer* t, const Source& source) const { + if (!allowed_features_.features.count(wgsl::LanguageFeature::kTexelBuffers)) { + AddError(source) << "use of " << style::Type("texel_buffer") + << " requires the texel_buffer language feature, which is not allowed " + "in the current environment"; + return false; + } + + if (!IsValidStorageTextureTexelFormat(t->TexelFormat())) { + AddError(source) << "texel_buffer format must be one of the texel formats specified for " + "texel buffers in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats"; + return false; + } + + if (!t->Type()->IsAnyOf()) { + AddError(source) << "texel_buffer: storage subtype must be f32, i32 or u32"; + return false; + } + + if (t->Dim() != core::type::TextureDimension::k1d) { + AddError(source) << "texel_buffer must be a 1d texture"; + return false; + } + + if (t->Access() != core::Access::kRead && t->Access() != core::Access::kReadWrite) { + AddError(source) << "texel_buffer access must be read or read_write"; + return false; + } + + return true; +} + +bool Validator::Materialize(const core::type::Type* to, + const core::type::Type* from, + const Source& source) const { + if (core::type::Type::ConversionRank(from, to) == core::type::Type::kNoConversion) { + AddError(source) << "cannot convert value of type " << style::Type(sem_.TypeNameOf(from)) + << " to type " << style::Type(sem_.TypeNameOf(to)); + return false; + } + return true; +} + +bool Validator::VariableInitializer(const ast::Variable* v, + const core::type::Type* storage_ty, + const sem::ValueExpression* initializer) const { + auto* initializer_ty = initializer->Type(); + auto* value_type = initializer_ty->UnwrapRef(); // Implicit load of RHS + + // Value type has to match storage type + if (storage_ty != value_type) { + AddError(v->source) << "cannot initialize " << style::Keyword(v->Kind()) << " of type " + << style::Type(sem_.TypeNameOf(storage_ty)) << " with value of type " + << style::Type(sem_.TypeNameOf(initializer_ty)); + return false; + } + + return true; +} + +bool Validator::AddressSpaceLayout(const core::type::Type* store_ty, + core::AddressSpace address_space, + Source source) const { + // https://gpuweb.github.io/gpuweb/wgsl/#storage-class-layout-constraints + + auto is_uniform_struct_or_array = [address_space](const core::type::Type* ty) { + return address_space == core::AddressSpace::kUniform && + ty->IsAnyOf(); + }; + + auto is_uniform_struct = [address_space](const core::type::Type* ty) { + return address_space == core::AddressSpace::kUniform && ty->Is(); + }; + + auto required_alignment_of = [&](const core::type::Type* ty) { + uint32_t actual_align = ty->Align(); + uint32_t required_align = actual_align; + if (is_uniform_struct_or_array(ty) && + !allowed_features_.features.contains( + wgsl::LanguageFeature::kUniformBufferStandardLayout)) { + required_align = tint::RoundUp(16u, actual_align); + } + return required_align; + }; + + auto member_name_of = [](const core::type::StructMember* sm) { return sm->Name().Name(); }; + + // Only validate the [type + address space] once + if (!valid_type_storage_layouts_.Add(TypeAndAddressSpace{store_ty, address_space})) { + return true; + } + + auto note_usage = [&] { + AddNote(source) << style::Type(store_ty->FriendlyName()) << " used in address space " + << style::Enum(address_space) << " here"; + }; + + // Among three host-shareable address spaces, f16 is supported in "uniform" and + // "storage" address space, but not "immediate" address space yet. + if (Is(store_ty->DeepestElement()) && + address_space == core::AddressSpace::kImmediate) { + AddError(source) << "using " << style::Type("f16") << " in " << style::Enum("immediate") + << " address space is not implemented yet"; + return false; + } + + if (auto* str = store_ty->As()) { + auto& str_source = str->Declaration()->name->source; + for (size_t i = 0; i < str->Members().Length(); ++i) { + auto* const m = str->Members()[i]; + uint32_t required_align = required_alignment_of(m->Type()); + + // Recurse into the member type. + if (!AddressSpaceLayout(m->Type(), address_space, m->Declaration()->type->source)) { + AddNote(str_source) << "see layout of struct:\n" << str->Layout(); + note_usage(); + return false; + } + + // Validate that member is at a valid byte offset + if (m->Offset() % required_align != 0) { + AddError(m->Declaration()->source) + << "the offset of a struct member of type " + << style::Type(m->Type()->UnwrapRef()->FriendlyName()) << " in address space " + << style::Enum(address_space) << " must be a multiple of " << required_align + << " bytes, but " << style::Variable(member_name_of(m)) + << " is currently at offset " << m->Offset() << ". Consider setting " + << style::Attribute("@align") << style::Code("(", required_align, ")") + << " on this member"; + + AddNote(str_source) << "see layout of struct:\n" << str->Layout(); + + if (auto* member_str = m->Type()->As()) { + AddNote(member_str->Declaration()->name->source) + << "and layout of struct member:\n" + << member_str->Layout(); + } + + note_usage(); + return false; + } + + // For uniform buffers, validate that the number of bytes between the previous member of + // type struct and the current is a multiple of 16 bytes. + auto* const prev_member = (i == 0) ? nullptr : str->Members()[i - 1]; + if (prev_member && is_uniform_struct(prev_member->Type()) && + !allowed_features_.features.contains( + wgsl::LanguageFeature::kUniformBufferStandardLayout)) { + const uint32_t prev_to_curr_offset = m->Offset() - prev_member->Offset(); + if (prev_to_curr_offset % 16 != 0) { + AddError(m->Declaration()->source) + << style::Enum("uniform") + << " storage requires that the number of bytes between the start of the " + "previous member of type struct and the current member be a " + "multiple of 16 bytes, but there are currently " + << prev_to_curr_offset << " bytes between " + << style::Variable(member_name_of(prev_member)) << " and " + << style::Variable(member_name_of(m)) << ". Consider setting " + << style::Attribute("@align") << style::Code("(16)") << " on this member"; + + AddNote(str_source) << "see layout of struct:\n" << str->Layout(); + + auto* prev_member_str = prev_member->Type()->As(); + AddNote(prev_member_str->Declaration()->name->source) + << "and layout of previous member struct:\n" + << prev_member_str->Layout(); + note_usage(); + return false; + } + } + + // If an alignment was explicitly specified, we need to validate that it satisfies the + // alignment requirement of the address space. + auto* align_attr = + ast::GetAttribute(m->Declaration()->attributes); + if (align_attr != nullptr) { + auto align = sem_.GetVal(align_attr->expr)->ConstantValue()->ValueAs(); + if (align % required_align != 0) { + AddError(align_attr->expr->source) + << "alignment must be a multiple of " << style::Literal(required_align) + << " bytes for the " << style::Enum(address_space) << " address space"; + note_usage(); + return false; + } + } + } + } + + // For uniform buffer array members, validate that array elements are aligned to 16 bytes + if (auto* arr = store_ty->As()) { + // Recurse into the element type. + // TODO(crbug.com/tint/1388): Ideally we'd pass the source for nested element type here, but + // we can't easily get that from the semantic node. We should consider recursing through the + // AST type nodes instead. + if (!AddressSpaceLayout(arr->ElemType(), address_space, source)) { + return false; + } + + if (address_space == core::AddressSpace::kUniform && + !allowed_features_.features.contains( + wgsl::LanguageFeature::kUniformBufferStandardLayout)) { + // We already validated that this array member is itself aligned to 16 bytes above, so + // we only need to validate that stride is a multiple of 16 bytes. + if (arr->ImplicitStride() % 16 != 0) { + // Since WGSL has no stride attribute, try to provide a useful hint for how the + // shader author can resolve the issue. + StyledText hint; + if (arr->ElemType()->Is()) { + hint << "Consider using a vector or struct as the element type instead."; + } else if (auto* vec = arr->ElemType()->As(); + vec && vec->Type()->Size() == 4) { + hint << "Consider using a vec4 instead."; + } else if (arr->ElemType()->Is()) { + hint << "Consider using the " << style::Attribute("@size") + << " attribute on the last struct member."; + } else { + hint << "Consider wrapping the element type in a struct and using the " + << style::Attribute("@size") << " attribute."; + } + AddError(source) << style::Enum("uniform") + << " storage requires that array elements are aligned to 16 " + "bytes, but array element of type " + << style::Type(arr->ElemType()->FriendlyName()) + << " has a stride of " << arr->ImplicitStride() << " bytes. " + << hint; + return false; + } + } + } + + return true; +} + +bool Validator::LocalVariable(const sem::Variable* local) const { + auto* decl = local->Declaration(); + return Switch( + decl, // + [&](const ast::Var* var) { + if (!local->Type()->UnwrapRef()->IsConstructible()) { + AddError(var->type ? var->type->source : var->source) + << "function-scope " << style::Keyword("var") + << " must have a constructible type"; + return false; + } + return Var(local); + }, // + [&](const ast::Let*) { return Let(local); }, // + [&](const ast::Const*) { return true; }, // + TINT_ICE_ON_NO_MATCH); +} + +bool Validator::GlobalVariable( + const sem::GlobalVariable* global, + const Hashmap& override_ids) const { + auto* decl = global->Declaration(); + bool ok = Switch( + decl, // + [&](const ast::Var* var) { + if (auto* init = global->Initializer(); + init && init->Stage() > core::EvaluationStage::kOverride) { + AddError(init->Declaration()->source) + << "module-scope " << style::Keyword("var") + << " initializer must be a constant or override-expression"; + return false; + } + + if (!var->declared_address_space && !global->Type()->UnwrapRef()->IsHandle()) { + AddError(decl->source) << "module-scope " << style::Keyword("var") + << " declarations that are not of texture or sampler types " + "must provide an address space"; + return false; + } + + return Var(global); + }, + [&](const ast::Override*) { return Override(global, override_ids); }, + [&](const ast::Const*) { return Const(global); }, // + TINT_ICE_ON_NO_MATCH); + + if (!ok) { + return false; + } + + if (global->AddressSpace() == core::AddressSpace::kFunction) { + AddError(decl->source) << "module-scope " << style::Keyword("var") + << " must not use address space " << style::Enum("function"); + return false; + } + + auto* input_attachment_index_attr = + ast::GetAttribute(decl->attributes); + if (input_attachment_index_attr && + !InputAttachmentIndexAttribute(input_attachment_index_attr, global->Type()->UnwrapRef(), + decl->source)) { + return false; + } + switch (global->AddressSpace()) { + case core::AddressSpace::kUniform: + case core::AddressSpace::kStorage: + case core::AddressSpace::kHandle: { + // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface + // Each resource variable must be declared with both group and binding attributes. + if (!decl->HasBindingPoint()) { + AddError(decl->source) + << "resource variables require " << style::Attribute("@group") << " and " + << style::Attribute("@binding") << " attributes"; + return false; + } + if (global->Type()->UnwrapRef()->Is() && + !input_attachment_index_attr) { + AddError(decl->source) + << style::Type("input_attachment") << " variables require " + << style::Attribute("@input_attachment_index") << " attribute"; + return false; + } + break; + } + default: { + auto* binding_attr = ast::GetAttribute(decl->attributes); + auto* group_attr = ast::GetAttribute(decl->attributes); + if (binding_attr || group_attr) { + // https://gpuweb.github.io/gpuweb/wgsl/#attribute-binding + // Must only be applied to a resource variable + AddError(decl->source) + << "non-resource variables must not have " << style::Attribute("@group") + << " or " << style::Attribute("@binding") << " attributes"; + return false; + } + } + } + + return true; +} + +bool Validator::Var(const sem::Variable* v) const { + auto* var = v->Declaration()->As(); + auto* store_ty = v->Type()->UnwrapRef(); + + if (!IsStorable(store_ty)) { + AddError(var->source) << sem_.TypeNameOf(store_ty) + << " cannot be used as the type of a var"; + return false; + } + + if (store_ty->IsHandle() && var->declared_address_space) { + // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables + // If the store type is a texture type or a sampler type, then the variable declaration must + // not have a address space attribute. The address space will always be handle. + AddError(var->source) << "variables of type " << style::Type(sem_.TypeNameOf(store_ty)) + << " must not specify an address space"; + return false; + } + + if (var->declared_access) { + // https://www.w3.org/TR/WGSL/#access-mode-defaults + // When writing a variable declaration or a pointer type in WGSL source: + // * For the storage address space, the access mode is optional, and defaults to read. + // * For other address spaces, the access mode must not be written. + if (v->AddressSpace() != core::AddressSpace::kStorage) { + AddError(var->source) + << "only variables in address space may specify an access mode"; + return false; + } + } + + if (auto* buffer = store_ty->As()) { + if (buffer->Count()->Is() && + (v->AddressSpace() == core::AddressSpace::kUniform || + v->AddressSpace() == core::AddressSpace::kWorkgroup)) { + AddError(var->source) << "buffer type must be sized in " + << style::Enum(v->AddressSpace()) << " address space"; + return false; + } + if (!(buffer->Count()->Is() || + buffer->Count()->Is()) && + v->AddressSpace() != core::AddressSpace::kWorkgroup) { + AddError(var->source) << "buffer type must not be sized with an override-expression in " + << style::Enum(v->AddressSpace()) << " address space"; + return false; + } + } + + if (var->initializer) { + switch (v->AddressSpace()) { + case core::AddressSpace::kPrivate: + case core::AddressSpace::kFunction: + break; // Allowed an initializer + default: + // https://gpuweb.github.io/gpuweb/wgsl/#var-and-let + // Optionally has an initializer expression, if the variable is in the private or + // function address spaces. + AddError(var->source) + << "var of address space " << style::Enum(v->AddressSpace()) + << " cannot have an initializer. var initializers are only supported for the " + "address spaces " + << style::Enum("private") << " and " << style::Enum("function"); + return false; + } + } + + if (!CheckTypeAccessAddressSpace(v->Type()->UnwrapRef(), v->Access(), v->AddressSpace(), + var->source)) { + return false; + } + + if ((v->AddressSpace() == core::AddressSpace::kIn || + v->AddressSpace() == core::AddressSpace::kOut)) { + AddError(var->source) << "invalid use of input/output address space"; + return false; + } + return true; +} + +bool Validator::Let(const sem::Variable* v) const { + auto* decl = v->Declaration(); + auto* storage_ty = v->Type()->UnwrapRef(); + + bool assignment_allowed = + storage_ty->IsConstructible() || storage_ty->Is(); + + if (allowed_features_.features.contains(wgsl::LanguageFeature::kTextureAndSamplerLet) && + storage_ty->IsAnyOf()) { + assignment_allowed = true; + } + + if (!assignment_allowed) { + AddError(decl->source) << sem_.TypeNameOf(storage_ty) << " cannot be used as the type of a " + << style::Keyword("let"); + return false; + } + return true; +} + +bool Validator::Override(const sem::GlobalVariable* v, + const Hashmap& override_ids) const { + auto* decl = v->Declaration(); + auto* storage_ty = v->Type()->UnwrapRef(); + + if (auto* init = v->Initializer(); init && init->Stage() > core::EvaluationStage::kOverride) { + AddError(init->Declaration()->source) + << style::Keyword("override") << " initializer must be an override-expression"; + return false; + } + + if (auto id = v->Attributes().override_id) { + if (auto var = override_ids.Get(*id); var && *var != v) { + auto* attr = ast::GetAttribute(v->Declaration()->attributes); + AddError(attr->source) << style::Attribute("@id") << " values must be unique"; + AddNote(ast::GetAttribute((*var)->Declaration()->attributes)->source) + << "a override with an ID of " << id->value << " was previously declared here"; + return false; + } + } + + if (!storage_ty->Is()) { + AddError(decl->source) << sem_.TypeNameOf(storage_ty) << " cannot be used as the type of a " + << style::Keyword("override"); + return false; + } + + return true; +} + +bool Validator::Const(const sem::Variable*) const { + return true; +} + +bool Validator::Parameter(const sem::Variable* var) const { + auto* decl = var->Declaration(); + + if (auto* ref = var->Type()->As()) { + bool ok = false; + + auto sc = ref->AddressSpace(); + switch (sc) { + case core::AddressSpace::kFunction: + case core::AddressSpace::kPrivate: + ok = true; + break; + case core::AddressSpace::kImmediate: + case core::AddressSpace::kStorage: + case core::AddressSpace::kUniform: + case core::AddressSpace::kWorkgroup: + ok = allowed_features_.features.count( + wgsl::LanguageFeature::kUnrestrictedPointerParameters) != 0; + break; + default: + break; + } + if (!ok) { + AddError(decl->source) << "function parameter of pointer type cannot be in " + << style::Enum(sc) << " address space"; + return false; + } + } + + auto* ba = var->Type()->As(); + bool is_runtime_binding_array = ba && ba->Count()->Is(); + + if (IsPlain(var->Type())) { + if (!var->Type()->IsConstructible()) { + AddError(decl->type->source) << "type of function parameter must be constructible"; + return false; + } + } else if (is_runtime_binding_array || + (!var->Type()->Is() && !var->Type()->IsHandle())) { + AddError(decl->source) << "type of function parameter cannot be " + << sem_.TypeNameOf(var->Type()); + return false; + } + + return true; +} + +bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr, + const core::type::Type* storage_ty, + ast::PipelineStage stage, + const bool is_input) const { + auto* type = storage_ty->UnwrapRef(); + bool is_stage_mismatch = false; + bool is_output = !is_input; + auto builtin = attr->builtin; + auto depth_mode = attr->depth_mode; + + auto err_builtin_type = [&](std::string_view required) { + AddError(attr->source) << "store type of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") << " must be " + << style::Type(required); + }; + + switch (builtin) { + case core::BuiltinValue::kPosition: { + if (stage != ast::PipelineStage::kNone && + !((is_input && stage == ast::PipelineStage::kFragment) || + (is_output && stage == ast::PipelineStage::kVertex))) { + is_stage_mismatch = true; + } + auto* vec = type->As(); + if (!(vec && vec->Width() == 4 && vec->Type()->Is())) { + err_builtin_type("vec4"); + return false; + } + break; + } + case core::BuiltinValue::kGlobalInvocationId: + case core::BuiltinValue::kLocalInvocationId: + case core::BuiltinValue::kNumWorkgroups: + case core::BuiltinValue::kWorkgroupId: + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kCompute && is_input)) { + is_stage_mismatch = true; + } + if (!(type->IsUnsignedIntegerVector() && + type->As()->Width() == 3)) { + err_builtin_type("vec3"); + return false; + } + break; + case core::BuiltinValue::kFragDepth: + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kFragment && !is_input)) { + is_stage_mismatch = true; + } + if (!allowed_features_.features.contains(wgsl::LanguageFeature::kFragmentDepth) && + depth_mode != core::BuiltinDepthMode::kUndefined) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ", ", style::Enum(depth_mode), ")") + << " attribute requires the " << style::Code("fragment_depth") + << " language feature"; + return false; + } + if (!type->Is()) { + err_builtin_type("f32"); + return false; + } + break; + case core::BuiltinValue::kFrontFacing: + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kFragment && is_input)) { + is_stage_mismatch = true; + } + if (!type->Is()) { + err_builtin_type("bool"); + return false; + } + break; + case core::BuiltinValue::kLocalInvocationIndex: + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kCompute && is_input)) { + is_stage_mismatch = true; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + break; + case core::BuiltinValue::kVertexIndex: + case core::BuiltinValue::kInstanceIndex: + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kVertex && is_input)) { + is_stage_mismatch = true; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + break; + case core::BuiltinValue::kSampleMask: + if (stage != ast::PipelineStage::kNone && !(stage == ast::PipelineStage::kFragment)) { + is_stage_mismatch = true; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + break; + case core::BuiltinValue::kSampleIndex: + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kFragment && is_input)) { + is_stage_mismatch = true; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + break; + case core::BuiltinValue::kSubgroupId: + if (!enabled_extensions_.Contains(wgsl::Extension::kSubgroups)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " attribute requires enabling extension " << style::Code("subgroups"); + return false; + } + // TODO(crbug.com/454654105): Remove this check. + if (!allowed_features_.features.contains(wgsl::LanguageFeature::kSubgroupId)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") << " attribute requires the " + << style::Code("subgroup_id") << " language feature"; + return false; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kCompute && is_input)) { + AddError(attr->source) + << style::Attribute("@builtin") << style::Code("(", style::Enum(builtin), ")") + << " is only valid as a compute shader input"; + return false; + } + break; + case core::BuiltinValue::kNumSubgroups: + if (!enabled_extensions_.Contains(wgsl::Extension::kSubgroups)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " attribute requires enabling extension " << style::Code("subgroups"); + return false; + } + // TODO(crbug.com/454654105): Remove this check. + if (!allowed_features_.features.contains(wgsl::LanguageFeature::kSubgroupId)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") << " attribute requires the " + << style::Code("subgroup_id") << " language feature"; + return false; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kCompute && is_input)) { + AddError(attr->source) + << style::Attribute("@builtin") << style::Code("(", style::Enum(builtin), ")") + << " is only valid as a compute shader input"; + return false; + } + break; + case core::BuiltinValue::kSubgroupInvocationId: + case core::BuiltinValue::kSubgroupSize: + if (!enabled_extensions_.Contains(wgsl::Extension::kSubgroups)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " attribute requires enabling extension " << style::Code("subgroups"); + return false; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + if (stage != ast::PipelineStage::kNone && !((stage == ast::PipelineStage::kCompute || + stage == ast::PipelineStage::kFragment) && + is_input)) { + AddError(attr->source) + << style::Attribute("@builtin") << style::Code("(", style::Enum(builtin), ")") + << " is only valid as a compute or fragment shader input"; + return false; + } + break; + case core::BuiltinValue::kClipDistances: { + if (!enabled_extensions_.Contains(wgsl::Extension::kClipDistances)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " requires enabling extension " << style::Code("clip_distances"); + return false; + } + auto* arr = type->As(); + if (!((arr != nullptr) && arr->ElemType()->Is() && + arr->ConstantCount().has_value() && + *arr->ConstantCount() <= kMaxClipDistancesSize)) { + AddError(attr->source) + << "store type of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") << " must be " + << style::Type("array") << " (N <= " << kMaxClipDistancesSize << ")"; + return false; + } + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kVertex && !is_input)) { + is_stage_mismatch = true; + } + break; + } + case core::BuiltinValue::kPrimitiveIndex: { + if (!enabled_extensions_.Contains(wgsl::Extension::kPrimitiveIndex)) { + AddError(attr->source) + << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " requires enabling extension " << style::Code("primitive_index"); + return false; + } + if (!type->Is()) { + err_builtin_type("u32"); + return false; + } + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kFragment && is_input)) { + is_stage_mismatch = true; + } + break; + } + case core::BuiltinValue::kBarycentricCoord: { + if (!enabled_extensions_.Contains( + wgsl::Extension::kChromiumExperimentalBarycentricCoord)) { + AddError(attr->source) << "use of " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " requires enabling extension " + << style::Code("chromium_experimental_barycentric_coord"); + return false; + } + if (!(type->IsFloatVector() && type->As()->Width() == 3)) { + err_builtin_type("vec3"); + return false; + } + if (stage != ast::PipelineStage::kNone && + !(stage == ast::PipelineStage::kFragment && is_input)) { + is_stage_mismatch = true; + } + break; + } + default: + break; + } + + if (is_stage_mismatch) { + AddError(attr->source) << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " cannot be used for " << stage << " shader " + << (is_input ? "input" : "output"); + return false; + } + + if (allowed_features_.features.contains(wgsl::LanguageFeature::kFragmentDepth) && + depth_mode != core::BuiltinDepthMode::kUndefined && + builtin != core::BuiltinValue::kFragDepth) { + AddError(attr->source) << "Builtin depth mode " << style::Code(style::Enum(depth_mode)) + << " cannot be used for " << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")"); + return false; + } + + return true; +} + +bool Validator::InterpolateAttribute(const ast::InterpolateAttribute* attr, + const core::type::Type* storage_ty, + const ast::PipelineStage stage) const { + if (stage == ast::PipelineStage::kCompute) { + AddError(attr->source) << style::Attribute("@", attr->Name()) + << " cannot be used by compute shaders"; + return false; + } + + auto* type = storage_ty->UnwrapRef(); + + auto i_type = attr->interpolation.type; + auto i_sampling = attr->interpolation.sampling; + if (DAWN_UNLIKELY(i_type == core::InterpolationType::kUndefined)) { + return false; + } + + if (type->IsIntegerScalarOrVector() && i_type != core::InterpolationType::kFlat) { + AddError(attr->source) << "interpolation type must be " << style::Enum("flat") + << " for integral user-defined IO types"; + return false; + } + + if (i_sampling != core::InterpolationSampling::kUndefined) { + bool is_first_or_either = i_sampling == core::InterpolationSampling::kFirst || + i_sampling == core::InterpolationSampling::kEither; + + if (i_type == core::InterpolationType::kFlat) { + if (!is_first_or_either) { + AddError(attr->source) + << "flat interpolation can only use 'first' and 'either' sampling parameters"; + return false; + } + } else { + if (is_first_or_either) { + AddError(attr->source) << "'first' and 'either' sampling parameters can only be " + "used with flat interpolation"; + return false; + } + } + } + + return true; +} + +bool Validator::InvariantAttribute(const ast::InvariantAttribute* attr, + const ast::PipelineStage stage) const { + if (stage == ast::PipelineStage::kCompute) { + AddError(attr->source) << style::Attribute("@", attr->Name()) + << " cannot be used by compute shaders"; + return false; + } + return true; +} + +bool Validator::Function(const sem::Function* func, ast::PipelineStage stage) const { + auto* decl = func->Declaration(); + + for (auto* attr : decl->attributes) { + bool ok = Switch( + attr, // + [&](const ast::WorkgroupAttribute*) { + if (decl->PipelineStage() != ast::PipelineStage::kCompute) { + AddError(attr->source) << style::Attribute("@workgroup_size") + << " is only valid for compute stages"; + return false; + } + return true; + }, + [&](const ast::MustUseAttribute*) { + if (func->ReturnType()->Is()) { + AddError(attr->source) + << style::Attribute("@must_use") + << " can only be applied to functions that return a value"; + return false; + } + return true; + }, + [&](const ast::SubgroupSizeAttribute*) { + if (!enabled_extensions_.Contains( + wgsl::Extension::kChromiumExperimentalSubgroupSizeControl)) { + AddError(attr->source) + << "use of " << style::Attribute("@subgroup_size") + << " requires enabling extension " + << style::Code("chromium_experimental_subgroup_size_control"); + return false; + } + if (decl->PipelineStage() != ast::PipelineStage::kCompute) { + AddError(attr->source) << style::Attribute("@subgroup_size") + << " is only valid for compute stages"; + return false; + } + return true; + }, + [&](Default) { return true; }); + if (!ok) { + return false; + } + } + + if (decl->params.Length() > kMaxFunctionParameters) { + AddError(decl->name->source) << "function declares " << decl->params.Length() + << " parameters, maximum is " << kMaxFunctionParameters; + return false; + } + + if (!func->ReturnType()->Is()) { + if (!func->ReturnType()->IsConstructible()) { + AddError(decl->return_type->source) + << "function return type must be a constructible type"; + return false; + } + + TINT_ASSERT(decl->body) << "function " << decl->name->symbol.NameView() << " has no body"; + + auto behaviors = sem_.Get(decl->body)->Behaviors(); + if (behaviors.Contains(sem::Behavior::kNext)) { + auto end_source = decl->body->source.End(); + end_source.range.begin.column--; + AddError(end_source) << "missing return at end of function"; + return false; + } + } + + if (decl->IsEntryPoint()) { + if (!EntryPoint(func, stage)) { + return false; + } + } + + // https://www.w3.org/TR/WGSL/#behaviors-rules + // a function behavior is always one of {}, or {Next}. + if (DAWN_UNLIKELY(func->Behaviors() != sem::Behaviors{} && + func->Behaviors() != sem::Behavior::kNext)) { + auto name = decl->name->symbol.NameView(); + TINT_ICE() << "function '" << name << "' behaviors are: " << func->Behaviors(); + } + + return true; +} + +bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage) const { + auto* decl = func->Declaration(); + + // Use a lambda to validate the entry point attributes for a type. + // Persistent state is used to track which builtins and locations have already been seen, in + // order to catch conflicts. + // TODO(jrprice): This state could be stored in sem::Function instead, and then passed to + // sem::Function since it would be useful there too. + Hashset builtins; + Hashset, 8> locations_and_blend_srcs; + Hashset colors; + enum class ParamOrRetType { + kParameter, + kReturnType, + }; + + // Inner lambda that is applied to a type and all of its members. + auto validate_entry_point_attributes_inner = [&](VectorRef attrs, + const core::type::Type* ty, Source source, + ParamOrRetType param_or_ret, + bool is_struct_member, + std::optional location, + std::optional blend_src, + std::optional color) { + // Scan attributes for pipeline IO attributes. + // Check for overlap with attributes that have been seen previously. + const ast::Attribute* pipeline_io_attribute = nullptr; + const ast::LocationAttribute* location_attribute = nullptr; + const ast::ColorAttribute* color_attribute = nullptr; + const ast::BlendSrcAttribute* blend_src_attribute = nullptr; + const ast::InterpolateAttribute* interpolate_attribute = nullptr; + const ast::InvariantAttribute* invariant_attribute = nullptr; + for (auto* attr : attrs) { + bool ok = Switch( + attr, // + [&](const ast::BuiltinAttribute* builtin_attr) { + auto builtin = builtin_attr->builtin; + + if (pipeline_io_attribute) { + AddError(attr->source) << "multiple entry point IO attributes"; + AddNote(pipeline_io_attribute->source) + << "previously consumed " + << style::Attribute("@", pipeline_io_attribute->Name()); + return false; + } + pipeline_io_attribute = attr; + + if (builtins.Contains(builtin)) { + AddError(decl->source) + << style::Attribute("@builtin") + << style::Code("(", style::Enum(builtin), ")") + << " appears multiple times as pipeline " + << (param_or_ret == ParamOrRetType::kParameter ? "input" : "output"); + return false; + } + + if (!BuiltinAttribute( + builtin_attr, ty, stage, + /* is_input */ param_or_ret == ParamOrRetType::kParameter)) { + return false; + } + builtins.Add(builtin); + return true; + }, + [&](const ast::LocationAttribute* loc_attr) { + location_attribute = loc_attr; + if (pipeline_io_attribute) { + AddError(attr->source) << "multiple entry point IO attributes"; + AddNote(pipeline_io_attribute->source) + << "previously consumed " + << style::Attribute("@", pipeline_io_attribute->Name()); + return false; + } + pipeline_io_attribute = attr; + + TINT_ASSERT(location.has_value()) << "@location has no value"; + + return LocationAttribute(loc_attr, ty, stage, source); + }, + [&](const ast::BlendSrcAttribute* blend_src_attr) { + blend_src_attribute = blend_src_attr; + + TINT_ASSERT(blend_src.has_value()) << "@blend_src has no value"; + + bool is_input = param_or_ret == ParamOrRetType::kParameter; + return BlendSrcAttribute(blend_src_attr, stage, is_input); + }, + [&](const ast::ColorAttribute* col_attr) { + color_attribute = col_attr; + if (pipeline_io_attribute) { + AddError(attr->source) << "multiple entry point IO attributes"; + AddNote(pipeline_io_attribute->source) + << "previously consumed " + << style::Attribute("@", pipeline_io_attribute->Name()); + return false; + } + pipeline_io_attribute = attr; + + bool is_input = param_or_ret == ParamOrRetType::kParameter; + + TINT_ASSERT(color.has_value()) << "@color has no value"; + + return ColorAttribute(col_attr, ty, stage, source, is_input); + }, + [&](const ast::InterpolateAttribute* interpolate) { + interpolate_attribute = interpolate; + return InterpolateAttribute(interpolate, ty, stage); + }, + [&](const ast::InvariantAttribute* invariant) { + invariant_attribute = invariant; + return InvariantAttribute(invariant, stage); + }, + [&](Default) { return true; }); + + if (!ok) { + return false; + } + } + + if (is_struct_member && ty->Is()) { + AddError(source) << "nested structures cannot be used for entry point IO"; + return false; + } + + if (!ty->Is() && !pipeline_io_attribute) { + auto& err = AddError(source) << "missing entry point IO attribute"; + if (!is_struct_member) { + err << (param_or_ret == ParamOrRetType::kParameter ? " on parameter" + : " on return type"); + } + return false; + } + + if (pipeline_io_attribute && pipeline_io_attribute->Is()) { + if (ty->IsIntegerScalarOrVector() && !interpolate_attribute) { + if (decl->PipelineStage() == ast::PipelineStage::kVertex && + param_or_ret == ParamOrRetType::kReturnType) { + AddError(source) << "integral user-defined vertex outputs must have a " + << style::Attribute("@interpolate") + << style::Code("(", style::Enum("flat"), ")") << " attribute"; + return false; + } + if (decl->PipelineStage() == ast::PipelineStage::kFragment && + param_or_ret == ParamOrRetType::kParameter) { + AddError(source) << "integral user-defined fragment inputs must have a " + << style::Attribute("@interpolate") + << style::Code("(", style::Enum("flat"), ")") << " attribute"; + return false; + } + } + } + + if (location_attribute) { + std::pair location_and_blend_src(location.value(), + blend_src.value_or(0)); + if (!locations_and_blend_srcs.Add(location_and_blend_src)) { + auto& err = AddError(location_attribute->source) + << style::Attribute("@location") + << style::Code("(", style::Literal(location.value()), ")"); + if (blend_src_attribute) { + err << style::Attribute(" @blend_src") + << style::Code("(", style::Literal(blend_src.value()), ")"); + } + err << " appears multiple times"; + return false; + } + } + + if (color_attribute && !colors.Add(color.value())) { + AddError(color_attribute->source) + << style::Attribute("@color") + << style::Code("(", style::Literal(color.value()), ")") + << " appears multiple times"; + return false; + } + + if (interpolate_attribute) { + if (!pipeline_io_attribute || !pipeline_io_attribute->Is()) { + AddError(interpolate_attribute->source) + << style::Attribute("@interpolate") << " can only be used with " + << style::Attribute("@location"); + return false; + } + } + + if (invariant_attribute) { + bool has_position = false; + if (pipeline_io_attribute) { + if (auto* builtin_attr = pipeline_io_attribute->As()) { + has_position = (builtin_attr->builtin == core::BuiltinValue::kPosition); + } + } + if (!has_position) { + AddError(invariant_attribute->source) + << style::Attribute("@invariant") << " must be applied to a " + << style::Attribute("@builtin") + << style::Code("(", style::Enum("position"), ")"); + return false; + } + } + + return true; + }; + + // Outer lambda for validating the entry point attributes for a type. + auto validate_entry_point_attributes = + [&](VectorRef attrs, const core::type::Type* ty, Source source, + ParamOrRetType param_or_ret, std::optional location, + std::optional blend_src, std::optional color) { + if (!validate_entry_point_attributes_inner(attrs, ty, source, param_or_ret, + /*is_struct_member*/ false, location, + blend_src, color)) { + return false; + } + + if (auto* str = ty->As()) { + for (auto* member : str->Members()) { + if (!validate_entry_point_attributes_inner( + member->Declaration()->attributes, member->Type(), + member->Declaration()->source, param_or_ret, + /*is_struct_member*/ true, member->Attributes().location, + member->Attributes().blend_src, member->Attributes().color)) { + AddNote(decl->source) << "while analyzing entry point " + << style::Function(decl->name->symbol.NameView()); + return false; + } + } + } + + return true; + }; + + for (auto* param : func->Parameters()) { + auto* param_decl = param->Declaration(); + auto& attrs = param->Attributes(); + if (!validate_entry_point_attributes(param_decl->attributes, param->Type(), + param_decl->source, ParamOrRetType::kParameter, + attrs.location, attrs.blend_src, attrs.color)) { + return false; + } + } + + // Clear IO sets after parameter validation. Builtin and location attributes in return types + // should be validated independently from those used in parameters. + builtins.Clear(); + locations_and_blend_srcs.Clear(); + + if (!func->ReturnType()->Is()) { + if (!validate_entry_point_attributes(decl->return_type_attributes, func->ReturnType(), + decl->source, ParamOrRetType::kReturnType, + func->ReturnLocation(), /* blend_src */ std::nullopt, + /* color */ std::nullopt)) { + return false; + } + } + + if (decl->PipelineStage() == ast::PipelineStage::kVertex && + !builtins.Contains(core::BuiltinValue::kPosition)) { + AddError(decl->source) << "a vertex shader must include the " << style::Enum("position") + << " builtin in its return type"; + return false; + } + + if (decl->PipelineStage() == ast::PipelineStage::kCompute) { + if (!ast::HasAttribute(decl->attributes)) { + AddError(decl->source) << "a compute shader must include " + << style::Attribute("@workgroup_size") << " in its attributes"; + return false; + } + } + + // Validate there are no resource variable binding collisions + Hashmap binding_points; + for (auto* global : func->TransitivelyReferencedGlobals()) { + auto* var_decl = global->Declaration()->As(); + if (!var_decl) { + continue; + } + auto bp = global->Attributes().binding_point; + if (!bp) { + continue; + } + auto added = binding_points.Add(*bp, var_decl); + if (!added) { + // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface + // Bindings must not alias within a shader stage: two different variables in the + // resource interface of a given shader must not have the same group and binding values, + // when considered as a pair of values. + auto func_name = decl->name->symbol.NameView(); + AddError(var_decl->source) + << "entry point " << style::Function(func_name) + << " references multiple variables that use the same resource binding " + << style::Attribute("@group") << style::Code("(", style::Literal(bp->group), ")") + << ", " << style::Attribute("@binding") + << style::Code("(", style::Literal(bp->binding), ")"); + AddNote(added.value->source) << "first resource binding usage declared here"; + return false; + } + } + + return true; +} + +bool Validator::EvaluationStage(const sem::ValueExpression* expr, + core::EvaluationStage latest_stage, + std::string_view constraint) const { + if (expr->Stage() == core::EvaluationStage::kNotEvaluated) { + return true; + } + if (expr->Stage() > latest_stage) { + auto stage_name = [](core::EvaluationStage stage) -> std::string { + switch (stage) { + case core::EvaluationStage::kRuntime: + return "a runtime-expression"; + case core::EvaluationStage::kOverride: + return "an override-expression"; + case core::EvaluationStage::kConstant: + return "a const-expression"; + case core::EvaluationStage::kNotEvaluated: + return "an unevaluated expression"; + } + return ""; + }; + + AddError(expr->Declaration()->source) + << constraint << " requires " << stage_name(latest_stage) << ", but expression is " + << stage_name(expr->Stage()); + + if (auto* stmt = expr->Stmt()) { + if (auto* decl = As(stmt->Declaration())) { + if (decl->variable->Is()) { + AddNote(decl->source) << "consider changing " << style::Keyword("const") + << " to " << style::Keyword("let"); + } + } + } + return false; + } + return true; +} + +bool Validator::Statements(VectorRef stmts) const { + for (auto* stmt : stmts) { + if (!sem_.Get(stmt)->IsReachable()) { + if (auto* d = MaybeAddDiagnostic(wgsl::ChromiumDiagnosticRule::kUnreachableCode, + stmt->source)) { + *d << "code is unreachable"; + if (d->severity >= diag::Severity::Error) { + return false; + } + } + break; + } + } + return true; +} + +bool Validator::BinaryExpression(const ast::Node* node, + const core::BinaryOp op, + const tint::sem::ValueExpression* lhs, + const tint::sem::ValueExpression* rhs) const { + switch (op) { + case core::BinaryOp::kShiftLeft: + case core::BinaryOp::kShiftRight: { + // If lhs value is a concrete type, and rhs is a const-expression greater than or equal + // to the bit width of lhs, then it is a shader-creation error. + const auto* elem_type = lhs->Type()->UnwrapRef()->DeepestElement(); + if (!elem_type->IsAbstract() && rhs->Stage() == core::EvaluationStage::kConstant) { + const uint32_t bit_width = elem_type->Size() * 8; + auto* rhs_val = rhs->ConstantValue(); + for (size_t i = 0, n = rhs_val->NumElements(); i < n; i++) { + auto* shift_val = n == 1 ? rhs_val : rhs_val->Index(i); + if (shift_val->ValueAs() >= bit_width) { + AddError(node->source) + << "shift " << (op == core::BinaryOp::kShiftLeft ? "left" : "right") + << " value must be less than the bit width of the lhs, which is " + << bit_width; + return false; + } + } + } + return true; + } + case core::BinaryOp::kDivide: + case core::BinaryOp::kModulo: { + // Integer division by zero should be checked for the partial evaluation case (only rhs + // is const). FP division by zero is only invalid when the whole expression is + // constant-evaluated. + if (rhs->Type()->IsIntegerScalarOrVector() && + rhs->Stage() == core::EvaluationStage::kConstant) { + if (rhs->ConstantValue()->AnyZero()) { + AddError(node->source) << "integer division by zero is invalid"; + return false; + } + } + return true; + } + default: { + return true; + } + } +} + +bool Validator::BreakStatement(const sem::Statement* stmt, + sem::Statement* current_statement) const { + if (!stmt->FindFirstParent()) { + AddError(stmt->Declaration()->source) << "break statement must be in a loop or switch case"; + return false; + } + if (ClosestContinuing(/*stop_at_loop*/ true, /* stop_at_switch */ true, current_statement) != + nullptr) { + AddError(stmt->Declaration()->source) + << style::Keyword("break") << " must not be used to exit from a continuing block. Use " + << style::Keyword("break if") << " instead."; + return false; + } + return true; +} + +bool Validator::ContinueStatement(const sem::Statement* stmt, + sem::Statement* current_statement) const { + if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ true, /* stop_at_switch */ false, + current_statement)) { + AddError(stmt->Declaration()->source) + << "continuing blocks must not contain a continue statement"; + if (continuing != stmt->Declaration() && continuing != stmt->Parent()->Declaration()) { + AddNote(continuing->source) << "see continuing block here"; + } + return false; + } + + if (!stmt->FindFirstParent()) { + AddError(stmt->Declaration()->source) << "continue statement must be in a loop"; + return false; + } + + return true; +} + +bool Validator::Call(const sem::Call* call, sem::Statement* current_statement) const { + if (!call->Target()->MustUse()) { + return true; + } + + auto* expr = call->Declaration(); + bool is_call_stmt = (current_statement != nullptr) && + Is(current_statement->Declaration(), + [&](auto* stmt) { return stmt->expr == expr; }); + if (is_call_stmt) { + // Call target is annotated with @must_use, but was used as a call statement. + Switch( + call->Target(), // + [&](const sem::Function* fn) { + AddError(call->Declaration()->source) + << "ignoring return value of function " + << style::Function(fn->Declaration()->name->symbol.NameView()) + << " annotated with " << style::Attribute("@must_use"); + sem_.NoteDeclarationSource(fn->Declaration()); + }, + [&](const sem::BuiltinFn* b) { + AddError(call->Declaration()->source) + << "ignoring return value of builtin " << style::Function(b->Fn()); + }, + [&](const sem::ValueConversion*) { + AddError(call->Declaration()->source) << "value conversion evaluated but not used"; + }, + [&](const sem::ValueConstructor*) { + AddError(call->Declaration()->source) << "value constructor evaluated but not used"; + }, + [&](Default) { + AddError(call->Declaration()->source) << "return value of call not used"; + }); + return false; + } + + return true; +} + +bool Validator::LoopStatement(const sem::LoopStatement* stmt) const { + if (stmt->Behaviors().Empty()) { + AddError(stmt->Declaration()->source.Begin()) << "loop does not exit"; + return false; + } + return true; +} + +bool Validator::ForLoopStatement(const sem::ForLoopStatement* stmt) const { + if (stmt->Behaviors().Empty()) { + AddError(stmt->Declaration()->source.Begin()) << "for-loop does not exit"; + return false; + } + if (auto* cond = stmt->Condition()) { + auto* cond_ty = cond->Type()->UnwrapRef(); + if (!cond_ty->Is()) { + AddError(stmt->Condition()->Declaration()->source) + << "for-loop condition must be bool, got " << sem_.TypeNameOf(cond_ty); + return false; + } + } + return true; +} + +bool Validator::WhileStatement(const sem::WhileStatement* stmt) const { + if (stmt->Behaviors().Empty()) { + AddError(stmt->Declaration()->source.Begin()) << "while does not exit"; + return false; + } + if (auto* cond = stmt->Condition()) { + auto* cond_ty = cond->Type()->UnwrapRef(); + if (!cond_ty->Is()) { + AddError(stmt->Condition()->Declaration()->source) + << "while condition must be bool, got " << sem_.TypeNameOf(cond_ty); + return false; + } + } + return true; +} + +bool Validator::BreakIfStatement(const sem::BreakIfStatement* stmt, + sem::Statement* current_statement) const { + auto* cond_ty = stmt->Condition()->Type()->UnwrapRef(); + if (!cond_ty->Is()) { + AddError(stmt->Condition()->Declaration()->source) + << "break-if statement condition must be bool, got " << sem_.TypeNameOf(cond_ty); + return false; + } + + for (const auto* s = current_statement; s != nullptr; s = s->Parent()) { + if (s->Is()) { + break; + } + if (auto* continuing = s->As()) { + if (continuing->Declaration()->statements.Back() != stmt->Declaration()) { + AddError(stmt->Declaration()->source) + << "break-if must be the last statement in a continuing block"; + AddNote(s->Declaration()->source) << "see continuing block here"; + return false; + } + return true; + } + } + + AddError(stmt->Declaration()->source) << "break-if must be in a continuing block"; + return false; +} + +bool Validator::IfStatement(const sem::IfStatement* stmt) const { + auto* cond_ty = stmt->Condition()->Type()->UnwrapRef(); + if (!cond_ty->Is()) { + AddError(stmt->Condition()->Declaration()->source) + << "if statement condition must be bool, got " << sem_.TypeNameOf(cond_ty); + return false; + } + return true; +} + +bool Validator::BuiltinCall(const sem::Call* call) const { + if (call->Type()->Is()) { + bool is_call_statement = false; + // Some built-in call are not owned by a statement, e.g. a built-in called in global + // variable declaration. Calling no-return-value built-in in these context is invalid as + // well. + if (auto* call_stmt = call->Stmt()) { + if (auto* call_stmt_ast = As(call_stmt->Declaration())) { + if (call_stmt_ast->expr == call->Declaration()) { + is_call_statement = true; + } + } + } + if (!is_call_statement) { + // https://gpuweb.github.io/gpuweb/wgsl/#function-call-expr + // If the called function does not return a value, a function call statement should be + // used instead. + auto* builtin = call->Target()->As(); + AddError(call->Declaration()->source) + << "builtin function " << style::Function(builtin->Fn()) + << " does not return a value"; + return false; + } + } + + // The `print()` builtin requires the chromium_print language feature to be available. + if (auto* fn = call->Target()->As()) { + if (fn->Fn() == wgsl::BuiltinFn::kPrint) { + if (!allowed_features_.features.count(wgsl::LanguageFeature::kChromiumPrint)) { + AddError(call->Declaration()->source) << "the 'chromium_print' language feature is " + "not allowed in the current environment"; + return false; + } + } + } + + return true; +} + +bool Validator::SubgroupShuffleFunction(wgsl::BuiltinFn fn, const sem::Call* call) const { + auto* builtin = call->Target()->As(); + if (!builtin) { + return false; + } + + TINT_ASSERT(call->Arguments().Length() == 2); + auto* id = call->Arguments()[1]; + auto* constant_value = id->ConstantValue(); + + if (!constant_value) { + // Non const values are allowed as parameters. + return true; + } + + // User friendly param name. + std::string paramName = "sourceLaneIndex"; + switch (fn) { + case wgsl::BuiltinFn::kSubgroupShuffleXor: + paramName = "mask"; + break; + case wgsl::BuiltinFn::kSubgroupShuffleUp: + case wgsl::BuiltinFn::kSubgroupShuffleDown: + paramName = "delta"; + break; + default: + break; + } + + if (id->Type()->IsSignedIntegerScalar() && constant_value->ValueAs() < 0) { + AddError(id->Declaration()->source) + << "the " << paramName << " argument of " << builtin->str() + << " must be greater than or equal to zero"; + return false; + } + + if (id->Type()->IsSignedIntegerScalar() && + constant_value->ValueAs() >= tint::internal_limits::kMaxSubgroupSize) { + AddError(id->Declaration()->source) + << "the " << paramName << " argument of " << builtin->str() << " must be less than " + << tint::internal_limits::kMaxSubgroupSize; + return false; + } + + if (id->Type()->IsUnsignedIntegerScalar() && + constant_value->ValueAs() >= tint::internal_limits::kMaxSubgroupSize) { + AddError(id->Declaration()->source) + << "the " << paramName << " argument of " << builtin->str() << " must be less than " + << tint::internal_limits::kMaxSubgroupSize; + return false; + } + + return true; +} + +bool Validator::BufferView(const sem::Call* call) const { + auto* builtin = call->Target()->As(); + if (!builtin) { + return false; + } + + auto ContainsAtomic = [&](const core::type::Type* type) { + if (type->Is()) { + return true; + } + return atomic_composite_info_.Contains(type); + }; + auto* ret_type = call->Target()->ReturnType(); + auto* ret_ptr_type = ret_type->As(); + auto* ret_store_type = ret_ptr_type->StoreType(); + if (!ret_store_type->IsHostShareable()) { + AddError(call->Declaration()->source) + << "return type of " << builtin->str() << " must be host-shareable"; + return false; + } + if (ret_store_type->Is()) { + AddError(call->Declaration()->source) + << "return type of " << builtin->str() << " cannot be a buffer"; + return false; + } + if (ContainsAtomic(ret_store_type)) { + AddError(call->Declaration()->source) + << "return type of " << builtin->str() << " cannot contain an atomic type"; + return false; + } + + if (!CheckTypeAccessAddressSpace(ret_store_type, ret_ptr_type->Access(), + ret_ptr_type->AddressSpace(), call->Declaration()->source)) { + return false; + } + + TINT_ASSERT(call->Arguments().Length() == 2); + + auto* buffer_ptr = call->Arguments()[0]; + auto* buffer_type = + buffer_ptr->Type()->As()->StoreType()->As(); + auto* offset = call->Arguments()[1]; + auto* constant_value = offset->ConstantValue(); + if (!constant_value || !offset->Type()->IsIntegerScalar()) { + return true; + } + + uint32_t value; + if (offset->Type()->IsUnsignedIntegerScalar()) { + value = constant_value->ValueAs(); + } else { + int32_t ivalue = constant_value->ValueAs(); + if (ivalue < 0) { + AddError(offset->Declaration()->source) + << "the offset argument of " << builtin->str() << " must be non-negative"; + return false; + } + value = static_cast(ivalue); + } + if (value % ret_store_type->Align() != 0) { + AddError(offset->Declaration()->source) + << "the offset argument of " << builtin->str() + << " must evenly divide the alignment of the return type (" << ret_store_type->Align() + << ")"; + return false; + } + auto count = buffer_type->ConstantCount(); + if (count != std::nullopt && value + ret_store_type->Size() >= count.value()) { + AddError(offset->Declaration()->source) + << "the offset argument of " << builtin->str() + << " plus the size of the return type must be smaller than the buffer size"; + return false; + } + + return true; +} + +bool Validator::TextureBuiltinFn(const sem::Call* call) const { + auto* builtin = call->Target()->As(); + if (!builtin) { + return false; + } + + std::string func_name = builtin->str(); + auto& signature = builtin->Signature(); + + auto check_arg_is_constexpr = [&](core::ParameterUsage usage, int min, int max) { + auto signed_index = signature.IndexOf(usage); + if (signed_index < 0) { + return true; + } + auto index = static_cast(signed_index); + auto* arg = call->Arguments()[index]; + if (auto values = arg->ConstantValue()) { + if (auto* vector = values->Type()->As()) { + for (size_t i = 0; i < vector->Width(); i++) { + auto value = values->Index(i)->ValueAs(); + if (value < min || value > max) { + AddError(arg->Declaration()->source) + << "each component of the " << usage << " argument must be at least " + << min << " and at most " << max << ". " << usage << " component " << i + << " is " << value; + return false; + } + } + } else { + auto value = values->ValueAs(); + if (value < min || value > max) { + AddError(arg->Declaration()->source) + << "the " << usage << " argument must be at least " << min + << " and at most " << max << ". " << usage << " is " << value; + return false; + } + } + return true; + } + AddError(arg->Declaration()->source) + << "the " << usage << " argument must be a const-expression"; + return false; + }; + + return check_arg_is_constexpr(core::ParameterUsage::kOffset, -8, 7) && + check_arg_is_constexpr(core::ParameterUsage::kComponent, 0, 3); +} + +bool Validator::SubgroupBroadcast(const sem::Call* call) const { + auto* builtin = call->Target()->As(); + if (!builtin) { + return false; + } + + TINT_ASSERT(call->Arguments().Length() == 2); + auto* id = call->Arguments()[1]; + auto* constant_value = id->ConstantValue(); + + if (!constant_value) { + AddError(id->Declaration()->source) + << "the sourceLaneIndex argument of subgroupBroadcast must be a const-expression"; + return false; + } + + if (id->Type()->IsSignedIntegerScalar()) { + if (constant_value->ValueAs() < 0) { + AddError(id->Declaration()->source) + << "the sourceLaneIndex argument of subgroupBroadcast " + "must be greater than or equal to zero"; + return false; + } + if (constant_value->ValueAs() >= tint::internal_limits::kMaxSubgroupSize) { + AddError(id->Declaration()->source) + << "the sourceLaneIndex argument of subgroupBroadcast " + "must be less than " + << tint::internal_limits::kMaxSubgroupSize; + return false; + } + } + + if (id->Type()->IsUnsignedIntegerScalar() && + constant_value->ValueAs() >= tint::internal_limits::kMaxSubgroupSize) { + AddError(id->Declaration()->source) << "the sourceLaneIndex argument of subgroupBroadcast " + "must be less than " + << tint::internal_limits::kMaxSubgroupSize; + return false; + } + + return true; +} + +bool Validator::QuadBroadcast(const sem::Call* call) const { + auto* builtin = call->Target()->As(); + if (!builtin) { + return false; + } + + TINT_ASSERT(call->Arguments().Length() == 2); + auto* id = call->Arguments()[1]; + auto* constant_value = id->ConstantValue(); + + if (!constant_value) { + AddError(id->Declaration()->source) + << "the id argument of quadBroadcast must be a const-expression"; + return false; + } + + if (id->Type()->IsSignedIntegerScalar()) { + if (constant_value->ValueAs() < 0) { + AddError(id->Declaration()->source) + << "the id argument of quadBroadcast must be greater than or equal to zero"; + return false; + } + if (constant_value->ValueAs() >= tint::internal_limits::kQuadSize) { + AddError(id->Declaration()->source) + << "the id argument of quadBroadcast must be less than " + << tint::internal_limits::kQuadSize; + return false; + } + } + + if (id->Type()->IsUnsignedIntegerScalar() && + constant_value->ValueAs() >= tint::internal_limits::kQuadSize) { + AddError(id->Declaration()->source) << "the id argument of quadBroadcast must be less than " + << tint::internal_limits::kQuadSize; + return false; + } + + return true; +} + +bool Validator::RequiredFeaturesForBuiltinFn(const sem::Call* call) const { + const auto* builtin = call->Target()->As(); + if (!builtin) { + return true; + } + + if (builtin->IsSubgroup()) { + if (!enabled_extensions_.Contains(wgsl::Extension::kSubgroups)) { + AddError(call->Declaration()->source) + << "cannot call built-in function " << style::Function(builtin->Fn()) + << " without extension " + << style::Code(wgsl::ToString(wgsl::Extension::kSubgroups)); + return false; + } + } + + if (builtin->IsResourceTable()) { + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalResourceTable)) { + AddError(call->Declaration()->source) + << "cannot call built-in function " << style::Function(builtin->Fn()) + << " without extension " + << style::Code(wgsl::ToString(wgsl::Extension::kChromiumExperimentalResourceTable)); + return false; + } + } + + const auto feature = builtin->RequiredLanguageFeature(); + if (feature != wgsl::LanguageFeature::kUndefined) { + if (!allowed_features_.features.count(feature)) { + AddError(call->Declaration()->source) + << "built-in function " << style::Function(builtin->Fn()) << " requires the " + << style::Code(wgsl::ToString(feature)) + << " language feature, which is not allowed in the current environment"; + return false; + } + } + + return true; +} + +bool Validator::CheckF16Enabled(const Source& source) const { + // Validate if f16 type is allowed. + if (!enabled_extensions_.Contains(wgsl::Extension::kF16)) { + AddError(source) << style::Type("f16") << " type used without " << style::Code("f16") + << " extension enabled"; + return false; + } + return true; +} + +bool Validator::CheckI8Enabled(const Source& source) const { + // Validate if i8 type is allowed. + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalSubgroupMatrix)) { + AddError(source) << style::Type("i8") << " type used without " + << style::Code("chromium_experimental_subgroup_matrix") + << " extension enabled"; + return false; + } + return true; +} + +bool Validator::CheckU8Enabled(const Source& source) const { + // Validate if u8 type is allowed. + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalSubgroupMatrix)) { + AddError(source) << style::Type("u8") << " type used without " + << style::Code("chromium_experimental_subgroup_matrix") + << " extension enabled"; + return false; + } + return true; +} + +bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_statement) const { + auto* decl = call->Declaration(); + auto* target = call->Target()->As(); + auto sym = target->Declaration()->name->symbol; + auto name = sym.Name(); + + if (!current_statement) { // Function call at module-scope. + AddError(decl->source) << "user-declared functions cannot be called at module-scope"; + return false; + } + + if (target->Declaration()->IsEntryPoint()) { + // https://www.w3.org/TR/WGSL/#function-restriction + // An entry point must never be the target of a function call. + AddError(decl->source) << "entry point functions cannot be the target of a function call"; + return false; + } + + if (decl->args.Length() != target->Parameters().Length()) { + bool more = decl->args.Length() > target->Parameters().Length(); + AddError(decl->source) << "too " + << (more ? std::string("many") : std::string("few")) + + " arguments in call to " + << style::Function(name) << ", expected " + << target->Parameters().Length() << ", got " + << call->Arguments().Length(); + return false; + } + + for (size_t i = 0; i < call->Arguments().Length(); ++i) { + const sem::Variable* param = target->Parameters()[i]; + const ast::Expression* arg_expr = decl->args[i]; + auto* param_type = param->Type(); + auto* arg_type = sem_.TypeOf(arg_expr)->UnwrapRef(); + + bool allow_mismatch = false; + if (param_type->Is() && arg_type->Is()) { + auto* arg_ptr_type = arg_type->As(); + auto* arg_store_type = arg_ptr_type->StoreType(); + auto* param_ptr_type = param_type->As(); + auto* param_store_type = param_ptr_type->StoreType(); + if (arg_store_type->Is() && + param_store_type->Is()) { + const bool param_unsized = param_store_type->As() + ->Count() + ->Is(); + auto arg_count = arg_store_type->As()->ConstantCount(); + auto param_count = param_store_type->As()->ConstantCount(); + if (arg_ptr_type->AddressSpace() == param_ptr_type->AddressSpace() && + arg_ptr_type->Access() == param_ptr_type->Access() && + (param_unsized || arg_count.value_or(0) > param_count.value_or(0))) { + // Any buffer argument can match an unsized buffer parameter. + // A larger buffer argument can match a smaller buffer parameter. + allow_mismatch = true; + } + } + } + + if (!allow_mismatch && param_type != arg_type) { + AddError(arg_expr->source) << "type mismatch for argument " << (i + 1) << " in call to " + << style::Function(name) << ", expected " + << style::Type(sem_.TypeNameOf(param_type)) << ", got " + << style::Type(sem_.TypeNameOf(arg_type)); + return false; + } + + if (param_type->Is() && + (allowed_features_.features.count( + wgsl::LanguageFeature::kUnrestrictedPointerParameters) == 0u)) { + // https://gpuweb.github.io/gpuweb/wgsl/#function-restriction + // Each argument of pointer type to a user-defined function must have the same memory + // view as its root identifier. + // We can validate this by just comparing the store type of the argument with that of + // its root identifier, as these will match iff the memory view is the same. + auto* arg_store_type = arg_type->As()->StoreType(); + auto* root = call->Arguments()[i]->RootIdentifier(); + auto* root_ptr_ty = root->Type()->As(); + auto* root_ref_ty = root->Type()->As(); + TINT_ASSERT(root_ptr_ty || root_ref_ty); + const core::type::Type* root_store_type; + if (root_ptr_ty) { + root_store_type = root_ptr_ty->StoreType(); + } else { + root_store_type = root_ref_ty->StoreType(); + } + if (root_store_type != arg_store_type) { + AddError(arg_expr->source) << "arguments of pointer type must not point to a " + "subset of the originating variable"; + return false; + } + } + } + + if (call->Type()->Is()) { + bool is_call_statement = false; + if (auto* call_stmt = As(call->Stmt()->Declaration())) { + if (call_stmt->expr == call->Declaration()) { + is_call_statement = true; + } + } + if (!is_call_statement) { + // https://gpuweb.github.io/gpuweb/wgsl/#function-call-expr + // If the called function does not return a value, a function call + // statement should be used instead. + AddError(decl->source) + << "function " << style::Function(name) << " does not return a value"; + return false; + } + } + + return true; +} + +bool Validator::StructureInitializer(const ast::CallExpression* ctor, + const core::type::Struct* struct_type) const { + if (!struct_type->IsConstructible()) { + AddError(ctor->source) << "structure constructor has non-constructible type"; + return false; + } + + if (ctor->args.Length() > 0) { + if (ctor->args.Length() != struct_type->Members().Length()) { + std::string fm = ctor->args.Length() < struct_type->Members().Length() ? "few" : "many"; + AddError(ctor->source) + << "structure constructor has too " << fm << " inputs: expected " + << struct_type->Members().Length() << ", found " << ctor->args.Length(); + return false; + } + for (auto* member : struct_type->Members()) { + auto* value = ctor->args[member->Index()]; + auto* value_ty = sem_.TypeOf(value); + if (member->Type() != value_ty->UnwrapRef()) { + AddError(value->source) + << "type in structure constructor does not match struct member type: expected " + << style::Type(sem_.TypeNameOf(member->Type())) << ", found " + << style::Type(sem_.TypeNameOf(value_ty)); + return false; + } + } + } + return true; +} + +bool Validator::ArrayConstructor(const ast::CallExpression* ctor, + const sem::Array* array_type) const { + auto& values = ctor->args; + if (values.Length() > internal_limits::kMaxArrayConstructorElements) { + AddError(ctor->target->source) << "array constructor has excessive number of elements (>" + << internal_limits::kMaxArrayConstructorElements << ")"; + return false; + } + + auto* elem_ty = array_type->ElemType(); + for (auto* value : values) { + auto* value_ty = sem_.TypeOf(value)->UnwrapRef(); + if (core::type::Type::ConversionRank(value_ty, elem_ty) == + core::type::Type::kNoConversion) { + AddError(value->source) << style::Type(sem_.TypeNameOf(value_ty)) + << " cannot be used to construct an array of " + << style::Type(sem_.TypeNameOf(elem_ty)); + return false; + } + } + + auto* c = array_type->Count(); + if (c->Is()) { + AddError(ctor->source) << "cannot construct a runtime-sized array"; + return false; + } + + if (c->IsAnyOf()) { + AddError(ctor->source) << "cannot construct an array that has an override-expression count"; + return false; + } + + if (!elem_ty->IsConstructible()) { + AddError(ctor->source) << "array constructor has non-constructible element type"; + return false; + } + + TINT_ASSERT(c->Is()) << "Invalid ArrayCount found"; + + const auto count = c->As()->value; + if (!values.IsEmpty() && (values.Length() != count)) { + std::string fm = values.Length() < count ? "few" : "many"; + AddError(ctor->source) << "array constructor has too " << fm << " elements: expected " + << count << ", found " << values.Length(); + return false; + } + return true; +} + +bool Validator::SubgroupMatrixConstructor(const ast::CallExpression* ctor, + const core::type::SubgroupMatrix* subgroup_matrix_type, + const sem::CallTarget* signature) const { + auto& values = ctor->args; + if (values.Length() == 1) { + auto* elem_ty = subgroup_matrix_type->Type(); + auto* value_ty = sem_.TypeOf(values[0])->UnwrapRef(); + auto* expected_ty = signature->Parameters()[0]->Type(); + if (core::type::Type::ConversionRank(value_ty, expected_ty) == + core::type::Type::kNoConversion) { + AddError(values[0]->source) << style::Type(sem_.TypeNameOf(value_ty)) + << " cannot be used to construct a subgroup matrix of " + << style::Type(sem_.TypeNameOf(elem_ty)); + return false; + } + } else if (values.Length() > 1) { + AddError(ctor->target->source) + << "subgroup_matrix constructor can only have zero or one elements"; + return false; + } + + return true; +} + +bool Validator::Vector(const core::type::Type* el_ty, const Source& source) const { + if (!el_ty->Is() || el_ty->Is() || + el_ty->Is()) { + AddError(source) << "vector element type must be " << style::Type("bool") << ", " + << style::Type("f32") << ", " << style::Type("f16") << ", " + << style::Type("i32") << " or " << style::Type("u32"); + return false; + } + return true; +} + +bool Validator::Matrix(const core::type::Type* el_ty, const Source& source) const { + if (!el_ty->IsFloatScalar()) { + AddError(source) << "matrix element type must be " << style::Type("f32") << " or " + << style::Type("f16"); + return false; + } + return true; +} + +bool Validator::PipelineStages(VectorRef entry_points) const { + auto var_source = [&](const sem::Function* func, const sem::GlobalVariable* var) { + for (auto* user : var->Users()) { + if (user->Stmt() && func == user->Stmt()->Function()) { + return user->Declaration()->source; + } + } + return Source(); + }; + + auto backtrace = [&](const sem::Function* func, const sem::Function* entry_point) { + if (func != entry_point) { + TraverseCallChain(entry_point, func, [&](const sem::Function* f) { + AddNote(f->Declaration()->source) + << "called by function " + << style::Function(f->Declaration()->name->symbol.NameView()); + }); + AddNote(entry_point->Declaration()->source) + << "called by entry point " + << style::Function(entry_point->Declaration()->name->symbol.NameView()); + } + }; + + auto check_var_uses = [&](const sem::Function* func, const sem::Function* entry_point) { + auto var_decl_note = [&](const sem::GlobalVariable* var) { + AddNote(var->Declaration()->source) << "variable is declared here"; + backtrace(func, entry_point); + }; + + auto stage = entry_point->Declaration()->PipelineStage(); + for (auto* var : func->DirectlyReferencedGlobals()) { + Source source = var_source(func, var); + if ((stage != ast::PipelineStage::kCompute && + var->AddressSpace() == core::AddressSpace::kWorkgroup) || + (stage != ast::PipelineStage::kFragment && + var->AddressSpace() == core::AddressSpace::kPixelLocal)) { + AddError(source) << "var with " << style::Enum(var->AddressSpace()) + << " address space cannot be used by " << stage + << " pipeline stage"; + var_decl_note(var); + return false; + } + if (stage == ast::PipelineStage::kVertex && + var->AddressSpace() == core::AddressSpace::kStorage && + var->Access() != core::Access::kRead) { + AddError(source) << "var with " << style::Enum(var->AddressSpace()) + << " address space and " << style::Enum(var->Access()) + << " access mode cannot be used by " << stage << " pipeline stage"; + var_decl_note(var); + return false; + } + auto* storage = var->Type()->UnwrapRef()->As(); + if (stage == ast::PipelineStage::kVertex && storage && + storage->Access() != core::Access::kRead) { + AddError(source) << "storage texture with " << style::Enum(storage->Access()) + << " access mode cannot be used by " << stage << " pipeline stage"; + var_decl_note(var); + return false; + } + } + return true; + }; + + auto check_builtin_calls = [&](const sem::Function* func, const sem::Function* entry_point) { + auto stage = entry_point->Declaration()->PipelineStage(); + for (auto* builtin : func->DirectlyCalledBuiltins()) { + if (!builtin->SupportedStages().Contains(stage)) { + auto* call = func->FindDirectCallTo(builtin); + AddError(call ? call->Declaration()->source : func->Declaration()->source) + << "built-in cannot be used by " << stage << " pipeline stage"; + backtrace(func, entry_point); + return false; + } + } + return true; + }; + + auto check_no_discards = [&](const sem::Function* func, const sem::Function* entry_point) { + if (auto* discard = func->DiscardStatement()) { + auto stage = entry_point->Declaration()->PipelineStage(); + AddError(discard->Declaration()->source) + << "discard statement cannot be used in " << stage << " pipeline stage"; + backtrace(func, entry_point); + return false; + } + return true; + }; + + auto check_no_subgroup_matrix = [&](const sem::Function* func, + const sem::Function* entry_point) { + if (auto matrix_use = func->DirectlyUsedSubgroupMatrix()) { + auto stage = entry_point->Declaration()->PipelineStage(); + AddError(*(matrix_use.value())) + << "subgroup matrix type cannot be used in " << stage << " pipeline stage"; + backtrace(func, entry_point); + return false; + } + return true; + }; + + auto check_func = [&](const sem::Function* func, const sem::Function* entry_point) { + if (!check_var_uses(func, entry_point)) { + return false; + } + if (!check_builtin_calls(func, entry_point)) { + return false; + } + if (entry_point->Declaration()->PipelineStage() != ast::PipelineStage::kFragment) { + if (!check_no_discards(func, entry_point)) { + return false; + } + } + if (entry_point->Declaration()->PipelineStage() != ast::PipelineStage::kCompute) { + if (!check_no_subgroup_matrix(func, entry_point)) { + return false; + } + } + return true; + }; + + for (auto* entry_point : entry_points) { + if (!check_func(entry_point, entry_point)) { + return false; + } + for (auto* func : entry_point->TransitivelyCalledFunctions()) { + if (!check_func(func, entry_point)) { + return false; + } + } + } + + return true; +} + +bool Validator::ModuleScopeVarUsages(VectorRef entry_points) const { + for (auto* entry_point : entry_points) { + if (!CheckNoMultipleModuleScopeVarsOfAddressSpace(entry_point, + core::AddressSpace::kImmediate)) { + return false; + } + if (!CheckNoMultipleModuleScopeVarsOfAddressSpace(entry_point, + core::AddressSpace::kPixelLocal)) { + return false; + } + } + + return true; +} + +bool Validator::Array(const sem::Array* arr, const Source& el_source) const { + auto* el_ty = arr->ElemType(); + + if (!IsPlain(el_ty)) { + AddError(el_source) << sem_.TypeNameOf(el_ty) + << " cannot be used as an element type of an array"; + return false; + } + + if (!el_ty->HasFixedFootprint()) { + AddError(el_source) << "an array element type cannot contain a runtime-sized array"; + return false; + } + + if (IsArrayWithOverrideCount(el_ty)) { + RaiseArrayWithOverrideCountError(el_source); + return false; + } + + return true; +} + +bool Validator::Alias(const ast::Alias*) const { + return true; +} + +bool Validator::Structure(const sem::Struct* str, ast::PipelineStage stage) const { + if (str->Members().IsEmpty()) { + AddError(str->Declaration()->name->source) << "structures must have at least one member"; + return false; + } + + std::bitset<2> blend_src_appearance_mask; + const ast::BlendSrcAttribute* first_blend_src = nullptr; + const core::type::Type* first_blend_src_type = nullptr; + const ast::LocationAttribute* first_location_without_blend_src = nullptr; + Hashset>, 8> locations_and_blend_srcs; + Hashset colors; + for (auto* member : str->Members()) { + if (auto* r = member->Type()->As()) { + if (r->Count()->Is()) { + if (member != str->Members().Back()) { + AddError(member->Declaration()->source) + << "runtime arrays may only appear as the last member of a struct"; + return false; + } + } + + if (IsArrayWithOverrideCount(member->Type())) { + RaiseArrayWithOverrideCountError(member->Declaration()->type->source); + return false; + } + } else if (!member->Type()->HasFixedFootprint()) { + AddError(member->Declaration()->source) + << "a struct that contains a runtime array cannot be nested inside another struct"; + return false; + } + + auto has_position = false; + const ast::BlendSrcAttribute* blend_src_attribute = nullptr; + const ast::LocationAttribute* location_attribute = nullptr; + const ast::ColorAttribute* color_attribute = nullptr; + const ast::InvariantAttribute* invariant_attribute = nullptr; + const ast::InterpolateAttribute* interpolate_attribute = nullptr; + for (auto* attr : member->Declaration()->attributes) { + bool ok = Switch( + attr, // + [&](const ast::InvariantAttribute* invariant) { + invariant_attribute = invariant; + return InvariantAttribute(invariant, stage); + }, + [&](const ast::LocationAttribute* location) { + location_attribute = location; + TINT_ASSERT(member->Attributes().location.has_value()); + return LocationAttribute(location, member->Type(), stage, + member->Declaration()->source); + }, + [&](const ast::BlendSrcAttribute* blend_src) { + blend_src_attribute = blend_src; + return BlendSrcAttribute(blend_src, stage); + }, + [&](const ast::ColorAttribute* color) { + color_attribute = color; + return ColorAttribute(color, member->Type(), stage, + member->Declaration()->source); + }, + [&](const ast::BuiltinAttribute* builtin_attr) { + if (!BuiltinAttribute(builtin_attr, member->Type(), stage, + /* is_input */ false)) { + return false; + } + if (builtin_attr->builtin == core::BuiltinValue::kPosition) { + has_position = true; + } + return true; + }, + [&](const ast::InterpolateAttribute* interpolate) { + interpolate_attribute = interpolate; + return InterpolateAttribute(interpolate, member->Type(), stage); + }, + [&](const ast::StructMemberSizeAttribute*) { + if (!member->Type()->HasCreationFixedFootprint()) { + AddError(attr->source) + << style::Attribute("@size") + << " can only be applied to members where the member's type size can " + "be fully determined at shader creation time"; + return false; + } + return true; + }, + [&](Default) { return true; }); + if (!ok) { + return false; + } + } + + if (invariant_attribute && !has_position) { + AddError(invariant_attribute->source) + << style::Attribute("@invariant") << " must be applied to a position builtin"; + return false; + } + + if (blend_src_attribute) { + if (member->Attributes().location.value_or(1) != 0) { + AddError(blend_src_attribute->source) + << style::Attribute("@blend_src") << " can only be used with " + << style::Attribute("@location") << style::Code("(", style::Literal("0"), ")"); + return false; + } + + if (first_blend_src == nullptr) { + first_blend_src = blend_src_attribute; + first_blend_src_type = member->Type(); + } else if (!first_blend_src_type->Equals(*member->Type())) { + AddError(blend_src_attribute->source) + << "All the outputs with " << style::Attribute("@blend_src") + << " must have same type"; + return false; + } + + TINT_ASSERT(member->Attributes().blend_src.has_value() && + *member->Attributes().blend_src <= 1u); + uint32_t blend_src = *member->Attributes().blend_src; + blend_src_appearance_mask.set(blend_src); + } else if (location_attribute) { + first_location_without_blend_src = location_attribute; + } + + if (first_blend_src && first_location_without_blend_src) { + AddError(member->Declaration()->source) + << style::Attribute("@blend_src") << " and " << style::Attribute("@location") + << " are used on one member while another member with " + << style::Attribute("@location") << " doesn't use " + << style::Attribute("@blend_src"); + return false; + } + + if (interpolate_attribute && !location_attribute) { + AddError(interpolate_attribute->source) + << style::Attribute("@interpolate") << " can only be used with " + << style::Attribute("@location"); + return false; + } + + // Ensure all locations and optional blend_src pairs are unique + if (location_attribute) { + uint32_t location = member->Attributes().location.value(); + std::optional blend_src = member->Attributes().blend_src; + + if (!locations_and_blend_srcs.Add(std::make_pair(location, blend_src))) { + auto& err = AddError(location_attribute->source) + << style::Attribute("@location") + << style::Code("(", style::Literal(location), ")"); + if (blend_src) { + err << style::Attribute(" @blend_src") + << style::Code("(", style::Literal(blend_src.value()), ")"); + } + err << " appears multiple times"; + return false; + } + } + + if (color_attribute) { + uint32_t color = member->Attributes().color.value(); + if (!colors.Add(color)) { + AddError(color_attribute->source) + << style::Attribute("@color") << style::Code("(", style::Literal(color), ")") + << " appears multiple times"; + return false; + } + } + } + + if (first_blend_src != nullptr && !blend_src_appearance_mask.all()) { + for (uint32_t i = 0; i < blend_src_appearance_mask.size(); ++i) { + if (!blend_src_appearance_mask.test(i)) { + AddError(first_blend_src->source) + << style::Attribute("@blend_src") << style::Code("(", style::Literal(i), ")") + << " is missing when " << style::Attribute("@blend_src") << " is used"; + } + } + return false; + } + + return true; +} + +bool Validator::LocationAttribute(const ast::LocationAttribute* attr, + const core::type::Type* type, + ast::PipelineStage stage, + const Source& source) const { + if (stage == ast::PipelineStage::kCompute) { + AddError(attr->source) << style::Attribute("@", attr->Name()) + << " cannot be used by compute shaders"; + return false; + } + + if (!type->IsNumericScalarOrVector()) { + std::string invalid_type = sem_.TypeNameOf(type); + AddError(source) << "cannot apply " << style::Attribute("@location") + << " to declaration of type " << style::Type(invalid_type); + AddNote(attr->source) + << style::Attribute("@location") + << " must only be applied to declarations of numeric scalar or numeric vector type"; + return false; + } + + return true; +} + +bool Validator::ColorAttribute(const ast::ColorAttribute* attr, + const core::type::Type* type, + ast::PipelineStage stage, + const Source& source, + const std::optional is_input) const { + if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumExperimentalFramebufferFetch)) { + AddError(attr->source) << "use of " << style::Attribute("@color") + << " requires enabling extension " + << style::Code("chromium_experimental_framebuffer_fetch"); + return false; + } + + bool is_stage_non_fragment = + stage != ast::PipelineStage::kNone && stage != ast::PipelineStage::kFragment; + bool is_output = !is_input.value_or(true); + if (is_stage_non_fragment || is_output) { + AddError(attr->source) << style::Attribute("@color") + << " can only be used for fragment shader input"; + return false; + } + + if (!type->IsNumericScalarOrVector()) { + std::string invalid_type = sem_.TypeNameOf(type); + AddError(source) << "cannot apply " << style::Attribute("@color") + << " to declaration of type " << style::Type(invalid_type); + AddNote(attr->source) + << style::Attribute("@color") + << " must only be applied to declarations of numeric scalar or numeric vector type"; + return false; + } + + return true; +} + +bool Validator::BlendSrcAttribute(const ast::BlendSrcAttribute* attr, + ast::PipelineStage stage, + const std::optional is_input) const { + if (!enabled_extensions_.Contains(wgsl::Extension::kDualSourceBlending)) { + AddError(attr->source) << "use of " << style::Attribute("@blend_src") + << " requires enabling extension " + << style::Code("dual_source_blending"); + return false; + } + + bool is_stage_non_fragment = + stage != ast::PipelineStage::kNone && stage != ast::PipelineStage::kFragment; + bool is_input_param = is_input.value_or(false); + if (is_stage_non_fragment || is_input_param) { + AddError(attr->source) << style::Attribute("@", attr->Name()) + << " can only be used for fragment shader output"; + return false; + } + + return true; +} + +bool Validator::Return(const ast::ReturnStatement* ret, + const core::type::Type* func_type, + const core::type::Type* ret_type, + sem::Statement* current_statement) const { + if (func_type->UnwrapRef() != ret_type) { + AddError(ret->source) + << "return statement type must match its function return type, returned " + << style::Type(sem_.TypeNameOf(ret_type)) << ", expected " + << style::Type(sem_.TypeNameOf(func_type)); + return false; + } + + auto* sem = sem_.Get(ret); + if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ false, /* stop_at_switch */ false, + current_statement)) { + AddError(ret->source) << "continuing blocks must not contain a return statement"; + if (continuing != sem->Declaration() && continuing != sem->Parent()->Declaration()) { + AddNote(continuing->source) << "see continuing block here"; + } + return false; + } + + return true; +} + +bool Validator::SwitchStatement(const ast::SwitchStatement* s) { + if (s->body.Length() > kMaxSwitchCaseSelectors) { + AddError(s->source) << "switch statement has " << s->body.Length() + << " case selectors, max is " << kMaxSwitchCaseSelectors; + return false; + } + + auto* cond_ty = sem_.TypeOf(s->condition); + if (!cond_ty->IsIntegerScalar()) { + AddError(s->condition->source) + << "switch statement selector expression must be of a scalar integer type"; + return false; + } + + const sem::CaseSelector* default_selector = nullptr; + Hashmap selectors; + + for (auto* case_stmt : s->body) { + auto* case_sem = sem_.Get(case_stmt); + for (auto* selector : case_sem->Selectors()) { + if (selector->IsDefault()) { + if (default_selector != nullptr) { + // More than one default clause + AddError(selector->Declaration()->source) + << "switch statement must have exactly one default clause"; + + AddNote(default_selector->Declaration()->source) << "previous default case"; + return false; + } + default_selector = selector; + continue; + } + + auto* decl_ty = selector->Value()->Type(); + if (cond_ty != decl_ty) { + AddError(selector->Declaration()->source) + << "the case selector values must have the same type as the " + "selector expression."; + return false; + } + + auto value = selector->Value()->ValueAs(); + if (auto added = selectors.Add(value, selector->Declaration()->source); !added) { + auto& err = AddError(selector->Declaration()->source) + << "duplicate switch case " << style::Literal; + if (decl_ty->IsAnyOf()) { + err << i32(value); + } else { + err << value; + } + AddNote(added.value) << "previous case declared here"; + return false; + } + } + } + + if (default_selector == nullptr) { + // No default clause + AddError(s->source) << "switch statement must have a default clause"; + return false; + } + + return true; +} + +bool Validator::Assignment(const ast::Statement* a, const core::type::Type* rhs_ty) const { + const ast::Expression* lhs; + const ast::Expression* rhs; + if (auto* assign = a->As()) { + lhs = assign->lhs; + rhs = assign->rhs; + } else if (auto* compound = a->As()) { + lhs = compound->lhs; + rhs = compound->rhs; + if (!BinaryExpression(a, compound->op, sem_.GetVal(lhs), sem_.GetVal(rhs))) { + return false; + } + } else { + TINT_ICE() << "invalid assignment statement"; + } + + if (lhs->Is()) { + // https://www.w3.org/TR/WGSL/#phony-assignment-section + auto* ty = rhs_ty->UnwrapRef(); + if (!ty->IsConstructible() && + !ty->IsAnyOf()) { + AddError(rhs->source) + << "cannot assign " << style::Type(sem_.TypeNameOf(rhs_ty)) << " to " + << style::Code("_") << ". " << style::Code("_") + << " can only be assigned a constructible, pointer, texture or sampler type"; + return false; + } + return true; // RHS can be anything. + } + + // https://gpuweb.github.io/gpuweb/wgsl/#assignment-statement + auto const* lhs_sem = sem_.GetVal(lhs); + auto const* lhs_ty = lhs_sem->Type(); + + auto* lhs_ref = lhs_ty->As(); + if (!lhs_ref) { + // LHS is not a reference, so it has no storage. + AddError(lhs->source) << "cannot assign to " << sem_.Describe(lhs_sem); + + auto* expr = lhs; + while (expr) { + expr = Switch( + expr, // + [&](const ast::AccessorExpression* e) { return e->object; }, + [&](const ast::IdentifierExpression* i) { + if (auto user = sem_.Get(i)) { + Switch( + user->Variable()->Declaration(), // + [&](const ast::Let* v) { + AddNote(user->Declaration()->source) + << style::Variable("let") << " variables are immutable"; + sem_.NoteDeclarationSource(v); + }, + [&](const ast::Const* v) { + AddNote(user->Declaration()->source) + << style::Variable("const") << " variables are immutable"; + sem_.NoteDeclarationSource(v); + }, + [&](const ast::Override* v) { + AddNote(user->Declaration()->source) + << style::Variable("override") << " variables are immutable"; + sem_.NoteDeclarationSource(v); + }, + [&](const ast::Parameter* v) { + AddNote(user->Declaration()->source) << "parameters are immutable"; + sem_.NoteDeclarationSource(v); + }); + } + return nullptr; + }); + } + + return false; + } + + auto* storage_ty = lhs_ref->StoreType(); + auto* value_type = rhs_ty->UnwrapRef(); // Implicit load of RHS + + // Value type has to match storage type + if (storage_ty != value_type) { + AddError(a->source) << "cannot assign " << style::Type(sem_.TypeNameOf(rhs_ty)) << " to " + << style::Type(sem_.TypeNameOf(lhs_ty)); + return false; + } + if (!storage_ty->IsConstructible()) { + AddError(a->source) << "storage type of assignment must be constructible"; + return false; + } + if (lhs_ref->Access() == core::Access::kRead) { + AddError(a->source) << "cannot store into a read-only type " + << style::Type(sem_.RawTypeNameOf(lhs_ty)); + return false; + } + return true; +} + +bool Validator::IncrementDecrementStatement(const ast::IncrementDecrementStatement* inc) const { + const ast::Expression* lhs = inc->lhs; + + // https://gpuweb.github.io/gpuweb/wgsl/#increment-decrement + + if (auto* var_user = sem_.Get(lhs)) { + auto* v = var_user->Variable()->Declaration(); + bool errored = Switch( + v, // + [&](const ast::Parameter*) { + AddError(lhs->source) << "cannot modify function parameter"; + return true; + }, + [&](const ast::Let*) { + AddError(lhs->source) << "cannot modify " << style::Keyword("let"); + return true; + }, + [&](const ast::Override*) { + AddError(lhs->source) << "cannot modify " << style::Keyword("override"); + return true; + }); + if (errored) { + sem_.NoteDeclarationSource(v); + return false; + } + } + + auto const* lhs_ty = sem_.TypeOf(lhs); + auto* lhs_ref = lhs_ty->As(); + if (!lhs_ref) { + // LHS is not a reference, so it has no storage. + AddError(lhs->source) << "cannot modify value of type " + << style::Type(sem_.TypeNameOf(lhs_ty)); + return false; + } + + if (!lhs_ref->StoreType()->IsIntegerScalar()) { + const std::string kind = inc->increment ? "increment" : "decrement"; + AddError(lhs->source) << kind << " statement can only be applied to an integer scalar"; + return false; + } + + if (lhs_ref->Access() == core::Access::kRead) { + AddError(inc->source) << "cannot modify read-only type " + << style::Type(sem_.RawTypeNameOf(lhs_ty)); + return false; + } + return true; +} + +bool Validator::NoDuplicateAttributes(VectorRef attributes) const { + Hashmap seen; + tint::Vector diagnostic_controls; + for (auto* d : attributes) { + if (auto* diag = d->As()) { + // Allow duplicate diagnostic attributes, and check for conflicts later. + diagnostic_controls.Push(&diag->control); + } else { + auto added = seen.Add(&d->TypeInfo(), d->source); + if (!added) { + AddError(d->source) << "duplicate " << d->Name() << " attribute"; + AddNote(added.value) << "first attribute declared here"; + return false; + } + } + } + return DiagnosticControls(diagnostic_controls, "attribute", DiagnosticDuplicates::kDenied); +} + +bool Validator::DiagnosticControls(VectorRef controls, + const char* use, + DiagnosticDuplicates allow_duplicates) const { + // Make sure that no two diagnostic controls conflict. + // They conflict if the rule name is the same and the severity is different. + Hashmap, const ast::DiagnosticControl*, 8> diagnostics; + for (auto* dc : controls) { + auto category = dc->rule_name->category ? dc->rule_name->category->symbol : Symbol(); + auto name = dc->rule_name->name->symbol; + + auto diag_added = diagnostics.Add(std::make_pair(category, name), dc); + if (!diag_added) { + if (diag_added.value->severity != dc->severity) { + AddError(dc->rule_name->source) << "conflicting diagnostic " << use; + AddNote(diag_added.value->rule_name->source) + << "severity of " << style::Code(dc->rule_name->String()) << " set to " + << style::Code(dc->severity) << " here"; + return false; + } else if (allow_duplicates == DiagnosticDuplicates::kDenied) { + AddError(dc->rule_name->source) << "duplicate diagnostic " << use; + AddNote(diag_added.value->rule_name->source) << "first " << use << " declared here"; + return false; + } + } + } + return true; +} + +bool Validator::IsArrayWithOverrideCount(const core::type::Type* ty) const { + if (auto* arr = ty->UnwrapRef()->As()) { + if (arr->Count()->IsAnyOf()) { + return true; + } + } + return false; +} + +void Validator::RaiseArrayWithOverrideCountError(const Source& source) const { + AddError(source) << style::Type("array") << " with an " << style::Keyword("override") + << " element count can only be used as the store type of a " + << style::Keyword("var") << style::Code("<", style::Enum("workgroup"), ">"); +} + +std::string Validator::VectorPretty(uint32_t size, const core::type::Type* element_type) const { + core::type::Vector vec_type(element_type, size); + return vec_type.FriendlyName(); +} + +bool Validator::CheckTypeAccessAddressSpace(const core::type::Type* store_ty, + core::Access access, + core::AddressSpace address_space, + const Source& source) const { + if (!AddressSpaceLayout(store_ty, address_space, source)) { + return false; + } + + switch (address_space) { + case core::AddressSpace::kPixelLocal: + if (auto* str = store_ty->As()) { + for (auto* member : str->Members()) { + using Allowed = std::tuple; + if (DAWN_UNLIKELY(!member->Type()->TypeInfo().IsAnyOfTuple())) { + AddError(member->Declaration()->source) + << style::Keyword("struct") << " members used in the " + << style::Enum("pixel_local") + << " address space can only be of the type " << style::Type("i32") + << ", " << style::Type("u32") << " or " << style::Type("f32"); + AddNote(source) << style::Keyword("struct ") + << style::Type(str->Name().Name()) << " used in the " + << style::Enum("pixel_local") << " address space here"; + return false; + } + } + } else if (DAWN_UNLIKELY(!store_ty->TypeInfo().Is())) { + AddError(source) << style::Enum("pixel_local") + << " variable only support struct storage types"; + return false; + } + break; + case core::AddressSpace::kImmediate: + if (DAWN_UNLIKELY(allowed_features_.features.count( + wgsl::LanguageFeature::kImmediateAddressSpace) == 0u)) { + AddError(source) << "use of variable address space " << style::Enum("immediate") + << " requires the immediate_address_space language feature, which " + "is not allowed in the current environment"; + return false; + } + break; + case core::AddressSpace::kStorage: + if (DAWN_UNLIKELY(access == core::Access::kWrite)) { + // The access mode for the storage address space can only be 'read' or 'read_write'. + AddError(source) << "access mode " << style::Enum("write") + << " is not valid for the " << style::Enum("storage") + << " address space"; + return false; + } + break; + default: + break; + } + + auto atomic_error = [&] { + StyledText err; + if (address_space != core::AddressSpace::kStorage && + address_space != core::AddressSpace::kWorkgroup) { + AddError(source) << style::Type("atomic") << " variables must have " + << style::Enum("storage") << " or " << style::Enum("workgroup") + << " address space"; + return true; + } + if (address_space == core::AddressSpace::kStorage && access != core::Access::kReadWrite) { + AddError(source) << "atomic variables in " << style::Enum("storage") + << " address space must have " << style::Enum("read_write") + << " access mode"; + return true; + } + return false; + }; + + if (store_ty->Is() && !(address_space == core::AddressSpace::kStorage || + address_space == core::AddressSpace::kUniform || + address_space == core::AddressSpace::kWorkgroup)) { + AddError(source) << style::Type("buffer") << " variables must have " + << style::Enum("storage") << ", " << style::Enum("uniform") << ", or " + << style::Enum("workgroup") << " address space"; + return false; + } + + auto check_sub_atomics = [&] { + if (auto atomic_use = atomic_composite_info_.Get(store_ty)) { + if (DAWN_UNLIKELY(atomic_error())) { + AddNote(**atomic_use) + << "atomic sub-type of " << style::Type(sem_.TypeNameOf(store_ty)) + << " is declared here"; + return false; + } + } + return true; + }; + + return Switch( + store_ty, // + [&](const core::type::Atomic*) { + if (DAWN_UNLIKELY(atomic_error())) { + return false; + } + return true; + }, + [&](const core::type::Struct*) { return check_sub_atomics(); }, // + [&](const sem::Array*) { return check_sub_atomics(); }, // + [&](Default) { return true; }); +} + +bool Validator::CheckNoMultipleModuleScopeVarsOfAddressSpace(sem::Function* entry_point, + core::AddressSpace space) const { + // State checked and modified by check() so that it remembers previously seen immediate + // variables for an entry-point. + const sem::Variable* seen_var = nullptr; + const sem::Function* seen_func = nullptr; + + auto check = [&](const sem::Function* func, const sem::Function* ep) { + for (auto* var : func->DirectlyReferencedGlobals()) { + if (var->AddressSpace() != space || var == seen_var) { + continue; + } + + if (seen_var == nullptr) { + seen_var = var; + seen_func = func; + continue; + } + + AddError(ep->Declaration()->source) + << "entry point " << style::Function(ep->Declaration()->name->symbol.NameView()) + << " uses two different " << style::Enum(space) << " variables."; + AddNote(var->Declaration()->source) + << "first " << style::Enum(space) << " variable declaration is here"; + if (func != ep) { + TraverseCallChain(ep, func, [&](const sem::Function* f) { + AddNote(f->Declaration()->source) + << "called by function " + << style::Function(f->Declaration()->name->symbol.NameView()); + }); + AddNote(ep->Declaration()->source) + << "called by entry point " + << style::Function(ep->Declaration()->name->symbol.NameView()); + } + AddNote(seen_var->Declaration()->source) + << "second " << style::Enum(space) << " variable declaration is here"; + if (seen_func != ep) { + TraverseCallChain(ep, seen_func, [&](const sem::Function* f) { + AddNote(f->Declaration()->source) + << "called by function " + << style::Function(f->Declaration()->name->symbol.NameView()); + }); + AddNote(ep->Declaration()->source) + << "called by entry point " + << style::Function(ep->Declaration()->name->symbol.NameView()); + } + return false; + } + + return true; + }; + + if (!check(entry_point, entry_point)) { + return false; + } + for (auto* func : entry_point->TransitivelyCalledFunctions()) { + if (!check(func, entry_point)) { + return false; + } + } + return true; +} + +} // namespace tint::resolver diff --git a/3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.h b/3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.h new file mode 100644 index 000000000..0cf5410bc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/resolver/validator.h @@ -0,0 +1,679 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_RESOLVER_VALIDATOR_H_ +#define SRC_TINT_LANG_WGSL_RESOLVER_VALIDATOR_H_ + +#include +#include +#include +#include + +#include "src/tint/lang/core/evaluation_stage.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/wgsl/allowed_features.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/pipeline_stage.h" +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/resolver/sem_helper.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/scope_stack.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/diagnostic/source.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/text/styled_text.h" + +// Forward declarations +namespace tint::ast { +class IndexAccessorExpression; +class BinaryExpression; +class BitcastExpression; +class CallExpression; +class CallStatement; +class CaseStatement; +class ForLoopStatement; +class Function; +class IdentifierExpression; +class LoopStatement; +class MemberAccessorExpression; +class ReturnStatement; +class SwitchStatement; +class UnaryOpExpression; +class Variable; +class WhileStatement; +} // namespace tint::ast +namespace tint::sem { +class Array; +class BlockStatement; +class BreakIfStatement; +class BuiltinFn; +class Call; +class CaseStatement; +class ForLoopStatement; +class IfStatement; +class LoopStatement; +class Materialize; +class Statement; +class SwitchStatement; +class WhileStatement; +} // namespace tint::sem +namespace tint::core::type { +class Atomic; +} // namespace tint::core::type + +namespace tint::resolver { + +/// TypeAndAddressSpace is a pair of type and address space +struct TypeAndAddressSpace { + /// The type + const core::type::Type* type; + /// The address space + core::AddressSpace address_space; + + /// Equality operator + /// @param other the other TypeAndAddressSpace to compare this TypeAndAddressSpace to + /// @returns true if the type and address space of this TypeAndAddressSpace is equal to @p other + bool operator==(const TypeAndAddressSpace& other) const { + return type == other.type && address_space == other.address_space; + } + + /// @returns the hash value of this object + tint::HashCode HashCode() const { return Hash(type, address_space); } +}; + +/// DiagnosticFilterStack is a scoped stack of diagnostic filters. +using DiagnosticFilterStack = ScopeStack; + +/// Enumerator of duplication behavior for diagnostics. +enum class DiagnosticDuplicates : uint8_t { + // Diagnostic duplicates are allowed. + kAllowed, + // Diagnostic duplicates are not allowed. + kDenied, +}; + +/// Validation logic for various ast nodes. The validations in general should +/// be shallow and depend on the resolver to call on children. The validations +/// also assume that sem changes have already been made. The validation checks +/// should not alter the AST or SEM trees. +class Validator { + public: + /// Constructor + /// @param builder the program builder + /// @param helper the SEM helper to validate with + /// @param enabled_extensions all the extensions declared in current module + /// @param allowed_features the allowed extensions and features + /// @param atomic_composite_info atomic composite info of the module + /// @param valid_type_storage_layouts a set of validated type layouts by address space + Validator(ProgramBuilder* builder, + SemHelper& helper, + const wgsl::Extensions& enabled_extensions, + const wgsl::AllowedFeatures& allowed_features, + const Hashmap& atomic_composite_info, + Hashset& valid_type_storage_layouts); + ~Validator(); + + /// @returns an error diagnostic + /// @param source the error source + diag::Diagnostic& AddError(const Source& source) const; + + /// @returns an warning diagnostic + /// @param source the warning source + diag::Diagnostic& AddWarning(const Source& source) const; + + /// @returns an note diagnostic + /// @param source the note source + diag::Diagnostic& AddNote(const Source& source) const; + + /// Adds a diagnostic with current severity for the given rule. + /// @param rule the diagnostic trigger rule + /// @param source the diagnostic source + /// @returns the diagnostic, if the diagnostic level isn't disabled + diag::Diagnostic* MaybeAddDiagnostic(wgsl::DiagnosticRule rule, const Source& source) const; + + /// @returns the diagnostic filter stack + DiagnosticFilterStack& DiagnosticFilters() { return diagnostic_filters_; } + + /// @param type the given type + /// @returns true if the given type is a plain type + bool IsPlain(const core::type::Type* type) const; + + /// @param type the given type + /// @returns true if the given type is storable + bool IsStorable(const core::type::Type* type) const; + + /// Validates the enabled extensions + /// @param enables the extension enables + /// @returns true on success, false otherwise. + bool Enables(VectorRef enables) const; + + /// Validates pipeline stages + /// @param entry_points the entry points to the module + /// @returns true on success, false otherwise. + bool PipelineStages(VectorRef entry_points) const; + + /// Validates usages of module-scope vars. + /// @note Must only be called after all functions have been resolved. + /// @param entry_points the entry points to the module + /// @returns true on success, false otherwise. + bool ModuleScopeVarUsages(VectorRef entry_points) const; + + /// Validates aliases + /// @param alias the alias to validate + /// @returns true on success, false otherwise. + bool Alias(const ast::Alias* alias) const; + + /// Validates the array + /// @param arr the array to validate + /// @param el_source the source of the array element, or the array if the array does not have a + /// locally-declared element AST node. + /// @returns true on success, false otherwise. + bool Array(const sem::Array* arr, const Source& el_source) const; + + /// Validates an atomic type + /// @param a the atomic ast node + /// @param s the atomic sem node + /// @returns true on success, false otherwise. + bool Atomic(const ast::TemplatedIdentifier* a, const core::type::Atomic* s) const; + + /// Validates a pointer type + /// @param a the pointer ast node + /// @param s the pointer sem node + /// @returns true on success, false otherwise. + bool Pointer(const ast::TemplatedIdentifier* a, const core::type::Pointer* s) const; + + /// Validates an assignment + /// @param a the assignment statement + /// @param rhs_ty the type of the right hand side + /// @returns true on success, false otherwise. + bool Assignment(const ast::Statement* a, const core::type::Type* rhs_ty) const; + + /// Validates a binary expression + /// @param node the ast binary expression or compound assignment node + /// @param op the binary operator + /// @param lhs the left hand side sem node + /// @param rhs the right hand side sem node + /// @returns true on success, false otherwise. + bool BinaryExpression(const ast::Node* node, + const core::BinaryOp op, + const tint::sem::ValueExpression* lhs, + const tint::sem::ValueExpression* rhs) const; + + /// Validates a break statement + /// @param stmt the break statement to validate + /// @param current_statement the current statement being resolved + /// @returns true on success, false otherwise. + bool BreakStatement(const sem::Statement* stmt, sem::Statement* current_statement) const; + + /// Validates a builtin attribute + /// @param attr the attribute to validate + /// @param storage_type the attribute storage type + /// @param stage the current pipeline stage + /// @param is_input true if this is an input attribute + /// @returns true on success, false otherwise. + bool BuiltinAttribute(const ast::BuiltinAttribute* attr, + const core::type::Type* storage_type, + ast::PipelineStage stage, + const bool is_input) const; + + /// Validates a continue statement + /// @param stmt the continue statement to validate + /// @param current_statement the current statement being resolved + /// @returns true on success, false otherwise + bool ContinueStatement(const sem::Statement* stmt, sem::Statement* current_statement) const; + + /// Validates a call + /// @param call the call + /// @param current_statement the current statement being resolved + /// @returns true on success, false otherwise + bool Call(const sem::Call* call, sem::Statement* current_statement) const; + + /// Validates an entry point + /// @param func the entry point function to validate + /// @param stage the pipeline stage for the entry point + /// @returns true on success, false otherwise + bool EntryPoint(const sem::Function* func, ast::PipelineStage stage) const; + + /// Validates that the expression must not be evaluated any later than @p latest_stage + /// @param expr the expression to check + /// @param latest_stage the latest evaluation stage that the expression can be evaluated + /// @param constraint the 'thing' that is imposing the contraint. e.g. "var declaration" + /// @returns true if @p expr is evaluated in or before @p latest_stage, false otherwise + bool EvaluationStage(const sem::ValueExpression* expr, + core::EvaluationStage latest_stage, + std::string_view constraint) const; + + /// Validates a for loop + /// @param stmt the for loop statement to validate + /// @returns true on success, false otherwise + bool ForLoopStatement(const sem::ForLoopStatement* stmt) const; + + /// Validates a while loop + /// @param stmt the while statement to validate + /// @returns true on success, false otherwise + bool WhileStatement(const sem::WhileStatement* stmt) const; + + /// Validates a function + /// @param func the function to validate + /// @param stage the current pipeline stage + /// @returns true on success, false otherwise. + bool Function(const sem::Function* func, ast::PipelineStage stage) const; + + /// Validates a function call + /// @param call the function call to validate + /// @param current_statement the current statement being resolved + /// @returns true on success, false otherwise + bool FunctionCall(const sem::Call* call, sem::Statement* current_statement) const; + + /// Validates a global variable + /// @param var the global variable to validate + /// @param override_id the set of override ids in the module + /// @returns true on success, false otherwise + bool GlobalVariable(const sem::GlobalVariable* var, + const Hashmap& override_id) const; + + /// Validates a break-if statement + /// @param stmt the statement to validate + /// @param current_statement the current statement being resolved + /// @returns true on success, false otherwise + bool BreakIfStatement(const sem::BreakIfStatement* stmt, + sem::Statement* current_statement) const; + + /// Validates an if statement + /// @param stmt the statement to validate + /// @returns true on success, false otherwise + bool IfStatement(const sem::IfStatement* stmt) const; + + /// Validates an increment or decrement statement + /// @param stmt the statement to validate + /// @returns true on success, false otherwise + bool IncrementDecrementStatement(const ast::IncrementDecrementStatement* stmt) const; + + /// Validates an interpolate attribute + /// @param attr the attribute to validate + /// @param storage_type the storage type of the attached variable + /// @param stage the current pipeline stage + /// @returns true on success, false otherwise + bool InterpolateAttribute(const ast::InterpolateAttribute* attr, + const core::type::Type* storage_type, + const ast::PipelineStage stage) const; + + /// Validates an invariant attribute + /// @param attr the attribute to validate + /// @param stage the current pipeline stage + /// @returns true on success, false otherwise + bool InvariantAttribute(const ast::InvariantAttribute* attr, + const ast::PipelineStage stage) const; + + /// Validates a builtin call + /// @param call the builtin call to validate + /// @returns true on success, false otherwise. + bool BuiltinCall(const sem::Call* call) const; + + /// Validates a local variable + /// @param v the variable to validate + /// @returns true on success, false otherwise. + bool LocalVariable(const sem::Variable* v) const; + + /// Validates a location attribute + /// @param attr the attribute to validate + /// @param type the variable type + /// @param stage the current pipeline stage + /// @param source the source of declaration using the attribute + /// @returns true on success, false otherwise. + bool LocationAttribute(const ast::LocationAttribute* attr, + const core::type::Type* type, + const ast::PipelineStage stage, + const Source& source) const; + + /// Validates a color attribute + /// @param attr the color attribute to validate + /// @param type the variable type + /// @param stage the current pipeline stage + /// @param source the source of declaration using the attribute + /// @param is_input true if is an input variable, false if output variable, std::nullopt is + /// unknown. + /// @returns true on success, false otherwise. + bool ColorAttribute(const ast::ColorAttribute* attr, + const core::type::Type* type, + ast::PipelineStage stage, + const Source& source, + const std::optional is_input = std::nullopt) const; + + /// Validates a blend_src attribute + /// @param blend_src_attr the blend_src attribute to validate + /// @param stage the current pipeline stage + /// @param is_input true if is an input variable, false if output variable, std::nullopt is + /// unknown. + /// @returns true on success, false otherwise. + bool BlendSrcAttribute(const ast::BlendSrcAttribute* blend_src_attr, + ast::PipelineStage stage, + const std::optional is_input = std::nullopt) const; + + /// Validates a loop statement + /// @param stmt the loop statement + /// @returns true on success, false otherwise. + bool LoopStatement(const sem::LoopStatement* stmt) const; + + /// Validates a materialize of an abstract numeric value from the type `from` to the type `to`. + /// @param to the target type + /// @param from the abstract numeric type + /// @param source the source of the materialization + /// @returns true on success, false otherwise + bool Materialize(const core::type::Type* to, + const core::type::Type* from, + const Source& source) const; + + /// Validates a matrix + /// @param el_ty the matrix element type to validate + /// @param source the source of the matrix + /// @returns true on success, false otherwise + bool Matrix(const core::type::Type* el_ty, const Source& source) const; + + /// Validates a function parameter + /// @param var the variable to validate + /// @returns true on success, false otherwise + bool Parameter(const sem::Variable* var) const; + + /// Validates a return + /// @param ret the return statement to validate + /// @param func_type the return type of the curreunt function + /// @param ret_type the return type + /// @param current_statement the current statement being resolved + /// @returns true on success, false otherwise + bool Return(const ast::ReturnStatement* ret, + const core::type::Type* func_type, + const core::type::Type* ret_type, + sem::Statement* current_statement) const; + + /// Validates a list of statements + /// @param stmts the statements to validate + /// @returns true on success, false otherwise + bool Statements(VectorRef stmts) const; + + /// Validates a storage texture + /// @param t the texture to validate + /// @param source the source of the texture + /// @returns true on success, false otherwise + bool StorageTexture(const core::type::StorageTexture* t, const Source& source) const; + + /// Validates a texel buffer + /// @param t the texel buffer to validate + /// @param source the source of the texel buffer + /// @returns true on success, false otherwise + bool TexelBuffer(const core::type::TexelBuffer* t, const Source& source) const; + + /// Validates a sampled texture + /// @param t the texture to validate + /// @param source the source of the texture + /// @returns true on success, false otherwise + bool SampledTexture(const core::type::SampledTexture* t, const Source& source) const; + + /// Validates a multisampled texture + /// @param t the texture to validate + /// @param source the source of the texture + /// @returns true on success, false otherwise + bool MultisampledTexture(const core::type::MultisampledTexture* t, const Source& source) const; + + /// Validates a input attachment + /// @param t the input attachment to validate + /// @param source the source of the input attachment + /// @returns true on success, false otherwise + bool InputAttachment(const core::type::InputAttachment* t, const Source& source) const; + + /// Validates a input attachment index attribute + /// @param attr the input attachment index attribute to validate + /// @param type the variable type + /// @param source the source of declaration using the attribute + /// @returns true on success, false otherwise. + bool InputAttachmentIndexAttribute(const ast::InputAttachmentIndexAttribute* attr, + const core::type::Type* type, + const Source& source) const; + + /// Validates a binding array type + /// @param t the binding array to validate + /// @param source the source of the binding array type + /// @returns true on success, false otherwise + bool BindingArray(const core::type::BindingArray* t, const Source& source) const; + + /// Validates a subgroup matrix type + /// @param t the subgroup matrix type to validate + /// @param source the source of the subgroup matrix type + /// @returns true on success, false otherwise + bool SubgroupMatrix(const core::type::SubgroupMatrix* t, const Source& source) const; + + /// Validates buffer type + /// @param t the buffer type to validate + /// @param source the source of the buffer type + /// @returns true on success, false otherwise + bool Buffer(const core::type::Buffer* t, const Source& source) const; + + /// Validates a structure + /// @param str the structure to validate + /// @param stage the current pipeline stage + /// @returns true on success, false otherwise. + bool Structure(const sem::Struct* str, ast::PipelineStage stage) const; + + /// Validates a structure initializer + /// @param ctor the call expression to validate + /// @param struct_type the type of the structure + /// @returns true on success, false otherwise + bool StructureInitializer(const ast::CallExpression* ctor, + const core::type::Struct* struct_type) const; + + /// Validates a switch statement + /// @param s the switch to validate + /// @returns true on success, false otherwise + bool SwitchStatement(const ast::SwitchStatement* s); + + /// Validates a 'var' variable declaration + /// @param v the variable to validate + /// @returns true on success, false otherwise. + bool Var(const sem::Variable* v) const; + + /// Validates a 'let' variable declaration + /// @param v the variable to validate + /// @returns true on success, false otherwise. + bool Let(const sem::Variable* v) const; + + /// Validates a 'override' variable declaration + /// @param v the variable to validate + /// @param override_id the set of override ids in the module + /// @returns true on success, false otherwise. + bool Override(const sem::GlobalVariable* v, + const Hashmap& override_id) const; + + /// Validates a 'const' variable declaration + /// @param v the variable to validate + /// @returns true on success, false otherwise. + bool Const(const sem::Variable* v) const; + + /// Validates a variable initializer + /// @param v the variable to validate + /// @param storage_type the type of the storage + /// @param initializer the RHS initializer expression + /// @returns true on succes, false otherwise + bool VariableInitializer(const ast::Variable* v, + const core::type::Type* storage_type, + const sem::ValueExpression* initializer) const; + + /// Validates a vector + /// @param el_ty the vector element type to validate + /// @param source the source of the vector + /// @returns true on success, false otherwise + bool Vector(const core::type::Type* el_ty, const Source& source) const; + + /// Validates an array constructor + /// @param ctor the call expression to validate + /// @param arr_type the type of the array + /// @returns true on success, false otherwise + bool ArrayConstructor(const ast::CallExpression* ctor, const sem::Array* arr_type) const; + + /// Validates a subgroup matrix constructor + /// @param ctor the call expression to validate + /// @param subgroup_matrix_type the type of the subgroup matrix + /// @param signature the construct signature to validate against + /// @returns true on success, false otherwise + bool SubgroupMatrixConstructor(const ast::CallExpression* ctor, + const core::type::SubgroupMatrix* subgroup_matrix_type, + const sem::CallTarget* signature) const; + + /// Validates a subgroupShuffle builtin functions including Up,Down, and Xor. + /// @param fn the builtin call type + /// @param call the builtin call to validate + /// @returns true on success, false otherwise + bool SubgroupShuffleFunction(wgsl::BuiltinFn fn, const sem::Call* call) const; + + /// Validates a texture builtin function + /// @param call the builtin call to validate + /// @returns true on success, false otherwise + bool TextureBuiltinFn(const sem::Call* call) const; + + /// Validates a subgroupBroadcast builtin function + /// @param call the builtin call to validate + /// @returns true on success, false otherwise + bool SubgroupBroadcast(const sem::Call* call) const; + + /// Validates a quadBroadcast builtin function + /// @param call the builtin call to validate + /// @returns true on success, false otherwise + bool QuadBroadcast(const sem::Call* call) const; + + /// Validates a bufferView builtin function + /// @param call the builtin call to validate + /// @returns true on success, false otherwise + bool BufferView(const sem::Call* call) const; + + /// Validates an optional builtin function and its required extensions and language features. + /// @param call the builtin call to validate + /// @returns true on success, false otherwise + bool RequiredFeaturesForBuiltinFn(const sem::Call* call) const; + + /// Validates that 'f16' extension is enabled for f16 usage at @p source + /// @param source the source of the f16 usage + /// @returns true on success, false otherwise + bool CheckF16Enabled(const Source& source) const; + + /// Validates that 'chromium_experimental_subgroup_matrix' extension is enabled for i8 usage at + /// @p source + /// @param source the source of the i8 usage + /// @returns true on success, false otherwise + bool CheckI8Enabled(const Source& source) const; + + /// Validates that 'chromium_experimental_subgroup_matrix' extension is enabled for u8 usage at + /// @p source + /// @param source the source of the u8 usage + /// @returns true on success, false otherwise + bool CheckU8Enabled(const Source& source) const; + + /// Validates there are no duplicate attributes + /// @param attributes the list of attributes to validate + /// @returns true on success, false otherwise. + bool NoDuplicateAttributes(VectorRef attributes) const; + + /// Validates a set of diagnostic controls. + /// @param controls the diagnostic controls to validate + /// @param use the place where the controls are being used ("directive" or "attribute") + /// @param allow_duplicates if same name same severity diagnostics are allowed + /// @returns true on success, false otherwise. + bool DiagnosticControls(VectorRef controls, + const char* use, + DiagnosticDuplicates allow_duplicates) const; + + /// Validates a address space layout + /// @param type the type to validate + /// @param sc the address space + /// @param source the source of the type + /// @returns true on success, false otherwise + bool AddressSpaceLayout(const core::type::Type* type, + core::AddressSpace sc, + Source source) const; + + private: + /// @param ty the type to check + /// @returns true if @p ty is an array with an `override` expression element count, otherwise + /// false. + bool IsArrayWithOverrideCount(const core::type::Type* ty) const; + + /// Raises an error about an array type using an `override` expression element count, outside + /// the single allowed use of a `var`. + /// @param source the source for the error + void RaiseArrayWithOverrideCountError(const Source& source) const; + + /// Searches the current statement and up through parents of the current + /// statement looking for a loop or for-loop continuing statement. + /// @returns the closest continuing statement to the current statement that + /// (transitively) owns the current statement. + /// @param stop_at_loop if true then the function will return nullptr if a + /// loop or for-loop was found before the continuing. + /// @param stop_at_switch if true then the function will return nullptr if a switch was found + /// before continuing. + /// @param current_statement the current statement being resolved + const ast::Statement* ClosestContinuing(bool stop_at_loop, + bool stop_at_switch, + sem::Statement* current_statement) const; + + /// Returns a human-readable string representation of the vector type name + /// with the given parameters. + /// @param size the vector dimension + /// @param element_type scalar vector sub-element type + /// @return pretty string representation + std::string VectorPretty(uint32_t size, const core::type::Type* element_type) const; + + /// Raises an error if combination of @p store_ty, @p access and @p address_space are not valid + /// for a `var` or `ptr` declaration. + /// @param store_ty the store type of the var or pointer + /// @param access the var or pointer access + /// @param address_space the var or pointer address space + /// @param source the source for the error + /// @returns true on success, false if an error was raised. + bool CheckTypeAccessAddressSpace(const core::type::Type* store_ty, + core::Access access, + core::AddressSpace address_space, + const Source& source) const; + + /// Raises an error if the entry_point @p entry_point uses two or more module-scope 'var's with + /// the address space @p space. + /// @param entry_point the entry point + /// @param space the address space + /// @returns true if no duplicate uses were found or false if an error was raised. + bool CheckNoMultipleModuleScopeVarsOfAddressSpace(sem::Function* entry_point, + core::AddressSpace space) const; + + SymbolTable& symbols_; + diag::List& diagnostics_; + SemHelper& sem_; + DiagnosticFilterStack diagnostic_filters_; + const wgsl::Extensions& enabled_extensions_; + const wgsl::AllowedFeatures& allowed_features_; + const Hashmap& atomic_composite_info_; + Hashset& valid_type_storage_layouts_; +}; + +} // namespace tint::resolver + +#endif // SRC_TINT_LANG_WGSL_RESOLVER_VALIDATOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.cc new file mode 100644 index 000000000..e22ec48f6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.cc @@ -0,0 +1,45 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/accessor_expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::AccessorExpression); + +namespace tint::sem { + +AccessorExpression::AccessorExpression(const ast::AccessorExpression* declaration, + const core::type::Type* type, + core::EvaluationStage stage, + const ValueExpression* object, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident /* = nullptr */) + : Base(declaration, type, stage, statement, constant, root_ident), object_(object) {} + +AccessorExpression::~AccessorExpression() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.h new file mode 100644 index 000000000..58e143690 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/accessor_expression.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_ACCESSOR_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_ACCESSOR_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/accessor_expression.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" + +namespace tint::sem { + +/// AccessorExpression is the base class for all semantic information for an ast::AccessorExpression +/// node. +class AccessorExpression : public Castable { + public: + /// Destructor + ~AccessorExpression() override; + + /// @returns the object expression that is being indexed + ValueExpression const* Object() const { return object_; } + + protected: + /// Constructor + /// @param declaration the AST node + /// @param type the resolved type of the expression + /// @param stage the earliest evaluation stage for the expression + /// @param object the object expression that is being indexed + /// @param statement the statement that owns this expression + /// @param constant the constant value of the expression. May be null + /// @param root_ident the (optional) root identifier for this expression + AccessorExpression(const ast::AccessorExpression* declaration, + const core::type::Type* type, + core::EvaluationStage stage, + const ValueExpression* object, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident = nullptr); + + private: + ValueExpression const* const object_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_ACCESSOR_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/array.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/array.cc new file mode 100644 index 000000000..9c0a911d3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/array.cc @@ -0,0 +1,48 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/array.h" + +#include "src/tint/lang/wgsl/sem/variable.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Array); + +namespace tint::sem { + +Array::Array(core::type::Type const* element, const core::type::ArrayCount* count, uint32_t size) + : Base(element, count, size) {} + +Array::~Array() = default; + +void Array::AddTransitivelyReferencedOverride(const GlobalVariable* var) { + transitively_referenced_overrides_.Add(var); + for (auto* ref : var->TransitivelyReferencedOverrides()) { + AddTransitivelyReferencedOverride(ref); + } +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/array.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/array.h new file mode 100644 index 000000000..dbc8fd012 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/array.h @@ -0,0 +1,69 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_ARRAY_H_ +#define SRC_TINT_LANG_WGSL_SEM_ARRAY_H_ + +#include "src/tint/lang/core/type/array.h" +#include "src/tint/utils/containers/unique_vector.h" + +/// Forward declarations +namespace tint::sem { +class GlobalVariable; +} + +namespace tint::sem { + +/// Array holds the semantic information for Arrays. +class Array final : public Castable { + public: + /// Constructor + /// @param element the array element type + /// @param count the number of elements in the array. + /// @param size the byte size of the array. The size will be 0 if the array element count is + /// pipeline overridable. + Array(core::type::Type const* element, const core::type::ArrayCount* count, uint32_t size); + + /// Destructor + ~Array() override; + + /// Records that this variable (transitively) references the given override variable. + /// @param var the module-scope override variable + void AddTransitivelyReferencedOverride(const GlobalVariable* var); + + /// @returns all transitively referenced override variables + VectorRef TransitivelyReferencedOverrides() const { + return transitively_referenced_overrides_; + } + + private: + UniqueVector transitively_referenced_overrides_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_ARRAY_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.cc new file mode 100644 index 000000000..37d341292 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.cc @@ -0,0 +1,76 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/array_count.h" + +#include "src/tint/lang/wgsl/ast/identifier.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::NamedOverrideArrayCount); +TINT_INSTANTIATE_TYPEINFO(tint::sem::UnnamedOverrideArrayCount); + +namespace tint::sem { + +NamedOverrideArrayCount::NamedOverrideArrayCount(const GlobalVariable* var) + : Base(static_cast(tint::TypeCode::Of().bits)), + variable(var) {} +NamedOverrideArrayCount::~NamedOverrideArrayCount() = default; + +bool NamedOverrideArrayCount::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return variable == v->variable; + } + return false; +} + +std::string NamedOverrideArrayCount::FriendlyName() const { + return variable->Declaration()->name->symbol.Name(); +} + +core::type::ArrayCount* NamedOverrideArrayCount::Clone(core::type::CloneContext&) const { + TINT_UNREACHABLE() << "Named override array count clone not available"; +} + +UnnamedOverrideArrayCount::UnnamedOverrideArrayCount(const ValueExpression* e) + : Base(static_cast(tint::TypeCode::Of().bits)), expr(e) {} +UnnamedOverrideArrayCount::~UnnamedOverrideArrayCount() = default; + +bool UnnamedOverrideArrayCount::Equals(const UniqueNode& other) const { + if (auto* v = other.As()) { + return expr == v->expr; + } + return false; +} + +std::string UnnamedOverrideArrayCount::FriendlyName() const { + return "[unnamed override-expression]"; +} + +core::type::ArrayCount* UnnamedOverrideArrayCount::Clone(core::type::CloneContext&) const { + TINT_UNREACHABLE() << "Unnamed override array count clone not available"; +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.h new file mode 100644 index 000000000..4e7119a7d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/array_count.h @@ -0,0 +1,110 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_ARRAY_COUNT_H_ +#define SRC_TINT_LANG_WGSL_SEM_ARRAY_COUNT_H_ + +#include + +#include "src/tint/lang/core/type/array_count.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/lang/wgsl/sem/variable.h" + +namespace tint::sem { + +/// The variant of an ArrayCount when the count is a named override variable. +/// Example: +/// ``` +/// override N : i32; +/// type arr = array +/// ``` +class NamedOverrideArrayCount final + : public Castable { + public: + /// Constructor + /// @param var the `override` variable + explicit NamedOverrideArrayCount(const GlobalVariable* var); + ~NamedOverrideArrayCount() override; + + /// @param other the other node + /// @returns true if this array count is equal @p other + bool Equals(const core::type::UniqueNode& other) const override; + + /// @returns the friendly name for this array count + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + core::type::ArrayCount* Clone(core::type::CloneContext& ctx) const override; + + /// The `override` variable. + const GlobalVariable* variable; +}; + +/// The variant of an ArrayCount when the count is an unnamed override variable. +/// Example: +/// ``` +/// override N : i32; +/// type arr = array +/// ``` +class UnnamedOverrideArrayCount final + : public Castable { + public: + /// Constructor + /// @param e the override expression + explicit UnnamedOverrideArrayCount(const ValueExpression* e); + ~UnnamedOverrideArrayCount() override; + + /// @param other the other node + /// @returns true if this array count is equal @p other + bool Equals(const core::type::UniqueNode& other) const override; + + /// @returns the friendly name for this array count + std::string FriendlyName() const override; + + /// @param ctx the clone context + /// @returns a clone of this type + core::type::ArrayCount* Clone(core::type::CloneContext& ctx) const override; + + /// The unnamed override expression. + /// Note: Each AST expression gets a unique semantic expression node, so two equivalent AST + /// expressions will not result in the same `expr` pointer. This property is important to ensure + /// that two array declarations with equivalent AST expressions do not compare equal. + /// For example, consider: + /// ``` + /// override size : u32; + /// var a : array; + /// var b : array; + /// ``` + // The array count for `a` and `b` have equivalent AST expressions, but the types for `a` and + // `b` must not compare equal. + const ValueExpression* expr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_ARRAY_COUNT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.cc new file mode 100644 index 000000000..74a56c0fa --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.cc @@ -0,0 +1,46 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/behavior.h" + +namespace tint::sem { + +std::string_view ToString(Behavior behavior) { + switch (behavior) { + case Behavior::kReturn: + return "Return"; + case Behavior::kBreak: + return "Break"; + case Behavior::kContinue: + return "Continue"; + case Behavior::kNext: + return "Next"; + } + return ""; +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.h new file mode 100644 index 000000000..854e8673e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/behavior.h @@ -0,0 +1,63 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_BEHAVIOR_H_ +#define SRC_TINT_LANG_WGSL_SEM_BEHAVIOR_H_ + +#include "src/tint/utils/containers/enum_set.h" + +namespace tint::sem { + +/// Behavior enumerates the possible behaviors of an expression or statement. +/// @see https://www.w3.org/TR/WGSL/#behaviors +enum class Behavior { + kReturn, + kBreak, + kContinue, + kNext, +}; + +/// Behaviors is a set of Behavior +using Behaviors = tint::EnumSet; + +/// @param behavior the behavior +/// @returns the string for the given enumerator +std::string_view ToString(Behavior behavior); + +/// Writes the Behavior to the stream. +/// @param out the stream to write to +/// @param behavior the Behavior to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, Behavior behavior) { + return out << ToString(behavior); +} + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_BEHAVIOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.cc new file mode 100644 index 000000000..647668a79 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.cc @@ -0,0 +1,73 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/block_statement.h" + +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/function.h" +#include "src/tint/lang/wgsl/sem/function.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::BlockStatement); +TINT_INSTANTIATE_TYPEINFO(tint::sem::FunctionBlockStatement); +TINT_INSTANTIATE_TYPEINFO(tint::sem::LoopBlockStatement); + +namespace tint::sem { + +BlockStatement::BlockStatement(const ast::BlockStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) {} + +BlockStatement::~BlockStatement() = default; + +const ast::BlockStatement* BlockStatement::Declaration() const { + return Base::Declaration()->As(); +} + +FunctionBlockStatement::FunctionBlockStatement(const sem::Function* function) + : Base(function->Declaration()->body, nullptr, function) { + TINT_ASSERT(function); +} + +FunctionBlockStatement::~FunctionBlockStatement() = default; + +LoopBlockStatement::LoopBlockStatement(const ast::BlockStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) { + TINT_ASSERT(parent); + TINT_ASSERT(function); +} +LoopBlockStatement::~LoopBlockStatement() = default; + +void LoopBlockStatement::SetFirstContinue(const ast::ContinueStatement* first_continue, + size_t num_decls) { + first_continue_ = first_continue; + num_decls_at_first_continue_ = num_decls; +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.h new file mode 100644 index 000000000..e0dc851a8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/block_statement.h @@ -0,0 +1,113 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_BLOCK_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_BLOCK_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/sem/statement.h" + +// Forward declarations +namespace tint::ast { +class BlockStatement; +class ContinueStatement; +class Variable; +} // namespace tint::ast + +namespace tint::sem { + +/// Holds semantic information about a block, such as parent block and variables +/// declared in the block. +class BlockStatement : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this block statement + /// @param parent the owning statement + /// @param function the owning function + BlockStatement(const ast::BlockStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~BlockStatement() override; + + /// @returns the AST block statement associated with this semantic block + /// statement + const ast::BlockStatement* Declaration() const; +}; + +/// The root block statement for a function +class FunctionBlockStatement final : public Castable { + public: + /// Constructor + /// @param function the owning function + explicit FunctionBlockStatement(const sem::Function* function); + + /// Destructor + ~FunctionBlockStatement() override; +}; + +/// Holds semantic information about a loop body block or for-loop body block +class LoopBlockStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this block statement + /// @param parent the owning statement + /// @param function the owning function + LoopBlockStatement(const ast::BlockStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~LoopBlockStatement() override; + + /// @returns the first continue statement in this loop block, or nullptr if + /// there are no continue statements in the block + const ast::ContinueStatement* FirstContinue() const { return first_continue_; } + + /// @returns the number of variables declared before the first continue + /// statement + size_t NumDeclsAtFirstContinue() const { return num_decls_at_first_continue_; } + + /// Allows the resolver to record the first continue statement in the block + /// and the number of variables declared prior to that statement. + /// @param first_continue the first continue statement in the block + /// @param num_decls the number of variable declarations before that continue + void SetFirstContinue(const ast::ContinueStatement* first_continue, size_t num_decls); + + private: + /// The first continue statement in this loop block. + const ast::ContinueStatement* first_continue_ = nullptr; + + /// The number of variables declared before the first continue statement. + size_t num_decls_at_first_continue_ = 0; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_BLOCK_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.cc new file mode 100644 index 000000000..bdeade802 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.cc @@ -0,0 +1,47 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/break_if_statement.h" + +#include "src/tint/lang/wgsl/ast/break_if_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::BreakIfStatement); + +namespace tint::sem { + +BreakIfStatement::BreakIfStatement(const ast::BreakIfStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) {} + +BreakIfStatement::~BreakIfStatement() = default; + +const ast::BreakIfStatement* BreakIfStatement::Declaration() const { + return static_cast(Base::Declaration()); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.h new file mode 100644 index 000000000..0a002a833 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/break_if_statement.h @@ -0,0 +1,73 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_BREAK_IF_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_BREAK_IF_STATEMENT_H_ + +#include "src/tint/lang/wgsl/sem/statement.h" + +// Forward declarations +namespace tint::ast { +class BreakIfStatement; +} // namespace tint::ast +namespace tint::sem { +class ValueExpression; +} // namespace tint::sem + +namespace tint::sem { + +/// Holds semantic information about a break-if statement +class BreakIfStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this break-if statement + /// @param parent the owning statement + /// @param function the owning function + BreakIfStatement(const ast::BreakIfStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~BreakIfStatement() override; + + /// @returns the AST node + const ast::BreakIfStatement* Declaration() const; + + /// @returns the break-if-statement condition expression + const ValueExpression* Condition() const { return condition_; } + + /// Sets the break-if-statement condition expression + /// @param condition the break-if condition expression + void SetCondition(const ValueExpression* condition) { condition_ = condition; } + + private: + const ValueExpression* condition_ = nullptr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_BREAK_IF_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.cc new file mode 100644 index 000000000..0975b5196 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.cc @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/builtin_enum_expression.h" + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/enums.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpressionBase); + +// Specializations +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); + +namespace tint::sem { + +BuiltinEnumExpressionBase::BuiltinEnumExpressionBase(const ast::Expression* declaration, + const Statement* statement) + : Base(declaration, statement) {} + +BuiltinEnumExpressionBase::~BuiltinEnumExpressionBase() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.h new file mode 100644 index 000000000..53ba8578c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_enum_expression.h @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_BUILTIN_ENUM_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_BUILTIN_ENUM_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/sem/expression.h" + +// Forward declarations +namespace tint::core::type { +class Type; +} // namespace tint::core::type + +namespace tint::sem { + +/// Base class for BuiltinEnumExpression. +/// Useful for Is() queries. +class BuiltinEnumExpressionBase : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + BuiltinEnumExpressionBase(const ast::Expression* declaration, const Statement* statement); + + /// Destructor + ~BuiltinEnumExpressionBase() override; +}; + +/// BuiltinEnumExpression holds the semantic information for expression nodes that resolve to a +/// builtin enumerator value. +template +class BuiltinEnumExpression + : public Castable, BuiltinEnumExpressionBase> { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + /// @param value the enumerator value + BuiltinEnumExpression(const ast::Expression* declaration, + const Statement* statement, + ENUM value) + : BuiltinEnumExpression::Base(declaration, statement), value_(value) {} + + /// Destructor + ~BuiltinEnumExpression() override = default; + + /// @return the enumerator value + ENUM Value() const { return value_; } + + private: + const ENUM value_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_BUILTIN_ENUM_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.cc new file mode 100644 index 000000000..1242ab6d5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.cc @@ -0,0 +1,119 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Doxygen seems to trip over this file for some unknown reason. Disable. +//! @cond Doxygen_Suppress + +#include "src/tint/lang/wgsl/sem/builtin_fn.h" + +#include + +#include "src/tint/lang/core/intrinsic/table.h" +#include "src/tint/lang/core/type/texel_buffer.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinFn); + +namespace tint::sem { + +const char* BuiltinFn::str() const { + return wgsl::str(fn_); +} + +BuiltinFn::BuiltinFn(wgsl::BuiltinFn type, + const core::type::Type* return_type, + VectorRef parameters, + core::EvaluationStage eval_stage, + PipelineStageSet supported_stages, + const core::intrinsic::OverloadInfo& overload) + : Base(return_type, + std::move(parameters), + eval_stage, + overload.flags.Contains(core::intrinsic::OverloadFlag::kMustUse)), + fn_(type), + supported_stages_(supported_stages), + overload_(overload) {} + +BuiltinFn::~BuiltinFn() = default; + +bool BuiltinFn::IsDeprecated() const { + return overload_.flags.Contains(core::intrinsic::OverloadFlag::kIsDeprecated); +} + +bool BuiltinFn::IsDerivative() const { + return wgsl::IsDerivative(fn_); +} + +bool BuiltinFn::IsBarrier() const { + return wgsl::IsBarrier(fn_); +} + +bool BuiltinFn::IsAtomic() const { + return wgsl::IsAtomic(fn_); +} + +bool BuiltinFn::IsPacked4x8IntegerDotProductBuiltin() const { + return wgsl::IsPacked4x8IntegerDotProductBuiltin(fn_); +} + +bool BuiltinFn::IsSubgroup() const { + return wgsl::IsSubgroup(fn_); +} + +bool BuiltinFn::IsSubgroupMatrix() const { + return wgsl::IsSubgroupMatrix(fn_); +} + +bool BuiltinFn::IsTexelBuffer() const { + for (auto* param : Parameters()) { + if (param->Type()->UnwrapRef()->Is()) { + return true; + } + } + + return false; +} + +bool BuiltinFn::IsResourceTable() const { + return wgsl::IsResourceTable(fn_); +} + +wgsl::LanguageFeature BuiltinFn::RequiredLanguageFeature() const { + if (fn_ == wgsl::BuiltinFn::kTextureBarrier) { + return wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures; + } + if (IsPacked4x8IntegerDotProductBuiltin()) { + return wgsl::LanguageFeature::kPacked4X8IntegerDotProduct; + } + if (IsTexelBuffer()) { + return wgsl::LanguageFeature::kTexelBuffers; + } + return wgsl::LanguageFeature::kUndefined; +} + +} // namespace tint::sem + +//! @endcond diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.h new file mode 100644 index 000000000..566b27956 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/builtin_fn.h @@ -0,0 +1,125 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_BUILTIN_FN_H_ +#define SRC_TINT_LANG_WGSL_SEM_BUILTIN_FN_H_ + +#include +#include + +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/sem/call_target.h" +#include "src/tint/lang/wgsl/sem/pipeline_stage_set.h" +#include "src/tint/utils/math/hash.h" + +// Forward declarations +namespace tint::core::intrinsic { +struct OverloadInfo; +} + +namespace tint::sem { + +/// BuiltinFn holds the semantic information for a builtin function. +class BuiltinFn final : public Castable { + public: + /// Constructor + /// @param type the builtin type + /// @param return_type the return type for the builtin call + /// @param parameters the parameters for the builtin overload + /// @param eval_stage the earliest evaluation stage for a call to the builtin + /// @param supported_stages the pipeline stages that this builtin can be used in + /// @param overload the builtin table overload + BuiltinFn(wgsl::BuiltinFn type, + const core::type::Type* return_type, + VectorRef parameters, + core::EvaluationStage eval_stage, + PipelineStageSet supported_stages, + const core::intrinsic::OverloadInfo& overload); + + /// Destructor + ~BuiltinFn() override; + + /// @return the type of the builtin + wgsl::BuiltinFn Fn() const { return fn_; } + + /// @return the pipeline stages that this builtin can be used in + PipelineStageSet SupportedStages() const { return supported_stages_; } + + /// @return true if the builtin overload is considered deprecated + bool IsDeprecated() const; + + /// @returns the name of the builtin function type. The spelling, including + /// case, matches the name in the WGSL spec. + const char* str() const; + + /// @returns true if builtin is a derivative builtin + bool IsDerivative() const; + + /// @returns true if builtin is a barrier builtin + bool IsBarrier() const; + + /// @returns true if builtin is a atomic builtin + bool IsAtomic() const; + + /// @returns true if builtin is a builtin defined in the language extension + /// `packed_4x8_integer_dot_product`. + bool IsPacked4x8IntegerDotProductBuiltin() const; + + /// @returns true if builtin is a subgroup builtin (defined in the extension `subgroups`). + bool IsSubgroup() const; + + /// @returns true if builtin is a subgroup matrix builtin (defined in the extension + /// `subgroup_matrix`). + bool IsSubgroupMatrix() const; + + /// @returns true if builtin is a texel buffer builtin + bool IsTexelBuffer() const; + + /// @returns true if builtin is a resource table builtin + bool IsResourceTable() const; + + /// @returns the required language feature of this builtin function. Returns + /// wgsl::LanguageFeature::kUndefined if no language feature is required. + wgsl::LanguageFeature RequiredLanguageFeature() const; + + /// @returns the builtin table overload info + const core::intrinsic::OverloadInfo& Overload() const { return overload_; } + + /// @return the hash code for this object + tint::HashCode HashCode() const { + return Hash(Fn(), SupportedStages(), ReturnType(), Parameters(), IsDeprecated()); + } + + private: + const wgsl::BuiltinFn fn_; + const PipelineStageSet supported_stages_; + const core::intrinsic::OverloadInfo& overload_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_BUILTIN_FN_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/call.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/call.cc new file mode 100644 index 000000000..89ddd3a09 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/call.cc @@ -0,0 +1,52 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/call.h" + +#include + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Call); + +namespace tint::sem { + +Call::Call(const ast::CallExpression* declaration, + const CallTarget* target, + core::EvaluationStage stage, + VectorRef arguments, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident) + : Base(declaration, target->ReturnType(), stage, statement, constant, root_ident), + target_(target), + arguments_(std::move(arguments)) { + // Check that the stage is no earlier than the target supports + TINT_ASSERT((target->Stage() <= stage) || (stage == core::EvaluationStage::kNotEvaluated)); +} + +Call::~Call() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/call.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/call.h new file mode 100644 index 000000000..77e17ab8c --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/call.h @@ -0,0 +1,79 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_CALL_H_ +#define SRC_TINT_LANG_WGSL_SEM_CALL_H_ + +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/sem/call_target.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint::sem { + +/// Call is the base class for semantic nodes that hold semantic information for +/// ast::CallExpression nodes. +class Call final : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param target the call target + /// @param stage the earliest evaluation stage for the expression + /// @param arguments the call arguments + /// @param statement the statement that owns this expression + /// @param constant the constant value of this expression + /// @param root_ident the root identifier of the call (rarely used) + Call(const ast::CallExpression* declaration, + const CallTarget* target, + core::EvaluationStage stage, + VectorRef arguments, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident = nullptr); + + /// Destructor + ~Call() override; + + /// @return the target of the call + const CallTarget* Target() const { return target_; } + + /// @return the call arguments + const auto& Arguments() const { return arguments_; } + + /// @returns the AST node + const ast::CallExpression* Declaration() const { + return static_cast(declaration_); + } + + private: + CallTarget const* const target_; + tint::Vector arguments_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_CALL_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.cc new file mode 100644 index 000000000..fe416dbce --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.cc @@ -0,0 +1,95 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/call_target.h" + +#include + +#include "src/tint/utils/math/hash.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::CallTarget); + +namespace tint::sem { + +CallTarget::CallTarget(core::EvaluationStage stage, bool must_use) + : stage_(stage), must_use_(must_use) {} + +CallTarget::CallTarget(const core::type::Type* return_type, + VectorRef parameters, + core::EvaluationStage stage, + bool must_use) + : stage_(stage), must_use_(must_use) { + SetReturnType(return_type); + for (auto* param : parameters) { + AddParameter(param); + } + TINT_ASSERT(return_type); +} + +CallTarget::CallTarget(const CallTarget&) = default; +CallTarget::~CallTarget() = default; + +CallTargetSignature::CallTargetSignature() = default; + +CallTargetSignature::CallTargetSignature(const core::type::Type* ret_ty, + VectorRef params) + : return_type(ret_ty), parameters(std::move(params)) {} +CallTargetSignature::CallTargetSignature(const CallTargetSignature&) = default; +CallTargetSignature::~CallTargetSignature() = default; + +int CallTargetSignature::IndexOf(core::ParameterUsage usage) const { + for (size_t i = 0; i < parameters.Length(); i++) { + if (parameters[i]->Usage() == usage) { + return static_cast(i); + } + } + return -1; +} + +tint::HashCode CallTargetSignature::HashCode() const { + auto hash = tint::Hash(parameters.Length()); + for (auto* p : parameters) { + hash = HashCombine(hash, p->Type(), p->Usage()); + } + return Hash(hash, return_type); +} + +bool CallTargetSignature::operator==(const CallTargetSignature& other) const { + if (return_type != other.return_type || parameters.Length() != other.parameters.Length()) { + return false; + } + for (size_t i = 0; i < parameters.Length(); i++) { + auto* a = parameters[i]; + auto* b = other.parameters[i]; + if (a->Type() != b->Type() || a->Usage() != b->Usage()) { + return false; + } + } + return true; +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.h new file mode 100644 index 000000000..d7f10eca5 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/call_target.h @@ -0,0 +1,136 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_CALL_TARGET_H_ +#define SRC_TINT_LANG_WGSL_SEM_CALL_TARGET_H_ + +#include "src/tint/lang/wgsl/sem/node.h" +#include "src/tint/lang/wgsl/sem/variable.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/math/hash.h" + +namespace tint::sem { + +/// CallTargetSignature holds the return type and parameters for a call target +struct CallTargetSignature { + /// Constructor + CallTargetSignature(); + + /// Constructor + /// @param ret_ty the call target return type + /// @param params the call target parameters + CallTargetSignature(const core::type::Type* ret_ty, VectorRef params); + + /// Copy constructor + CallTargetSignature(const CallTargetSignature&); + + /// Destructor + ~CallTargetSignature(); + + /// @returns the hash code of the CallTargetSignature + tint::HashCode HashCode() const; + + /// Equality operator + /// @param other the signature to compare this to + /// @returns true if this signature is equal to other + bool operator==(const CallTargetSignature& other) const; + + /// @param usage the parameter usage to find + /// @returns the index of the parameter with the given usage, or -1 if no + /// parameter with the given usage exists. + int IndexOf(core::ParameterUsage usage) const; + + /// The type of the call target return value + const core::type::Type* return_type = nullptr; + + /// The parameters of the call target + tint::Vector parameters; +}; + +/// CallTarget is the base for callable functions, builtins, value constructors and value +/// conversions. +class CallTarget : public Castable { + public: + /// Constructor + /// @param stage the earliest evaluation stage for a call to this target + /// @param must_use the result of the call target must be used, i.e. it cannot be used as a call + /// statement. + CallTarget(core::EvaluationStage stage, bool must_use); + + /// Constructor + /// @param return_type the return type of the call target + /// @param parameters the parameters for the call target + /// @param stage the earliest evaluation stage for a call to this target + /// @param must_use the result of the call target must be used, i.e. it cannot be used as a call + /// statement. + CallTarget(const core::type::Type* return_type, + VectorRef parameters, + core::EvaluationStage stage, + bool must_use); + + /// Copy constructor + CallTarget(const CallTarget&); + + /// Destructor + ~CallTarget() override; + + /// Sets the call target's return type + /// @param ty the parameter + void SetReturnType(const core::type::Type* ty) { signature_.return_type = ty; } + + /// @return the return type of the call target + const core::type::Type* ReturnType() const { return signature_.return_type; } + + /// Adds a parameter to the call target + /// @param parameter the parameter + void AddParameter(Parameter* parameter) { + parameter->SetOwner(this); + signature_.parameters.Push(parameter); + } + + /// @return the parameters of the call target + auto& Parameters() const { return signature_.parameters; } + + /// @return the signature of the call target + const CallTargetSignature& Signature() const { return signature_; } + + /// @return the earliest evaluation stage for a call to this target + core::EvaluationStage Stage() const { return stage_; } + + /// @returns true if the result of the call target must be used, i.e. it cannot be used as a + /// call statement. + bool MustUse() const { return must_use_; } + + private: + CallTargetSignature signature_; + core::EvaluationStage stage_; + const bool must_use_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_CALL_TARGET_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/expression.cc new file mode 100644 index 000000000..6aeebcc2e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/expression.cc @@ -0,0 +1,39 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Expression); + +namespace tint::sem { + +Expression::Expression(const ast::Expression* declaration, const Statement* statement) + : declaration_(declaration), statement_(statement) {} + +Expression::~Expression() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/expression.h new file mode 100644 index 000000000..20cdfa1ec --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/expression.h @@ -0,0 +1,68 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/expression.h" +#include "src/tint/lang/wgsl/sem/node.h" + +// Forward declarations +namespace tint::sem { +class Statement; +} // namespace tint::sem + +namespace tint::sem { + +/// Expression holds the semantic information for expression nodes. +class Expression : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + Expression(const ast::Expression* declaration, const Statement* statement); + + /// Destructor + ~Expression() override; + + /// @returns the AST node + const ast::Expression* Declaration() const { return declaration_; } + + /// @return the statement that owns this expression + const Statement* Stmt() const { return statement_; } + + protected: + /// The AST expression node for this semantic expression + const ast::Expression* const declaration_; + + private: + const Statement* const statement_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.cc new file mode 100644 index 000000000..a6d3a27f8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.cc @@ -0,0 +1,47 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/for_loop_statement.h" + +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::ForLoopStatement); + +namespace tint::sem { + +ForLoopStatement::ForLoopStatement(const ast::ForLoopStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) {} + +ForLoopStatement::~ForLoopStatement() = default; + +const ast::ForLoopStatement* ForLoopStatement::Declaration() const { + return static_cast(Base::Declaration()); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.h new file mode 100644 index 000000000..fbcd745c4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/for_loop_statement.h @@ -0,0 +1,73 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_FOR_LOOP_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_FOR_LOOP_STATEMENT_H_ + +#include "src/tint/lang/wgsl/sem/statement.h" + +// Forward declarations +namespace tint::ast { +class ForLoopStatement; +} // namespace tint::ast +namespace tint::sem { +class ValueExpression; +} // namespace tint::sem + +namespace tint::sem { + +/// Holds semantic information about a for-loop statement +class ForLoopStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this for-loop statement + /// @param parent the owning statement + /// @param function the owning function + ForLoopStatement(const ast::ForLoopStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~ForLoopStatement() override; + + /// @returns the AST node + const ast::ForLoopStatement* Declaration() const; + + /// @returns the for-loop condition expression + const ValueExpression* Condition() const { return condition_; } + + /// Sets the for-loop condition expression + /// @param condition the for-loop condition expression + void SetCondition(const ValueExpression* condition) { condition_ = condition; } + + private: + const ValueExpression* condition_ = nullptr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_FOR_LOOP_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/function.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/function.cc new file mode 100644 index 000000000..161109572 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/function.cc @@ -0,0 +1,68 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/function.h" + +#include "src/tint/lang/wgsl/ast/function.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/must_use_attribute.h" +#include "src/tint/lang/wgsl/sem/variable.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Function); + +namespace tint::sem { + +Function::Function(const ast::Function* declaration) + : Base(core::EvaluationStage::kRuntime, + ast::HasAttribute(declaration->attributes)), + declaration_(declaration), + workgroup_size_{1, 1, 1} {} + +Function::~Function() = default; + +void Function::AddTransitivelyReferencedGlobal(const sem::GlobalVariable* global) { + if (transitively_referenced_globals_.Add(global)) { + for (auto* ref : global->TransitivelyReferencedOverrides()) { + AddTransitivelyReferencedGlobal(ref); + } + } +} + +bool Function::HasCallGraphEntryPoint(Symbol symbol) const { + for (const auto* point : call_graph_entry_points_) { + if (point->Declaration()->name->symbol == symbol) { + return true; + } + } + return false; +} + +void Function::SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) { + diagnostic_severities_.Add(rule, severity); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/function.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/function.h new file mode 100644 index 000000000..94cca3200 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/function.h @@ -0,0 +1,254 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_FUNCTION_H_ +#define SRC_TINT_LANG_WGSL_SEM_FUNCTION_H_ + +#include +#include +#include + +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/sem/call.h" +#include "src/tint/utils/containers/unique_vector.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/symbol/symbol.h" + +// Forward declarations +namespace tint::ast { +class BuiltinAttribute; +class Function; +class LocationAttribute; +class ReturnStatement; +} // namespace tint::ast +namespace tint::sem { +class BuiltinFn; +class Variable; +} // namespace tint::sem + +namespace tint::sem { + +/// WorkgroupSize is a three-dimensional array of WorkgroupDimensions. +/// Each dimension is a std::optional as a workgroup size can be a const-expression or +/// override-expression. Override expressions are not known at compilation time, so these will be +/// std::nullopt. +using WorkgroupSize = std::array, 3>; + +/// Function holds the semantic information for function nodes. +class Function final : public Castable { + public: + /// Constructor + /// @param declaration the ast::Function + explicit Function(const ast::Function* declaration); + + /// Destructor + ~Function() override; + + /// Sets the function's return location + /// @param return_location the location value + void SetReturnLocation(uint32_t return_location) { return_location_ = return_location; } + + /// @returns the ast::Function declaration + const ast::Function* Declaration() const { return declaration_; } + + /// @returns the workgroup size {x, y, z} for the function. + const sem::WorkgroupSize& WorkgroupSize() const { return workgroup_size_; } + + /// Sets the workgroup size {x, y, z} for the function. + /// @param workgroup_size the new workgroup size of the function + void SetWorkgroupSize(sem::WorkgroupSize workgroup_size) { + workgroup_size_ = std::move(workgroup_size); + } + + /// Sets the subgroup size for the function. + /// @param subgroup_size the new subgroup size of the function + void SetSubgroupSize(uint32_t subgroup_size) { subgroup_size_ = subgroup_size; } + + /// @returns the subgroup size for the functions. + std::optional SubgroupSize() const { return subgroup_size_; } + + /// @returns all directly referenced global variables + const UniqueVector& DirectlyReferencedGlobals() const { + return directly_referenced_globals_; + } + + /// Records that this function directly references the given global variable. + /// Note: Implicitly adds this global to the transitively-called globals. + /// @param global the module-scope variable + void AddDirectlyReferencedGlobal(const sem::GlobalVariable* global) { + directly_referenced_globals_.Add(global); + AddTransitivelyReferencedGlobal(global); + } + + /// @returns all transitively referenced global variables + const UniqueVector& TransitivelyReferencedGlobals() const { + return transitively_referenced_globals_; + } + + /// Records that this function transitively references the given global + /// variable. + /// @param global the module-scoped variable + void AddTransitivelyReferencedGlobal(const sem::GlobalVariable* global); + + /// @returns the list of functions that this function transitively calls. + const UniqueVector& TransitivelyCalledFunctions() const { + return transitively_called_functions_; + } + + /// Records that this function transitively calls `function`. + /// @param function the function this function transitively calls + void AddTransitivelyCalledFunction(const Function* function) { + transitively_called_functions_.Add(function); + } + + /// @returns the list of builtins that this function directly calls. + const UniqueVector& DirectlyCalledBuiltins() const { + return directly_called_builtins_; + } + + /// Records that this function transitively calls `builtin`. + /// @param builtin the builtin this function directly calls + void AddDirectlyCalledBuiltin(const BuiltinFn* builtin) { + directly_called_builtins_.Add(builtin); + } + + /// Records the source of the first node that uses a subgroup matrix type + /// @param src the source + void SetDirectlyUsedSubgroupMatrix(const Source* src) { + if (!directly_used_subgroup_matrix_) { + directly_used_subgroup_matrix_ = src; + } + } + + /// @returns the source of the first node that uses a subgroup matrix type, if any + std::optional DirectlyUsedSubgroupMatrix() const { + return directly_used_subgroup_matrix_; + } + + /// @returns the list of direct calls to functions / builtins made by this + /// function + const Vector& DirectCalls() const { return direct_calls_; } + + /// Adds a record of the direct function / builtin calls made by this + /// function + /// @param call the call + void AddDirectCall(const Call* call) { direct_calls_.Push(call); } + + /// @param target the target of a call + /// @returns the Call to the given CallTarget, or nullptr the target was not + /// called by this function. + const Call* FindDirectCallTo(const CallTarget* target) const { + for (auto* call : direct_calls_) { + if (call->Target() == target) { + return call; + } + } + return nullptr; + } + + /// @returns the list of callsites to this function + const Vector& CallSites() const { return callsites_; } + + /// Adds a record of a callsite to this function + /// @param call the callsite + void AddCallSite(const Call* call) { callsites_.Push(call); } + + /// @returns the entry points that have this function in their call graph. Entry points are in + /// their own call graph. + const Vector& CallGraphEntryPoints() const { + return call_graph_entry_points_; + } + + /// Adds a record that the given entry point has this function in its call graph. + /// @param entry_point the entry point + void AddCallGraphEntryPoint(const sem::Function* entry_point) { + call_graph_entry_points_.Push(entry_point); + } + + /// Checks if the given entry point has the function in its call graph + /// @param sym the entry point symbol + /// @returns true if `sym` has the function in its call graph + bool HasCallGraphEntryPoint(Symbol sym) const; + + /// Records the first discard statement in the function + /// @param stmt the `discard` statement. + void SetDiscardStatement(const Statement* stmt) { + if (!discard_stmt_) { + discard_stmt_ = stmt; + } + } + + /// @returns the first discard statement for the function, or nullptr if the function does not + /// use `discard`. + const Statement* DiscardStatement() const { return discard_stmt_; } + + /// @return the behaviors of this function + const sem::Behaviors& Behaviors() const { return behaviors_; } + + /// @return the behaviors of this function + sem::Behaviors& Behaviors() { return behaviors_; } + + /// @return the location for the return, if provided + std::optional ReturnLocation() const { return return_location_; } + + /// Modifies the severity of a specific diagnostic rule for this function. + /// @param rule the diagnostic rule + /// @param severity the new diagnostic severity + void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity); + + /// @returns the diagnostic severity modifications applied to this function + const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const { + return diagnostic_severities_; + } + + private: + Function(const Function&) = delete; + Function(Function&&) = delete; + + const ast::Function* const declaration_; + + sem::WorkgroupSize workgroup_size_; + std::optional subgroup_size_; + UniqueVector directly_referenced_globals_; + UniqueVector transitively_referenced_globals_; + UniqueVector transitively_called_functions_; + UniqueVector directly_called_builtins_; + Vector direct_calls_; + Vector callsites_; + Vector call_graph_entry_points_; + const Statement* discard_stmt_ = nullptr; + sem::Behaviors behaviors_{sem::Behavior::kNext}; + wgsl::DiagnosticRuleSeverities diagnostic_severities_; + + std::optional directly_used_subgroup_matrix_ = std::nullopt; + + std::optional return_location_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_FUNCTION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.cc new file mode 100644 index 000000000..f2a528c36 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.cc @@ -0,0 +1,42 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/function_expression.h" +#include "src/tint/lang/wgsl/ast/identifier_expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::FunctionExpression); + +namespace tint::sem { + +FunctionExpression::FunctionExpression(const ast::IdentifierExpression* declaration, + const Statement* statement, + const sem::Function* function) + : Base(declaration, statement), function_(function) {} + +FunctionExpression::~FunctionExpression() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.h new file mode 100644 index 000000000..dd56290d3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/function_expression.h @@ -0,0 +1,67 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_FUNCTION_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_FUNCTION_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/sem/expression.h" + +// Forward declarations +namespace tint::ast { +class IdentifierExpression; +} // namespace tint::ast +namespace tint::sem { +class Function; +} // namespace tint::sem + +namespace tint::sem { + +/// FunctionExpression holds the semantic information for expression nodes that resolve to +/// functions. +class FunctionExpression : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + /// @param function the function that the expression resolved to + FunctionExpression(const ast::IdentifierExpression* declaration, + const Statement* statement, + const sem::Function* function); + + /// Destructor + ~FunctionExpression() override; + + /// @return the function that the expression resolved to + const sem::Function* Function() const { return function_; } + + private: + sem::Function const* const function_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_FUNCTION_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.cc new file mode 100644 index 000000000..32624453d --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.cc @@ -0,0 +1,43 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/if_statement.h" + +#include "src/tint/lang/wgsl/ast/if_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::IfStatement); + +namespace tint::sem { + +IfStatement::IfStatement(const ast::IfStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) {} + +IfStatement::~IfStatement() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.h new file mode 100644 index 000000000..0a19b4b2e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/if_statement.h @@ -0,0 +1,70 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_IF_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_IF_STATEMENT_H_ + +#include "src/tint/lang/wgsl/sem/statement.h" + +// Forward declarations +namespace tint::ast { +class IfStatement; +} // namespace tint::ast +namespace tint::sem { +class ValueExpression; +} // namespace tint::sem + +namespace tint::sem { + +/// Holds semantic information about an if statement +class IfStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this if statement + /// @param parent the owning statement + /// @param function the owning function + IfStatement(const ast::IfStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~IfStatement() override; + + /// @returns the if-statement condition expression + const ValueExpression* Condition() const { return condition_; } + + /// Sets the if-statement condition expression + /// @param condition the if condition expression + void SetCondition(const ValueExpression* condition) { condition_ = condition; } + + private: + const ValueExpression* condition_ = nullptr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_IF_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.cc new file mode 100644 index 000000000..445ad4891 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.cc @@ -0,0 +1,48 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/index_accessor_expression.h" + +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::IndexAccessorExpression); + +namespace tint::sem { + +IndexAccessorExpression::IndexAccessorExpression(const ast::IndexAccessorExpression* declaration, + const core::type::Type* type, + core::EvaluationStage stage, + const ValueExpression* object, + const ValueExpression* index, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident /* = nullptr */) + : Base(declaration, type, stage, object, statement, constant, root_ident), index_(index) {} + +IndexAccessorExpression::~IndexAccessorExpression() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.h new file mode 100644 index 000000000..a194e9f76 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/index_accessor_expression.h @@ -0,0 +1,69 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_INDEX_ACCESSOR_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_INDEX_ACCESSOR_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/accessor_expression.h" + +namespace tint::sem { + +/// IndexAccessorExpression holds the semantic information for a ast::IndexAccessorExpression node. +class IndexAccessorExpression final : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param type the resolved type of the expression + /// @param stage the earliest evaluation stage for the expression + /// @param object the object expression that is being indexed + /// @param index the index expression + /// @param statement the statement that owns this expression + /// @param constant the constant value of the expression. May be null + /// @param root_ident the (optional) root identifier for this expression + IndexAccessorExpression(const ast::IndexAccessorExpression* declaration, + const core::type::Type* type, + core::EvaluationStage stage, + const ValueExpression* object, + const ValueExpression* index, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident = nullptr); + + /// Destructor + ~IndexAccessorExpression() override; + + /// @returns the index expression + ValueExpression const* Index() const { return index_; } + + private: + ValueExpression const* const index_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_INDEX_ACCESSOR_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/info.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/info.cc new file mode 100644 index 000000000..bfd6c0d35 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/info.cc @@ -0,0 +1,101 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/info.h" + +#include "src/tint/lang/wgsl/sem/function.h" +#include "src/tint/lang/wgsl/sem/module.h" +#include "src/tint/lang/wgsl/sem/statement.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/utils/rtti/switch.h" + +namespace tint::sem { + +Info::Info() = default; + +Info::Info(Info&&) = default; + +Info::~Info() = default; + +Info& Info::operator=(Info&&) = default; + +wgsl::DiagnosticSeverity Info::DiagnosticSeverity(const ast::Node* ast_node, + wgsl::DiagnosticRule rule) const { + // Get the diagnostic severity modification for a node. + auto check = [&](auto* node) { + if (auto severity = node->DiagnosticSeverities().Get(rule)) { + return *severity; + } + return wgsl::DiagnosticSeverity::kUndefined; + }; + + // Get the diagnostic severity modification for a function. + auto check_func = [&](const sem::Function* func) { + auto severity = check(func); + if (severity != wgsl::DiagnosticSeverity::kUndefined) { + return severity; + } + + // No severity set on the function, so check the module instead. + return check(module_); + }; + + // Get the diagnostic severity modification for a statement. + auto check_stmt = [&](const sem::Statement* stmt) { + // Walk up the statement hierarchy, checking for diagnostic severity modifications. + while (true) { + auto severity = check(stmt); + if (severity != wgsl::DiagnosticSeverity::kUndefined) { + return severity; + } + if (!stmt->Parent()) { + break; + } + stmt = stmt->Parent(); + } + + // No severity set on the statement, so check the function instead. + return check_func(stmt->Function()); + }; + + // Query the diagnostic severity from the semantic node that corresponds to the AST node. + auto* sem = Get(ast_node); + TINT_ASSERT(sem != nullptr); + auto severity = Switch( + sem, // + [&](const sem::ValueExpression* expr) { return check_stmt(expr->Stmt()); }, + [&](const sem::Statement* stmt) { return check_stmt(stmt); }, + [&](const sem::Function* func) { return check_func(func); }, + [&](Default) { + // Use the global severity set on the module. + return check(module_); + }); + TINT_ASSERT(severity != wgsl::DiagnosticSeverity::kUndefined); + return severity; +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/info.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/info.h new file mode 100644 index 000000000..527b2c7e4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/info.h @@ -0,0 +1,150 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_INFO_H_ +#define SRC_TINT_LANG_WGSL_SEM_INFO_H_ + +#include +#include + +#include "src/tint/lang/wgsl/ast/node.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/sem/node.h" +#include "src/tint/lang/wgsl/sem/type_mappings.h" +#include "src/tint/utils/ice/ice.h" + +// Forward declarations +namespace tint::sem { +class Module; +class ValueExpression; +} // namespace tint::sem +namespace tint::core::type { +class Node; +class Type; +} // namespace tint::core::type + +namespace tint::sem { + +/// Info holds all the resolved semantic information for a Program. +class Info { + public: + /// Placeholder type used by Get() to provide a default value for EXPLICIT_SEM + using InferFromAST = std::nullptr_t; + + /// Resolves to the return type of the Get() method given the desired semantic + /// type and AST type. + template + using GetResultType = + std::conditional_t::value, SemanticNodeTypeFor, SEM>; + + /// Constructor + Info(); + + /// Move constructor + Info(Info&&); + + /// Destructor + ~Info(); + + /// Move assignment operator + /// @param rhs the Program to move + /// @return this Program + Info& operator=(Info&& rhs); + + /// @param highest_node_id the last allocated (numerically highest) AST node identifier. + void Reserve(ast::NodeID highest_node_id) { + nodes_.Resize(std::max(highest_node_id.value + 1, static_cast(nodes_.Length()))); + } + + /// Get looks up the semantic information for the AST node `ast_node`. + /// @param ast_node the AST node + /// @returns a pointer to the semantic node if found, otherwise nullptr + template > + const RESULT* Get(const AST* ast_node) const { + static_assert(std::is_same_v || + !tint::traits::IsTypeOrDerived, SEM>, + "explicit template argument is unnecessary"); + if (ast_node && ast_node->node_id.value < nodes_.Length()) { + return As(nodes_[ast_node->node_id.value]); + } + return nullptr; + } + + /// Convenience function that's an alias for Get() + /// @param ast_node the AST node + /// @returns a pointer to the semantic node if found, otherwise nullptr + template + const sem::ValueExpression* GetVal(const AST* ast_node) const { + return Get(ast_node); + } + + /// Add registers the semantic node `sem_node` for the AST node `ast_node`. + /// @param ast_node the AST node + /// @param sem_node the semantic node + template + void Add(const AST* ast_node, const SemanticNodeTypeFor* sem_node) { + Reserve(ast_node->node_id); + // Check there's no semantic info already existing for the AST node + TINT_ASSERT(nodes_[ast_node->node_id.value] == nullptr); + nodes_[ast_node->node_id.value] = sem_node; + } + + /// Replace replaces any existing semantic node `sem_node` for the AST node `ast_node`. + /// @param ast_node the AST node + /// @param sem_node the new semantic node + template + void Replace(const AST* ast_node, const SemanticNodeTypeFor* sem_node) { + Reserve(ast_node->node_id); + nodes_[ast_node->node_id.value] = sem_node; + } + + /// Assigns the semantic module. + /// @param module the module to assign. + void SetModule(sem::Module* module) { module_ = module; } + + /// @returns the semantic module. + const sem::Module* Module() const { return module_; } + + /// Determines the severity of a filterable diagnostic rule for the AST node `ast_node`. + /// @param ast_node the AST node + /// @param rule the diagnostic rule + /// @returns the severity of the rule for that AST node + wgsl::DiagnosticSeverity DiagnosticSeverity(const ast::Node* ast_node, + wgsl::DiagnosticRule rule) const; + + private: + // AST node index to semantic node + tint::Vector nodes_; + // The semantic module + sem::Module* module_ = nullptr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_INFO_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/load.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/load.cc new file mode 100644 index 000000000..7ea267d03 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/load.cc @@ -0,0 +1,49 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/load.h" + +#include "src/tint/lang/core/type/memory_view.h" +#include "src/tint/utils/ice/ice.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Load); + +namespace tint::sem { +Load::Load(const ValueExpression* src, const Statement* statement, core::EvaluationStage stage) + : Base(/* declaration */ src->Declaration(), + /* type */ src->Type()->UnwrapPtrOrRef(), + /* stage */ stage, + /* statement */ statement, + /* constant */ nullptr, + /* root_ident */ src->RootIdentifier()), + source_(src) { + TINT_ASSERT(src->Type()->Is()); +} + +Load::~Load() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/load.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/load.h new file mode 100644 index 000000000..a635df6d3 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/load.h @@ -0,0 +1,58 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_LOAD_H_ +#define SRC_TINT_LANG_WGSL_SEM_LOAD_H_ + +#include "src/tint/lang/wgsl/sem/value_expression.h" + +namespace tint::sem { + +/// Load is a semantic expression which represents the load of a memory view to a value. +/// Loads from reference types are implicit in WGSL, so the Load semantic node shares the same AST +/// node as the inner semantic node. +class Load final : public Castable { + public: + /// Constructor + /// @param source the source expression being loaded from + /// @param statement the statement that owns this expression + /// @param stage the earliest evaluation stage for the expression + Load(const ValueExpression* source, const Statement* statement, core::EvaluationStage stage); + + /// Destructor + ~Load() override; + + /// @return the source object being loaded + const ValueExpression* Source() const { return source_; } + + private: + ValueExpression const* const source_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_LOAD_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.cc new file mode 100644 index 000000000..810594734 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.cc @@ -0,0 +1,61 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/loop_statement.h" + +#include "src/tint/lang/wgsl/ast/block_statement.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::LoopStatement); +TINT_INSTANTIATE_TYPEINFO(tint::sem::LoopContinuingBlockStatement); + +namespace tint::sem { + +LoopStatement::LoopStatement(const ast::LoopStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) { + TINT_ASSERT(parent); + TINT_ASSERT(function); +} + +LoopStatement::~LoopStatement() = default; + +LoopContinuingBlockStatement::LoopContinuingBlockStatement(const ast::BlockStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) { + TINT_ASSERT(parent); + TINT_ASSERT(function); +} +LoopContinuingBlockStatement::~LoopContinuingBlockStatement() = default; + +const ast::BlockStatement* LoopContinuingBlockStatement::Declaration() const { + return static_cast(Base::Declaration()); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.h new file mode 100644 index 000000000..396a3abe8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/loop_statement.h @@ -0,0 +1,76 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_LOOP_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_LOOP_STATEMENT_H_ + +#include "src/tint/lang/wgsl/sem/block_statement.h" + +// Forward declarations +namespace tint::ast { +class LoopStatement; +} // namespace tint::ast + +namespace tint::sem { + +/// Holds semantic information about a loop statement +class LoopStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this loop statement + /// @param parent the owning statement + /// @param function the owning function + LoopStatement(const ast::LoopStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~LoopStatement() override; +}; + +/// Holds semantic information about a loop continuing block +class LoopContinuingBlockStatement final + : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this block statement + /// @param parent the owning statement + /// @param function the owning function + LoopContinuingBlockStatement(const ast::BlockStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~LoopContinuingBlockStatement() override; + + /// @returns the AST node + const ast::BlockStatement* Declaration() const; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_LOOP_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.cc new file mode 100644 index 000000000..1be584d43 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.cc @@ -0,0 +1,48 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/materialize.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Materialize); + +namespace tint::sem { +Materialize::Materialize(const ValueExpression* expr, + const Statement* statement, + const core::type::Type* type, + const core::constant::Value* constant) + : Base(/* declaration */ expr->Declaration(), + /* type */ type, + /* stage */ + constant ? core::EvaluationStage::kConstant : core::EvaluationStage::kNotEvaluated, + /* statement */ statement, + /* constant */ constant, + /* root_ident */ expr->RootIdentifier()), + expr_(expr) {} + +Materialize::~Materialize() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.h new file mode 100644 index 000000000..013c5ce37 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/materialize.h @@ -0,0 +1,65 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_MATERIALIZE_H_ +#define SRC_TINT_LANG_WGSL_SEM_MATERIALIZE_H_ + +#include "src/tint/lang/wgsl/sem/value_expression.h" + +namespace tint::sem { + +/// Materialize is a semantic expression which represents the materialization of a value of an +/// abstract numeric type to a value of a concrete type. +/// Abstract numeric materialization is implicit in WGSL, so the Materialize semantic node shares +/// the same AST node as the inner semantic node. +/// Abstract numerics types may only be used by compile-time expressions, so a Materialize semantic +/// node must have a valid Constant value. +class Materialize final : public Castable { + public: + /// Constructor + /// @param expr the inner expression, being materialized + /// @param statement the statement that owns this expression + /// @param type concrete type to materialize to + /// @param constant the constant value of this expression or nullptr + Materialize(const ValueExpression* expr, + const Statement* statement, + const core::type::Type* type, + const core::constant::Value* constant); + + /// Destructor + ~Materialize() override; + + /// @return the expression being materialized + const ValueExpression* Expr() const { return expr_; } + + private: + ValueExpression const* const expr_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_MATERIALIZE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.cc new file mode 100644 index 000000000..b019b92da --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.cc @@ -0,0 +1,62 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/member_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/member_accessor_expression.h" + +#include + +TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMemberAccess); +TINT_INSTANTIATE_TYPEINFO(tint::sem::Swizzle); + +namespace tint::sem { + +StructMemberAccess::StructMemberAccess(const ast::MemberAccessorExpression* declaration, + const core::type::Type* type, + const Statement* statement, + const core::constant::Value* constant, + const ValueExpression* object, + const core::type::StructMember* member, + const Variable* root_ident /* = nullptr */) + : Base(declaration, type, object->Stage(), object, statement, constant, root_ident), + member_(member) {} + +StructMemberAccess::~StructMemberAccess() = default; + +Swizzle::Swizzle(const ast::MemberAccessorExpression* declaration, + const core::type::Type* type, + const Statement* statement, + const core::constant::Value* constant, + const ValueExpression* object, + VectorRef indices, + const Variable* root_ident /* = nullptr */) + : Base(declaration, type, object->Stage(), object, statement, constant, root_ident), + indices_(std::move(indices)) {} + +Swizzle::~Swizzle() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.h new file mode 100644 index 000000000..bb6c423a4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/member_accessor_expression.h @@ -0,0 +1,107 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_MEMBER_ACCESSOR_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_MEMBER_ACCESSOR_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/sem/accessor_expression.h" +#include "src/tint/utils/containers/vector.h" + +// Forward declarations +namespace tint::ast { +class MemberAccessorExpression; +} // namespace tint::ast +namespace tint::core::type { +class StructMember; +} // namespace tint::core::type + +namespace tint::sem { + +/// StructMemberAccess holds the semantic information for a +/// ast::MemberAccessorExpression node that represents an access to a structure +/// member. +class StructMemberAccess final : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param type the resolved type of the expression + /// @param statement the statement that owns this expression + /// @param constant the constant value of the expression. May be null + /// @param object the object that holds the member being accessed + /// @param member the structure member + /// @param root_ident the (optional) root identifier for this expression + StructMemberAccess(const ast::MemberAccessorExpression* declaration, + const core::type::Type* type, + const Statement* statement, + const core::constant::Value* constant, + const ValueExpression* object, + const core::type::StructMember* member, + const Variable* root_ident = nullptr); + + /// Destructor + ~StructMemberAccess() override; + + /// @returns the structure member + core::type::StructMember const* Member() const { return member_; } + + private: + core::type::StructMember const* const member_; +}; + +/// Swizzle holds the semantic information for a ast::MemberAccessorExpression +/// node that represents a vector swizzle. +class Swizzle final : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param type the resolved type of the expression + /// @param statement the statement that owns this expression + /// @param constant the constant value of the expression. May be null + /// @param object the object that holds the member being accessed + /// @param indices the swizzle indices + /// @param root_ident the (optional) root identifier for this expression + Swizzle(const ast::MemberAccessorExpression* declaration, + const core::type::Type* type, + const Statement* statement, + const core::constant::Value* constant, + const ValueExpression* object, + VectorRef indices, + const Variable* root_ident = nullptr); + + /// Destructor + ~Swizzle() override; + + /// @return the swizzle indices, if this is a vector swizzle + const auto& Indices() const { return indices_; } + + private: + tint::Vector const indices_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_MEMBER_ACCESSOR_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/module.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/module.cc new file mode 100644 index 000000000..d38de3910 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/module.cc @@ -0,0 +1,45 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/module.h" + +#include + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Module); + +namespace tint::sem { + +Module::Module(VectorRef dep_ordered_decls, wgsl::Extensions extensions) + : dep_ordered_decls_(std::move(dep_ordered_decls)), extensions_(std::move(extensions)) {} + +Module::~Module() = default; + +void Module::SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) { + diagnostic_severities_.Add(rule, severity); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/module.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/module.h new file mode 100644 index 000000000..db6ff325e --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/module.h @@ -0,0 +1,78 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_MODULE_H_ +#define SRC_TINT_LANG_WGSL_SEM_MODULE_H_ + +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/sem/node.h" +#include "src/tint/utils/containers/vector.h" + +// Forward declarations +namespace tint::ast { +class Node; +} // namespace tint::ast + +namespace tint::sem { + +/// Module holds the top-level semantic types, functions and global variables +/// used by a Program. +class Module final : public Castable { + public: + /// Constructor + /// @param dep_ordered_decls the dependency-ordered module-scope declarations + /// @param extensions the list of enabled extensions in the module + Module(VectorRef dep_ordered_decls, wgsl::Extensions extensions); + + /// Destructor + ~Module() override; + + /// @returns the dependency-ordered global declarations for the module + VectorRef DependencyOrderedDeclarations() const { return dep_ordered_decls_; } + + /// @returns the list of enabled extensions in the module + const wgsl::Extensions& Extensions() const { return extensions_; } + + /// Modifies the severity of a specific diagnostic rule for this module. + /// @param rule the diagnostic rule + /// @param severity the new diagnostic severity + void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity); + + /// @returns the diagnostic severity modifications applied to this module + const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const { + return diagnostic_severities_; + } + + private: + const tint::Vector dep_ordered_decls_; + wgsl::Extensions extensions_; + wgsl::DiagnosticRuleSeverities diagnostic_severities_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_MODULE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/node.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/node.cc new file mode 100644 index 000000000..415e82863 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/node.cc @@ -0,0 +1,40 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/node.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Node); + +namespace tint::sem { + +Node::Node() = default; + +Node::Node(const Node&) = default; + +Node::~Node() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/node.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/node.h new file mode 100644 index 000000000..3937ab91b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/node.h @@ -0,0 +1,50 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_NODE_H_ +#define SRC_TINT_LANG_WGSL_SEM_NODE_H_ + +#include "src/tint/utils/rtti/castable.h" + +namespace tint::sem { + +/// Node is the base class for all semantic nodes +class Node : public Castable { + public: + /// Constructor + Node(); + + /// Copy constructor + Node(const Node&); + + /// Destructor + ~Node() override; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_NODE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/pipeline_stage_set.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/pipeline_stage_set.h new file mode 100644 index 000000000..8c2e69fab --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/pipeline_stage_set.h @@ -0,0 +1,41 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_PIPELINE_STAGE_SET_H_ +#define SRC_TINT_LANG_WGSL_SEM_PIPELINE_STAGE_SET_H_ + +#include "src/tint/lang/wgsl/ast/pipeline_stage.h" +#include "src/tint/utils/containers/enum_set.h" + +namespace tint::sem { + +/// A set of PipelineStage +using PipelineStageSet = tint::EnumSet; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_PIPELINE_STAGE_SET_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/sampler_texture_pair.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/sampler_texture_pair.h new file mode 100644 index 000000000..beee4f0c6 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/sampler_texture_pair.h @@ -0,0 +1,102 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_SAMPLER_TEXTURE_PAIR_H_ +#define SRC_TINT_LANG_WGSL_SEM_SAMPLER_TEXTURE_PAIR_H_ + +#include + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/utils/reflection.h" + +namespace tint::sem { + +/// Mapping of a sampler to a texture it samples. +struct SamplerTexturePair { + /// group & binding values for a sampler. + BindingPoint sampler_binding_point; + /// group & binding values for a texture samepled by the sampler. + BindingPoint texture_binding_point; + + /// Equality operator + /// @param rhs the SamplerTexturePair to compare against + /// @returns true if this SamplerTexturePair is equal to `rhs` + inline bool operator==(const SamplerTexturePair& rhs) const { + return sampler_binding_point == rhs.sampler_binding_point && + texture_binding_point == rhs.texture_binding_point; + } + + /// Inequality operator + /// @param rhs the SamplerTexturePair to compare against + /// @returns true if this SamplerTexturePair is not equal to `rhs` + inline bool operator!=(const SamplerTexturePair& rhs) const { return !(*this == rhs); } + + /// Less than operator + /// @param rhs the SamplerTexturePair to compare against + /// @returns true if this SamplerTexturePair is less then `rhs` + inline bool operator<(const SamplerTexturePair& rhs) const { + if (sampler_binding_point == rhs.sampler_binding_point) { + return texture_binding_point < rhs.texture_binding_point; + } + return sampler_binding_point < rhs.sampler_binding_point; + } + + /// Reflect the fields of this class so that it can be used by tint::ForeachField() + TINT_REFLECT(SamplerTexturePair, sampler_binding_point, texture_binding_point); +}; + +/// Prints the SamplerTexturePair @p stp to @p o +/// @param o the stream to write to +/// @param stp the SamplerTexturePair +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, const SamplerTexturePair& stp) { + return o << "[sampler: " << stp.sampler_binding_point + << ", texture: " << stp.sampler_binding_point << "]"; +} + +} // namespace tint::sem + +namespace std { + +/// Custom std::hash specialization for tint::sem::SamplerTexturePair so +/// SamplerTexturePairs be used as keys for std::unordered_map and +/// std::unordered_set. +template <> +class hash { + public: + /// @param stp the texture pair to create a hash for + /// @return the hash value + inline std::size_t operator()(const tint::sem::SamplerTexturePair& stp) const { + return Hash(stp.sampler_binding_point, stp.texture_binding_point); + } +}; + +} // namespace std + +#endif // SRC_TINT_LANG_WGSL_SEM_SAMPLER_TEXTURE_PAIR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/statement.cc new file mode 100644 index 000000000..012f13dc8 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/statement.cc @@ -0,0 +1,67 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/ast/statement.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/variable.h" +#include "src/tint/lang/wgsl/sem/block_statement.h" +#include "src/tint/lang/wgsl/sem/statement.h" +#include "src/tint/lang/wgsl/sem/variable.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Statement); +TINT_INSTANTIATE_TYPEINFO(tint::sem::CompoundStatement); + +namespace tint::sem { + +Statement::Statement(const ast::Statement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : declaration_(declaration), parent_(parent), function_(function) {} + +Statement::~Statement() = default; + +const BlockStatement* Statement::Block() const { + return FindFirstParent(); +} + +void Statement::SetDiagnosticSeverity(wgsl::DiagnosticRule rule, + wgsl::DiagnosticSeverity severity) { + diagnostic_severities_.Add(rule, severity); +} + +CompoundStatement::CompoundStatement(const ast::Statement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) {} + +CompoundStatement::~CompoundStatement() = default; + +void CompoundStatement::AddDecl(const sem::LocalVariable* var) { + decls_.Add(var->Declaration()->name->symbol, OrderedLocalVariable{decls_.Count(), var}); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/statement.h new file mode 100644 index 000000000..655da21d4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/statement.h @@ -0,0 +1,225 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_STATEMENT_H_ + +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/sem/behavior.h" +#include "src/tint/lang/wgsl/sem/node.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/symbol/symbol.h" + +// Forward declarations +namespace tint::ast { +class Statement; +} // namespace tint::ast +namespace tint::sem { +class BlockStatement; +class CompoundStatement; +class Function; +class LocalVariable; +} // namespace tint::sem + +namespace tint::sem { +namespace detail { +/// FindFirstParentReturn is a traits helper for determining the return type for +/// the template member function Statement::FindFirstParent(). +/// For zero or multiple template arguments, FindFirstParentReturn::type +/// resolves to CompoundStatement. +template +struct FindFirstParentReturn { + /// The pointer type returned by Statement::FindFirstParent() + using type = CompoundStatement; +}; + +/// A specialization of FindFirstParentReturn for a single template argument. +/// FindFirstParentReturn::type resolves to the single template argument. +template +struct FindFirstParentReturn { + /// The pointer type returned by Statement::FindFirstParent() + using type = T; +}; + +template +using FindFirstParentReturnType = typename FindFirstParentReturn::type; +} // namespace detail + +/// Statement holds the semantic information for a statement. +class Statement : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this statement + /// @param parent the owning statement + /// @param function the owning function + Statement(const ast::Statement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~Statement() override; + + /// @return the AST node for this statement + const ast::Statement* Declaration() const { return declaration_; } + + /// @return the statement that encloses this statement + const CompoundStatement* Parent() const { return parent_; } + + /// @returns the closest enclosing parent that satisfies the given predicate, + /// which may be the statement itself, or nullptr if no match is found. + /// @param pred a predicate that the resulting block must satisfy + template + const CompoundStatement* FindFirstParent(Pred&& pred) const; + + /// @returns the closest enclosing parent that is of one of the types in + /// `TYPES`, which may be the statement itself, or nullptr if no match is + /// found. If `TYPES` is a single template argument, the return type is a + /// pointer to that template argument type, otherwise a CompoundStatement + /// pointer is returned. + template + const sem::detail::FindFirstParentReturnType* FindFirstParent() const; + + /// @return the closest enclosing block for this statement + const BlockStatement* Block() const; + + /// @returns the function that owns this statement + const sem::Function* Function() const { return function_; } + + /// @return the behaviors of this statement + const sem::Behaviors& Behaviors() const { return behaviors_; } + + /// @return the behaviors of this statement + sem::Behaviors& Behaviors() { return behaviors_; } + + /// @returns true if this statement is reachable by control flow according to + /// the behavior analysis + bool IsReachable() const { return is_reachable_; } + + /// @param is_reachable whether this statement is reachable by control flow + /// according to the behavior analysis + void SetIsReachable(bool is_reachable) { is_reachable_ = is_reachable; } + + /// Modifies the severity of a specific diagnostic rule for this statement. + /// @param rule the diagnostic rule + /// @param severity the new diagnostic severity + void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity); + + /// @returns the diagnostic severity modifications applied to this statement + const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const { + return diagnostic_severities_; + } + + private: + const ast::Statement* const declaration_; + const CompoundStatement* const parent_; + const sem::Function* const function_; + sem::Behaviors behaviors_{sem::Behavior::kNext}; + bool is_reachable_ = true; + wgsl::DiagnosticRuleSeverities diagnostic_severities_; +}; + +/// CompoundStatement is the base class of statements that can hold other +/// statements. +class CompoundStatement : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this statement + /// @param statement the owning statement + /// @param function the owning function + CompoundStatement(const ast::Statement* declaration, + const CompoundStatement* statement, + const sem::Function* function); + + /// Destructor + ~CompoundStatement() override; + + /// OrderedLocalVariable describes a local variable declaration, and order of declaration. + struct OrderedLocalVariable { + /// The 0-based declaration order index of the variable + size_t order; + /// The variable + const LocalVariable* variable; + }; + + /// @returns a map of variable name to variable declarations associated with this block + const Hashmap& Decls() const { return decls_; } + + /// Associates a declaration with this block. + /// @note this method must be called in variable declaration order + /// @param var a variable declaration to be added to the block + void AddDecl(const LocalVariable* var); + + private: + Hashmap decls_; +}; + +template +const CompoundStatement* Statement::FindFirstParent(Pred&& pred) const { + if (auto* self = As()) { + if (pred(self)) { + return self; + } + } + const auto* curr = parent_; + while (curr && !pred(curr)) { + curr = curr->Parent(); + } + return curr; +} + +template +const sem::detail::FindFirstParentReturnType* Statement::FindFirstParent() const { + using ReturnType = sem::detail::FindFirstParentReturnType; + if (sizeof...(TYPES) == 1) { + if (auto* p = As()) { + return p; + } + const auto* curr = parent_; + while (curr) { + if (auto* p = curr->As()) { + return p; + } + curr = curr->Parent(); + } + } else { + if (IsAnyOf()) { + return As(); + } + const auto* curr = parent_; + while (curr) { + if (curr->IsAnyOf()) { + return curr->As(); + } + curr = curr->Parent(); + } + } + return nullptr; +} + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/struct.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/struct.cc new file mode 100644 index 000000000..4fa87a120 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/struct.cc @@ -0,0 +1,61 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/struct.h" + +#include "src/tint/lang/wgsl/ast/struct_member.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Struct); +TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember); + +namespace tint::sem { + +Struct::Struct(const ast::Struct* declaration, + Symbol name, + VectorRef members, + uint32_t size) + : Base(name, members, size), declaration_(declaration) { + TINT_ASSERT(declaration != nullptr); +} + +Struct::~Struct() = default; + +StructMember::StructMember(const ast::StructMember* declaration, + Symbol name, + const core::type::Type* type, + uint32_t index, + uint32_t offset, + uint32_t align, + uint32_t size, + const core::IOAttributes& attributes) + : Base(name, type, index, offset, align, size, attributes), declaration_(declaration) { + TINT_ASSERT(declaration != nullptr); +} + +StructMember::~StructMember() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/struct.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/struct.h new file mode 100644 index 000000000..4e4d60c97 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/struct.h @@ -0,0 +1,116 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_STRUCT_H_ +#define SRC_TINT_LANG_WGSL_SEM_STRUCT_H_ + +#include "src/tint/lang/core/type/struct.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/wgsl/ast/struct.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/symbol/symbol.h" + +// Forward declarations +namespace tint::ast { +class StructMember; +} // namespace tint::ast +namespace tint::sem { +class StructMember; +} // namespace tint::sem +namespace tint::core::type { +class StructMember; +} // namespace tint::core::type + +namespace tint::sem { + +/// Struct holds the semantic information for structures. +/// Unlike core::type::Struct, sem::Struct has an AST declaration node. +class Struct final : public Castable { + public: + /// Constructor + /// @param declaration the AST structure declaration + /// @param name the name of the structure + /// @param members the structure members + /// @param size the byte size of the structure + Struct(const ast::Struct* declaration, + Symbol name, + VectorRef members, + uint32_t size); + + /// Destructor + ~Struct() override; + + /// @returns the struct + const ast::Struct* Declaration() const { return declaration_; } + + /// @returns the members of the structure + VectorRef Members() const { + return Base::Members().ReinterpretCast(); + } + + private: + ast::Struct const* const declaration_; +}; + +/// StructMember holds the semantic information for structure members. +/// Unlike core::type::StructMember, sem::StructMember has an AST declaration node. +class StructMember final : public Castable { + public: + /// Constructor + /// @param declaration the AST declaration node + /// @param name the name of the structure member + /// @param type the type of the member + /// @param index the index of the member in the structure + /// @param offset the byte offset from the base of the structure + /// @param align the byte alignment of the member + /// @param size the byte size of the member + /// @param attributes the optional attributes + StructMember(const ast::StructMember* declaration, + Symbol name, + const core::type::Type* type, + uint32_t index, + uint32_t offset, + uint32_t align, + uint32_t size, + const core::IOAttributes& attributes); + + /// Destructor + ~StructMember() override; + + /// @returns the AST declaration node + const ast::StructMember* Declaration() const { return declaration_; } + + /// @returns the structure that owns this member + const sem::Struct* Struct() const { return static_cast(Base::Struct()); } + + private: + const ast::StructMember* const declaration_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_STRUCT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.cc new file mode 100644 index 000000000..2f625b6d1 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.cc @@ -0,0 +1,71 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/switch_statement.h" + +#include "src/tint/lang/wgsl/ast/case_statement.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::CaseStatement); +TINT_INSTANTIATE_TYPEINFO(tint::sem::CaseSelector); +TINT_INSTANTIATE_TYPEINFO(tint::sem::SwitchStatement); + +namespace tint::sem { + +SwitchStatement::SwitchStatement(const ast::SwitchStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) { + TINT_ASSERT(parent); + TINT_ASSERT(function); +} + +SwitchStatement::~SwitchStatement() = default; + +CaseStatement::CaseStatement(const ast::CaseStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) { + TINT_ASSERT(parent); + TINT_ASSERT(function); +} +CaseStatement::~CaseStatement() = default; + +const ast::CaseStatement* CaseStatement::Declaration() const { + return static_cast(Base::Declaration()); +} + +CaseSelector::CaseSelector(const ast::CaseSelector* decl, const core::constant::Value* val) + : Base(), decl_(decl), val_(val) {} + +CaseSelector::~CaseSelector() = default; + +const ast::CaseSelector* CaseSelector::Declaration() const { + return decl_; +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.h new file mode 100644 index 000000000..6cbf1cdda --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/switch_statement.h @@ -0,0 +1,138 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_SWITCH_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_SWITCH_STATEMENT_H_ + +#include + +#include "src/tint/lang/wgsl/sem/block_statement.h" + +// Forward declarations +namespace tint::ast { +class CaseStatement; +class CaseSelector; +class SwitchStatement; +} // namespace tint::ast +namespace tint::core::constant { +class Value; +} // namespace tint::core::constant +namespace tint::sem { +class CaseStatement; +class CaseSelector; +class ValueExpression; +} // namespace tint::sem + +namespace tint::sem { + +/// Holds semantic information about an switch statement +class SwitchStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this switch statement + /// @param parent the owning statement + /// @param function the owning function + SwitchStatement(const ast::SwitchStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~SwitchStatement() override; + + /// @returns the case statements for this switch + std::vector& Cases() { return cases_; } + + /// @returns the case statements for this switch + const std::vector& Cases() const { return cases_; } + + private: + std::vector cases_; +}; + +/// Holds semantic information about a switch case statement +class CaseStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this case statement + /// @param parent the owning statement + /// @param function the owning function + CaseStatement(const ast::CaseStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~CaseStatement() override; + + /// @return the AST node for this statement + const ast::CaseStatement* Declaration() const; + + /// @param body the case body block statement + void SetBlock(const BlockStatement* body) { body_ = body; } + + /// @returns the case body block statement + const BlockStatement* Body() const { return body_; } + + /// @returns the selectors for the case + std::vector& Selectors() { return selectors_; } + + /// @returns the selectors for the case + const std::vector& Selectors() const { return selectors_; } + + private: + const BlockStatement* body_ = nullptr; + std::vector selectors_; +}; + +/// Holds semantic information about a switch case selector +class CaseSelector final : public Castable { + public: + /// Constructor + /// @param decl the selector declaration + /// @param val the case selector value, nullptr for a default selector + explicit CaseSelector(const ast::CaseSelector* decl, + const core::constant::Value* val = nullptr); + + /// Destructor + ~CaseSelector() override; + + /// @returns true if this is a default selector + bool IsDefault() const { return val_ == nullptr; } + + /// @returns the case selector declaration + const ast::CaseSelector* Declaration() const; + + /// @returns the selector constant value, or nullptr if this is the default selector + const core::constant::Value* Value() const { return val_; } + + private: + const ast::CaseSelector* const decl_; + const core::constant::Value* const val_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_SWITCH_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.cc new file mode 100644 index 000000000..356b8deb7 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.cc @@ -0,0 +1,41 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/type_expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::TypeExpression); + +namespace tint::sem { + +TypeExpression::TypeExpression(const ast::Expression* declaration, + const Statement* statement, + const core::type::Type* type) + : Base(declaration, statement), type_(type) {} + +TypeExpression::~TypeExpression() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.h new file mode 100644 index 000000000..e3c1ea5fd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/type_expression.h @@ -0,0 +1,67 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_TYPE_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_TYPE_EXPRESSION_H_ + +#include "src/tint/lang/wgsl/sem/expression.h" + +// Forward declarations +namespace tint::core::type { +class Type; +} // namespace tint::core::type + +namespace tint::sem { + +/// TypeExpression holds the semantic information for expression nodes that resolve to types. +class TypeExpression : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + /// @param type the type that this expression resolved to + TypeExpression(const ast::Expression* declaration, + const Statement* statement, + const core::type::Type* type); + + /// Destructor + ~TypeExpression() override; + + /// @return the type that the expression resolved to + const core::type::Type* Type() const { return type_; } + + /// Sets the type that this expression resolved to + /// @param type the new type + void SetType(const core::type::Type* type) { type_ = type; } + + private: + const core::type::Type* type_ = nullptr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_TYPE_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/type_mappings.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/type_mappings.h new file mode 100644 index 000000000..ab1c7ce50 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/type_mappings.h @@ -0,0 +1,120 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_TYPE_MAPPINGS_H_ +#define SRC_TINT_LANG_WGSL_SEM_TYPE_MAPPINGS_H_ + +#include + +// Forward declarations +namespace tint { +class CastableBase; +} // namespace tint +namespace tint::ast { +class AccessorExpression; +class BinaryExpression; +class BlockStatement; +class CallExpression; +class Expression; +class ForLoopStatement; +class Function; +class IfStatement; +class LiteralExpression; +class Node; +class Override; +class Parameter; +class PhonyExpression; +class Statement; +class Struct; +class StructMember; +class SwitchStatement; +class TypeDecl; +class UnaryOpExpression; +class Variable; +class WhileStatement; +} // namespace tint::ast +namespace tint::sem { +class BlockStatement; +class Expression; +class ForLoopStatement; +class Function; +class GlobalVariable; +class IfStatement; +class Parameter; +class Statement; +class Struct; +class StructMember; +class SwitchStatement; +class ValueExpression; +class Variable; +class WhileStatement; +} // namespace tint::sem +namespace tint::core::type { +class Type; +} // namespace tint::core::type + +namespace tint::sem { + +/// TypeMappings is a struct that holds undefined `operator()` methods that's +/// used by SemanticNodeTypeFor to map AST / type node types to their +/// corresponding semantic node types. The standard operator overload resolving +/// rules will be used to infer the return type based on the argument type. +struct TypeMappings { + //! @cond Doxygen_Suppress + BlockStatement* operator()(ast::BlockStatement*); + CastableBase* operator()(ast::Node*); + Expression* operator()(ast::Expression*); + ForLoopStatement* operator()(ast::ForLoopStatement*); + Function* operator()(ast::Function*); + GlobalVariable* operator()(ast::Override*); + IfStatement* operator()(ast::IfStatement*); + Parameter* operator()(ast::Parameter*); + Statement* operator()(ast::Statement*); + Struct* operator()(ast::Struct*); + StructMember* operator()(ast::StructMember*); + SwitchStatement* operator()(ast::SwitchStatement*); + core::type::Type* operator()(ast::TypeDecl*); + ValueExpression* operator()(ast::AccessorExpression*); + ValueExpression* operator()(ast::BinaryExpression*); + ValueExpression* operator()(ast::CallExpression*); + ValueExpression* operator()(ast::LiteralExpression*); + ValueExpression* operator()(ast::PhonyExpression*); + ValueExpression* operator()(ast::UnaryOpExpression*); + Variable* operator()(ast::Variable*); + WhileStatement* operator()(ast::WhileStatement*); + //! @endcond +}; + +/// SemanticNodeTypeFor resolves to the appropriate sem::Node type for the +/// AST node `AST`. +template +using SemanticNodeTypeFor = + typename std::remove_pointer()))>::type; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_TYPE_MAPPINGS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.cc new file mode 100644 index 000000000..883772c1b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.cc @@ -0,0 +1,43 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/value_constructor.h" + +#include + +TINT_INSTANTIATE_TYPEINFO(tint::sem::ValueConstructor); + +namespace tint::sem { + +ValueConstructor::ValueConstructor(const core::type::Type* type, + VectorRef parameters, + core::EvaluationStage stage) + : Base(type, std::move(parameters), stage, /* must_use */ true) {} + +ValueConstructor::~ValueConstructor() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.h new file mode 100644 index 000000000..8968c4ceb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_constructor.h @@ -0,0 +1,53 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_VALUE_CONSTRUCTOR_H_ +#define SRC_TINT_LANG_WGSL_SEM_VALUE_CONSTRUCTOR_H_ + +#include "src/tint/lang/wgsl/sem/call_target.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint::sem { + +/// ValueConstructor is the CallTarget for a value constructor. +class ValueConstructor final : public Castable { + public: + /// Constructor + /// @param type the type that's being constructed + /// @param parameters the constructor parameters + /// @param stage the earliest evaluation stage for the expression + ValueConstructor(const core::type::Type* type, + VectorRef parameters, + core::EvaluationStage stage); + + /// Destructor + ~ValueConstructor() override; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_VALUE_CONSTRUCTOR_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.cc new file mode 100644 index 000000000..1168a02bb --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.cc @@ -0,0 +1,41 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/value_conversion.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::ValueConversion); + +namespace tint::sem { + +ValueConversion::ValueConversion(const core::type::Type* type, + sem::Parameter* parameter, + core::EvaluationStage stage) + : Base(type, tint::Vector{parameter}, stage, /* must_use */ true) {} + +ValueConversion::~ValueConversion() = default; + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.h new file mode 100644 index 000000000..0fcefb160 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_conversion.h @@ -0,0 +1,52 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_VALUE_CONVERSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_VALUE_CONVERSION_H_ + +#include "src/tint/lang/wgsl/sem/call_target.h" + +namespace tint::sem { + +/// ValueConversion is the CallTarget for a value conversion (cast). +class ValueConversion final : public Castable { + public: + /// Constructor + /// @param type the target type of the cast + /// @param parameter the type cast parameter + /// @param stage the earliest evaluation stage for the expression + ValueConversion(const core::type::Type* type, + sem::Parameter* parameter, + core::EvaluationStage stage); + + /// Destructor + ~ValueConversion() override; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_VALUE_CONVERSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.cc new file mode 100644 index 000000000..38af97ea0 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.cc @@ -0,0 +1,82 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/value_expression.h" + +#include + +#include "src/tint/lang/wgsl/sem/load.h" +#include "src/tint/lang/wgsl/sem/materialize.h" +#include "src/tint/utils/rtti/switch.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::ValueExpression); + +namespace tint::sem { + +ValueExpression::ValueExpression(const ast::Expression* declaration, + const core::type::Type* type, + core::EvaluationStage stage, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident /* = nullptr */) + : Base(declaration, statement), + root_identifier_(root_ident), + type_(type), + stage_(stage), + constant_(std::move(constant)) { + TINT_ASSERT(type_); + TINT_ASSERT((constant != nullptr) == (stage == core::EvaluationStage::kConstant)); + if (constant != nullptr) { + TINT_ASSERT(type_ == constant->Type()); + } +} + +ValueExpression::~ValueExpression() = default; + +const ValueExpression* ValueExpression::UnwrapMaterialize() const { + if (auto* m = As()) { + return m->Expr(); + } + return this; +} + +const ValueExpression* ValueExpression::UnwrapLoad() const { + if (auto* l = As()) { + return l->Source(); + } + return this; +} + +const ValueExpression* ValueExpression::Unwrap() const { + return Switch( + this, // note: An expression can only be wrapped by a Load or Materialize, not both. + [&](const Load* load) { return load->Source(); }, + [&](const Materialize* materialize) { return materialize->Expr(); }, + [&](Default) { return this; }); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.h new file mode 100644 index 000000000..672cea133 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/value_expression.h @@ -0,0 +1,101 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_VALUE_EXPRESSION_H_ +#define SRC_TINT_LANG_WGSL_SEM_VALUE_EXPRESSION_H_ + +#include "src/tint/lang/core/constant/value.h" +#include "src/tint/lang/core/evaluation_stage.h" +#include "src/tint/lang/wgsl/sem/behavior.h" +#include "src/tint/lang/wgsl/sem/expression.h" + +// Forward declarations +namespace tint::sem { +class Statement; +class Variable; +} // namespace tint::sem + +namespace tint::sem { + +/// ValueExpression holds the semantic information for expression nodes. +class ValueExpression : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param type the resolved type of the expression + /// @param stage the earliest evaluation stage for the expression + /// @param statement the statement that owns this expression + /// @param constant the constant value of the expression. May be null + /// @param root_ident the (optional) root identifier for this expression + ValueExpression(const ast::Expression* declaration, + const core::type::Type* type, + core::EvaluationStage stage, + const Statement* statement, + const core::constant::Value* constant, + const Variable* root_ident = nullptr); + + /// Destructor + ~ValueExpression() override; + + /// @return the resolved type of the expression + const core::type::Type* Type() const { return type_; } + + /// @return the earliest evaluation stage for the expression + core::EvaluationStage Stage() const { return stage_; } + + /// @return the constant value of this expression + const core::constant::Value* ConstantValue() const { return constant_; } + + /// Returns the variable or parameter that this expression derives from. + /// For reference and pointer expressions, this will either be the originating + /// variable or a function parameter. For other types of expressions, it will + /// either be the parameter or constant declaration, or nullptr. + /// @return the root identifier of this expression, or nullptr + const Variable* RootIdentifier() const { return root_identifier_; } + + /// @return the inner expression node if this is a Materialize, otherwise this. + const ValueExpression* UnwrapMaterialize() const; + + /// @return the inner reference expression if this is a Load, otherwise this. + const ValueExpression* UnwrapLoad() const; + + /// @return the inner expression node if this is a Materialize or Load, otherwise this. + const ValueExpression* Unwrap() const; + + protected: + /// The root identifier for this semantic expression, or nullptr + const Variable* root_identifier_; + + private: + const core::type::Type* const type_; + const core::EvaluationStage stage_; + const core::constant::Value* const constant_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_VALUE_EXPRESSION_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/variable.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/variable.cc new file mode 100644 index 000000000..8be7862e4 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/variable.cc @@ -0,0 +1,95 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/variable.h" + +#include + +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/wgsl/ast/identifier_expression.h" +#include "src/tint/lang/wgsl/ast/parameter.h" +#include "src/tint/lang/wgsl/ast/variable.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::Variable); +TINT_INSTANTIATE_TYPEINFO(tint::sem::GlobalVariable); +TINT_INSTANTIATE_TYPEINFO(tint::sem::LocalVariable); +TINT_INSTANTIATE_TYPEINFO(tint::sem::Parameter); +TINT_INSTANTIATE_TYPEINFO(tint::sem::VariableUser); + +namespace tint::sem { +Variable::Variable(const ast::Variable* declaration) : declaration_(declaration) {} + +Variable::~Variable() = default; + +LocalVariable::LocalVariable(const ast::Variable* declaration, const sem::Statement* statement) + : Base(declaration), statement_(statement) {} + +LocalVariable::~LocalVariable() = default; + +GlobalVariable::GlobalVariable(const ast::Variable* declaration) : Base(declaration) {} + +GlobalVariable::~GlobalVariable() = default; + +void GlobalVariable::AddTransitivelyReferencedOverride(const GlobalVariable* var) { + if (transitively_referenced_overrides_.Add(var)) { + for (auto* ref : var->TransitivelyReferencedOverrides()) { + AddTransitivelyReferencedOverride(ref); + } + } +} + +Parameter::Parameter(const ast::Parameter* declaration, + uint32_t index, + const core::type::Type* type /* = nullptr */, + core::ParameterUsage usage /* = core::ParameterUsage::kNone */) + : Base(declaration), index_(index), usage_(usage) { + SetType(type); +} + +Parameter::~Parameter() = default; + +VariableUser::VariableUser(const ast::IdentifierExpression* declaration, + core::EvaluationStage stage, + Statement* statement, + const core::constant::Value* constant, + sem::Variable* variable) + : Base(declaration, variable->Type(), stage, statement, constant), variable_(variable) { + auto* type = variable->Type(); + if (type->Is() && variable->Initializer()) { + root_identifier_ = variable->Initializer()->RootIdentifier(); + } else { + root_identifier_ = variable; + } +} + +VariableUser::~VariableUser() = default; + +const ast::IdentifierExpression* VariableUser::Declaration() const { + return static_cast(Base::Declaration()); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/variable.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/variable.h new file mode 100644 index 000000000..9c51c56fc --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/variable.h @@ -0,0 +1,284 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_VARIABLE_H_ +#define SRC_TINT_LANG_WGSL_SEM_VARIABLE_H_ + +#include + +#include "src/tint/api/common/override_id.h" + +#include "src/tint/api/common/binding_point.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/wgsl/ast/parameter.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/utils/containers/unique_vector.h" + +// Forward declarations +namespace tint::ast { +class IdentifierExpression; +class Parameter; +class Variable; +} // namespace tint::ast +namespace tint::sem { +class CallTarget; +class VariableUser; +} // namespace tint::sem + +namespace tint::sem { + +/// Variable is the base class for local variables, global variables and +/// parameters. +class Variable : public Castable { + public: + /// Constructor + /// @param declaration the AST declaration node + explicit Variable(const ast::Variable* declaration); + + /// Destructor + ~Variable() override; + + /// @returns the AST declaration node + const ast::Variable* Declaration() const { return declaration_; } + + /// @param type the variable type + void SetType(const core::type::Type* type) { type_ = type; } + + /// @returns the canonical type for the variable + const core::type::Type* Type() const { return type_; } + + /// @param stage the evaluation stage for an expression of this variable type + void SetStage(core::EvaluationStage stage) { stage_ = stage; } + + /// @returns the evaluation stage for an expression of this variable type + core::EvaluationStage Stage() const { return stage_; } + + /// @param space the variable address space + void SetAddressSpace(core::AddressSpace space) { address_space_ = space; } + + /// @returns the address space for the variable + core::AddressSpace AddressSpace() const { return address_space_; } + + /// @param access the variable access control type + void SetAccess(core::Access access) { access_ = access; } + + /// @returns the access control for the variable + core::Access Access() const { return access_; } + + /// @param value the constant value for the variable. May be null + void SetConstantValue(const core::constant::Value* value) { constant_value_ = value; } + + /// @return the constant value of this expression + const core::constant::Value* ConstantValue() const { return constant_value_; } + + /// Sets the variable initializer expression. + /// @param initializer the initializer expression to assign to this variable. + void SetInitializer(const ValueExpression* initializer) { initializer_ = initializer; } + + /// @returns the variable initializer expression, or nullptr if the variable + /// does not have one. + const ValueExpression* Initializer() const { return initializer_; } + + /// @returns the expressions that use the variable + VectorRef Users() const { return users_; } + + /// @param user the user to add + void AddUser(const VariableUser* user) { users_.Push(user); } + + private: + const ast::Variable* const declaration_ = nullptr; + const core::type::Type* type_ = nullptr; + core::EvaluationStage stage_ = core::EvaluationStage::kRuntime; + core::AddressSpace address_space_ = core::AddressSpace::kUndefined; + core::Access access_ = core::Access::kUndefined; + const core::constant::Value* constant_value_ = nullptr; + const ValueExpression* initializer_ = nullptr; + tint::Vector users_; +}; + +/// LocalVariable is a function-scope variable +class LocalVariable final : public Castable { + public: + /// Constructor + /// @param declaration the AST declaration node + /// @param statement the statement that declared this local variable + LocalVariable(const ast::Variable* declaration, const sem::Statement* statement); + + /// Destructor + ~LocalVariable() override; + + /// @returns the statement that declares this local variable + const sem::Statement* Statement() const { return statement_; } + + /// Sets the Type, Function or Variable that this local variable shadows + /// @param shadows the Type, Function or Variable that this variable shadows + void SetShadows(const CastableBase* shadows) { shadows_ = shadows; } + + /// @returns the Type, Function or Variable that this local variable shadows + const CastableBase* Shadows() const { return shadows_; } + + private: + const sem::Statement* const statement_; + const CastableBase* shadows_ = nullptr; +}; + +/// Attributes that can be applied to global variables +struct GlobalVariableAttributes { + /// the pipeline constant ID associated with the variable + std::optional override_id; + /// the resource binding point for the variable, if set. + std::optional binding_point; + /// The `input_attachment_index` attribute value for the variable, if set + std::optional input_attachment_index; +}; + +/// GlobalVariable is a module-scope variable +class GlobalVariable final : public Castable { + public: + /// Constructor + /// @param declaration the AST declaration node + explicit GlobalVariable(const ast::Variable* declaration); + + /// Destructor + ~GlobalVariable() override; + + /// Records that this variable (transitively) references the given override variable. + /// @param var the module-scope override variable + void AddTransitivelyReferencedOverride(const GlobalVariable* var); + + /// @returns all transitively referenced override variables + VectorRef TransitivelyReferencedOverrides() const { + return transitively_referenced_overrides_; + } + + /// @return the mutable attributes for the variable + GlobalVariableAttributes& Attributes() { return attributes_; } + + /// @return the immutable attributes for the variable + const GlobalVariableAttributes& Attributes() const { return attributes_; } + + private: + tint::OverrideId override_id_; + UniqueVector transitively_referenced_overrides_; + GlobalVariableAttributes attributes_; +}; + +/// Attributes that can be applied to parameters +struct ParameterAttributes { + /// The `location` attribute value for the variable, if set + std::optional location; + /// The `blend_src` attribute value for the variable, if set + std::optional blend_src; + /// The `color` attribute value for the variable, if set + std::optional color; +}; + +/// Parameter is a function parameter +class Parameter final : public Castable { + public: + /// Constructor + /// @param declaration the AST declaration node + /// @param index the index of the parameter in the function + /// @param type the variable type + /// @param usage the parameter usage + Parameter(const ast::Parameter* declaration, + uint32_t index, + const core::type::Type* type = nullptr, + core::ParameterUsage usage = core::ParameterUsage::kNone); + + /// Destructor + ~Parameter() override; + + /// @returns the AST declaration node + const ast::Parameter* Declaration() const { + return static_cast(Variable::Declaration()); + } + + /// @return the index of the parameter in the function + uint32_t Index() const { return index_; } + + /// @returns the semantic usage for the parameter + core::ParameterUsage Usage() const { return usage_; } + + /// @param owner the CallTarget owner of this parameter + void SetOwner(const CallTarget* owner) { owner_ = owner; } + + /// @returns the CallTarget owner of this parameter + const CallTarget* Owner() const { return owner_; } + + /// Sets the Type, Function or Variable that this local variable shadows + /// @param shadows the Type, Function or Variable that this variable shadows + void SetShadows(const CastableBase* shadows) { shadows_ = shadows; } + + /// @returns the Type, Function or Variable that this local variable shadows + const CastableBase* Shadows() const { return shadows_; } + + /// @return the mutable attributes for the parameter + ParameterAttributes& Attributes() { return attributes_; } + + /// @return the immutable attributes for the parameter + const ParameterAttributes& Attributes() const { return attributes_; } + + private: + const uint32_t index_ = 0; + core::ParameterUsage usage_ = core::ParameterUsage::kNone; + CallTarget const* owner_ = nullptr; + const CastableBase* shadows_ = nullptr; + ParameterAttributes attributes_; +}; + +/// VariableUser holds the semantic information for an identifier expression +/// node that resolves to a variable. +class VariableUser final : public Castable { + public: + /// Constructor + /// @param declaration the AST identifier node + /// @param stage the evaluation stage for an expression of this variable type + /// @param statement the statement that owns this expression + /// @param constant the constant value of the expression. May be null + /// @param variable the semantic variable + VariableUser(const ast::IdentifierExpression* declaration, + core::EvaluationStage stage, + Statement* statement, + const core::constant::Value* constant, + sem::Variable* variable); + ~VariableUser() override; + + /// @returns the AST node + const ast::IdentifierExpression* Declaration() const; + + /// @returns the variable that this expression refers to + const sem::Variable* Variable() const { return variable_; } + + private: + const sem::Variable* const variable_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_VARIABLE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.cc b/3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.cc new file mode 100644 index 000000000..8ee74e110 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.cc @@ -0,0 +1,47 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/sem/while_statement.h" + +#include "src/tint/lang/wgsl/ast/while_statement.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::WhileStatement); + +namespace tint::sem { + +WhileStatement::WhileStatement(const ast::WhileStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function) + : Base(declaration, parent, function) {} + +WhileStatement::~WhileStatement() = default; + +const ast::WhileStatement* WhileStatement::Declaration() const { + return static_cast(Base::Declaration()); +} + +} // namespace tint::sem diff --git a/3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.h b/3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.h new file mode 100644 index 000000000..86ca2d36a --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/sem/while_statement.h @@ -0,0 +1,73 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_SEM_WHILE_STATEMENT_H_ +#define SRC_TINT_LANG_WGSL_SEM_WHILE_STATEMENT_H_ + +#include "src/tint/lang/wgsl/sem/statement.h" + +// Forward declarations +namespace tint::ast { +class WhileStatement; +} // namespace tint::ast +namespace tint::sem { +class ValueExpression; +} // namespace tint::sem + +namespace tint::sem { + +/// Holds semantic information about a while statement +class WhileStatement final : public Castable { + public: + /// Constructor + /// @param declaration the AST node for this while statement + /// @param parent the owning statement + /// @param function the owning function + WhileStatement(const ast::WhileStatement* declaration, + const CompoundStatement* parent, + const sem::Function* function); + + /// Destructor + ~WhileStatement() override; + + /// @returns the AST node + const ast::WhileStatement* Declaration() const; + + /// @returns the whilecondition expression + const ValueExpression* Condition() const { return condition_; } + + /// Sets the while condition expression + /// @param condition the while condition expression + void SetCondition(const ValueExpression* condition) { condition_ = condition; } + + private: + const ValueExpression* condition_ = nullptr; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_LANG_WGSL_SEM_WHILE_STATEMENT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc new file mode 100644 index 000000000..b87771f5b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc @@ -0,0 +1,1085 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/ast_printer/ast_printer.h" + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/wgsl/ast/accessor_expression.h" +#include "src/tint/lang/wgsl/ast/alias.h" +#include "src/tint/lang/wgsl/ast/assignment_statement.h" +#include "src/tint/lang/wgsl/ast/binary_expression.h" +#include "src/tint/lang/wgsl/ast/blend_src_attribute.h" +#include "src/tint/lang/wgsl/ast/bool_literal_expression.h" +#include "src/tint/lang/wgsl/ast/break_if_statement.h" +#include "src/tint/lang/wgsl/ast/break_statement.h" +#include "src/tint/lang/wgsl/ast/call_expression.h" +#include "src/tint/lang/wgsl/ast/call_statement.h" +#include "src/tint/lang/wgsl/ast/color_attribute.h" +#include "src/tint/lang/wgsl/ast/compound_assignment_statement.h" +#include "src/tint/lang/wgsl/ast/const.h" +#include "src/tint/lang/wgsl/ast/continue_statement.h" +#include "src/tint/lang/wgsl/ast/diagnostic_attribute.h" +#include "src/tint/lang/wgsl/ast/diagnostic_rule_name.h" +#include "src/tint/lang/wgsl/ast/discard_statement.h" +#include "src/tint/lang/wgsl/ast/float_literal_expression.h" +#include "src/tint/lang/wgsl/ast/for_loop_statement.h" +#include "src/tint/lang/wgsl/ast/id_attribute.h" +#include "src/tint/lang/wgsl/ast/identifier.h" +#include "src/tint/lang/wgsl/ast/identifier_expression.h" +#include "src/tint/lang/wgsl/ast/if_statement.h" +#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h" +#include "src/tint/lang/wgsl/ast/index_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h" +#include "src/tint/lang/wgsl/ast/int_literal_expression.h" +#include "src/tint/lang/wgsl/ast/interpolate_attribute.h" +#include "src/tint/lang/wgsl/ast/invariant_attribute.h" +#include "src/tint/lang/wgsl/ast/let.h" +#include "src/tint/lang/wgsl/ast/loop_statement.h" +#include "src/tint/lang/wgsl/ast/member_accessor_expression.h" +#include "src/tint/lang/wgsl/ast/module.h" +#include "src/tint/lang/wgsl/ast/must_use_attribute.h" +#include "src/tint/lang/wgsl/ast/override.h" +#include "src/tint/lang/wgsl/ast/phony_expression.h" +#include "src/tint/lang/wgsl/ast/return_statement.h" +#include "src/tint/lang/wgsl/ast/stage_attribute.h" +#include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h" +#include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h" +#include "src/tint/lang/wgsl/ast/subgroup_size_attribute.h" +#include "src/tint/lang/wgsl/ast/switch_statement.h" +#include "src/tint/lang/wgsl/ast/templated_identifier.h" +#include "src/tint/lang/wgsl/ast/unary_op_expression.h" +#include "src/tint/lang/wgsl/ast/var.h" +#include "src/tint/lang/wgsl/ast/variable_decl_statement.h" +#include "src/tint/lang/wgsl/ast/while_statement.h" +#include "src/tint/lang/wgsl/ast/workgroup_attribute.h" +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/reserved_words.h" +#include "src/tint/lang/wgsl/sem/member_accessor_expression.h" +#include "src/tint/lang/wgsl/sem/struct.h" +#include "src/tint/lang/wgsl/sem/switch_statement.h" +#include "src/tint/lang/wgsl/sem/value_expression.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/macros/scoped_assignment.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/strconv/float_to_string.h" +#include "src/tint/utils/text/string.h" + +namespace tint::wgsl::writer { + +ASTPrinter::ASTPrinter(const Program& program, const Options& options) + : program_(program), options_(options) {} + +ASTPrinter::~ASTPrinter() = default; + +bool ASTPrinter::Generate() { + if (options_.minify) { + BuildUnrenameableNames(); + } + + // Generate directives before any other global declarations. + bool has_directives = false; + for (auto enable : program_.AST().Enables()) { + EmitEnable(enable); + has_directives = true; + } + for (auto req : program_.AST().Requires()) { + EmitRequires(req); + has_directives = true; + } + for (auto diagnostic : program_.AST().DiagnosticDirectives()) { + auto out = Line(); + EmitDiagnosticControl(out, diagnostic->control); + out << ";"; + has_directives = true; + } + if (has_directives) { + Line(); + } + // Generate global declarations in the order they appear in the module. + bool has_declaration = false; + for (auto* decl : program_.AST().GlobalDeclarations()) { + if (decl->IsAnyOf()) { + continue; + } + if (has_declaration) { + Line(); + } + has_declaration = true; + Switch( + decl, // + [&](const ast::TypeDecl* td) { return EmitTypeDecl(td); }, + [&](const ast::Function* func) { return EmitFunction(func); }, + [&](const ast::Variable* var) { return EmitVariable(Line(), var); }, + [&](const ast::ConstAssert* ca) { return EmitConstAssert(ca); }, // + TINT_ICE_ON_NO_MATCH); + } + + return !diagnostics_.ContainsErrors(); +} + +std::string ASTPrinter::Result() const { + if (options_.minify) { + return main_buffer_.MinifiedString(); + } + return main_buffer_.String(); +} + +void ASTPrinter::EmitDiagnosticControl(StringStream& out, + const ast::DiagnosticControl& diagnostic) { + out << "diagnostic(" << diagnostic.severity << ", " << diagnostic.rule_name->String() << ")"; +} + +void ASTPrinter::EmitEnable(const ast::Enable* enable) { + auto out = Line(); + out << "enable "; + for (auto* ext : enable->extensions) { + if (ext != enable->extensions.Front()) { + out << ", "; + } + out << ext->name; + } + out << ";"; +} + +void ASTPrinter::EmitRequires(const ast::Requires* req) { + auto out = Line(); + out << "requires "; + bool first = true; + for (auto feature : req->features) { + if (!first) { + out << ", "; + } + out << wgsl::ToString(feature); + first = false; + } + out << ";"; +} + +void ASTPrinter::EmitTypeDecl(const ast::TypeDecl* ty) { + Switch( + ty, // + [&](const ast::Alias* alias) { + auto out = Line(); + out << "alias " << GetSymbolName(alias->name->symbol) << " = "; + EmitExpression(out, alias->type); + out << ";"; + }, + [&](const ast::Struct* str) { EmitStructType(str); }, // + TINT_ICE_ON_NO_MATCH); +} + +void ASTPrinter::EmitExpression(StringStream& out, const ast::Expression* expr) { + Switch( + expr, // + [&](const ast::IndexAccessorExpression* a) { EmitIndexAccessor(out, a); }, + [&](const ast::BinaryExpression* b) { EmitBinary(out, b); }, + [&](const ast::CallExpression* c) { EmitCall(out, c); }, + [&](const ast::IdentifierExpression* i) { EmitIdentifier(out, i); }, + [&](const ast::LiteralExpression* l) { EmitLiteral(out, l); }, + [&](const ast::MemberAccessorExpression* m) { EmitMemberAccessor(out, m); }, + [&](const ast::PhonyExpression*) { out << "_"; }, + [&](const ast::UnaryOpExpression* u) { EmitUnaryOp(out, u); }, // + TINT_ICE_ON_NO_MATCH); +} + +void ASTPrinter::EmitIndexAccessor(StringStream& out, const ast::IndexAccessorExpression* expr) { + bool paren_lhs = + !expr->object + ->IsAnyOf(); + if (paren_lhs) { + out << "("; + } + EmitExpression(out, expr->object); + if (paren_lhs) { + out << ")"; + } + out << "["; + + EmitExpression(out, expr->index); + out << "]"; +} + +void ASTPrinter::EmitMemberAccessor(StringStream& out, const ast::MemberAccessorExpression* expr) { + bool paren_lhs = + !expr->object + ->IsAnyOf(); + if (paren_lhs) { + out << "("; + } + EmitExpression(out, expr->object); + if (paren_lhs) { + out << ")"; + } + + auto* sem = program_.Sem().GetVal(expr->object); + auto* str = sem ? sem->Type()->UnwrapPtrOrRef()->As() : nullptr; + if (str && !str->IsWgslInternal()) { + // If we are accessing a non-builtin struct, we can minify the member name. + out << "." << GetSymbolName(expr->member->symbol); + } else { + // Builtin structure members and vector accessors are never renamed. + out << "." << expr->member->symbol.NameView(); + } +} + +void ASTPrinter::EmitCall(StringStream& out, const ast::CallExpression* expr) { + EmitExpression(out, expr->target); + out << "("; + + bool first = true; + const auto& args = expr->args; + for (auto* arg : args) { + if (!first) { + out << ", "; + } + first = false; + + EmitExpression(out, arg); + } + out << ")"; +} + +void ASTPrinter::EmitLiteral(StringStream& out, const ast::LiteralExpression* lit) { + Switch( + lit, // + [&](const ast::BoolLiteralExpression* l) { out << (l->value ? "true" : "false"); }, + [&](const ast::FloatLiteralExpression* l) { + // f16 literals are also emitted as float value with suffix "h". + // Note that all normal and subnormal f16 values are normal f32 values, and since NaN + // and Inf are not allowed to be spelled in literal, it should be fine to emit f16 + // literals in this way. + if (l->suffix == ast::FloatLiteralExpression::Suffix::kNone) { + out << tint::strconv::DoubleToBitPreservingString(l->value); + } else { + out << tint::strconv::FloatToBitPreservingString(static_cast(l->value)) + << l->suffix; + } + }, + [&](const ast::IntLiteralExpression* l) { out << l->value << l->suffix; }, // + TINT_ICE_ON_NO_MATCH); +} + +void ASTPrinter::EmitIdentifier(StringStream& out, const ast::IdentifierExpression* expr) { + EmitIdentifier(out, expr->identifier); +} + +void ASTPrinter::EmitIdentifier(StringStream& out, const ast::Identifier* ident) { + if (auto* tmpl_ident = ident->As()) { + out << GetSymbolName(ident->symbol) << "<"; + TINT_DEFER(out << ">"); + for (auto* expr : tmpl_ident->arguments) { + if (expr != tmpl_ident->arguments.Front()) { + out << ", "; + } + EmitExpression(out, expr); + } + } else { + out << GetSymbolName(ident->symbol); + } +} + +void ASTPrinter::EmitFunction(const ast::Function* func) { + if (func->attributes.Length()) { + EmitAttributes(Line(), func->attributes); + } + { + auto out = Line(); + out << "fn " << GetSymbolName(func->name->symbol) << "("; + + bool first = true; + for (auto* v : func->params) { + if (!first) { + out << ", "; + } + first = false; + + if (!v->attributes.IsEmpty()) { + EmitAttributes(out, v->attributes); + out << " "; + } + + out << GetSymbolName(v->name->symbol) << " : "; + + EmitExpression(out, v->type); + } + + out << ")"; + + if (func->return_type || !func->return_type_attributes.IsEmpty()) { + out << " -> "; + + if (!func->return_type_attributes.IsEmpty()) { + EmitAttributes(out, func->return_type_attributes); + out << " "; + } + + EmitExpression(out, func->return_type); + } + + if (func->body) { + out << " "; + EmitBlockHeader(out, func->body); + } + } + + if (func->body) { + EmitStatementsWithIndent(func->body->statements); + Line() << "}"; + } +} + +void ASTPrinter::EmitImageFormat(StringStream& out, const core::TexelFormat fmt) { + switch (fmt) { + case core::TexelFormat::kUndefined: + diagnostics_.AddError(Source{}) << "unknown image format"; + break; + default: + out << fmt; + break; + } +} + +void ASTPrinter::EmitStructType(const ast::Struct* str) { + if (str->attributes.Length()) { + EmitAttributes(Line(), str->attributes); + } + Line() << "struct " << GetSymbolName(str->name->symbol) << " {"; + + Hashset member_names; + for (auto* mem : str->members) { + member_names.Add(std::string(GetSymbolName(mem->name->symbol))); + } + size_t padding_idx = 0; + auto new_padding_name = [&] { + while (true) { + auto name = "padding_" + tint::ToString(padding_idx++); + if (member_names.Add(name)) { + return name; + } + } + }; + + auto add_padding = [&](uint32_t size) { + Line() << "@size(" << size << ")"; + + // Note: u32 is the smallest primitive we currently support. When WGSL + // supports smaller types, this will need to be updated. + Line() << new_padding_name() << " : u32,"; + }; + + IncrementIndent(); + uint32_t offset = 0; + for (auto* mem : str->members) { + // Emit comments to show non-default struct member offsets. + if (auto* mem_sem = program_.Sem().Get(mem)) { + offset = tint::RoundUp(mem_sem->Align(), offset); + if (mem_sem->Offset() != offset) { + Line() << "/* offset(" << mem_sem->Offset() << ") */"; + } + + if (uint32_t padding = mem_sem->Offset() - offset) { + add_padding(padding); + offset += padding; + } + + offset += mem_sem->Size(); + } + + if (!mem->attributes.IsEmpty()) { + EmitAttributes(Line(), mem->attributes); + } + + auto out = Line(); + out << GetSymbolName(mem->name->symbol) << " : "; + EmitExpression(out, mem->type); + out << ","; + } + DecrementIndent(); + + Line() << "}"; +} + +void ASTPrinter::EmitVariable(StringStream& out, const ast::Variable* v) { + if (!v->attributes.IsEmpty()) { + EmitAttributes(out, v->attributes); + out << " "; + } + + Switch( + v, // + [&](const ast::Var* var) { + out << "var"; + if (var->declared_address_space || var->declared_access) { + out << "<"; + TINT_DEFER(out << ">"); + EmitExpression(out, var->declared_address_space); + if (var->declared_access) { + out << ", "; + EmitExpression(out, var->declared_access); + } + } + }, + [&](const ast::Let*) { out << "let"; }, [&](const ast::Override*) { out << "override"; }, + [&](const ast::Const*) { out << "const"; }, // + TINT_ICE_ON_NO_MATCH); + + out << " " << GetSymbolName(v->name->symbol); + + if (auto ty = v->type) { + out << " : "; + EmitExpression(out, ty); + } + + if (v->initializer != nullptr) { + out << " = "; + EmitExpression(out, v->initializer); + } + out << ";"; +} + +void ASTPrinter::EmitAttributes(StringStream& out, VectorRef attrs) { + bool first = true; + for (auto* attr : attrs) { + if (!first) { + out << " "; + } + first = false; + out << "@"; + Switch( + attr, // + [&](const ast::WorkgroupAttribute* workgroup) { + auto values = workgroup->Values(); + out << "workgroup_size("; + for (size_t i = 0; i < 3; i++) { + if (values[i]) { + if (i > 0) { + out << ", "; + } + EmitExpression(out, values[i]); + } + } + out << ")"; + }, + [&](const ast::StageAttribute* stage) { out << stage->stage; }, + [&](const ast::BindingAttribute* binding) { + out << "binding("; + EmitExpression(out, binding->expr); + out << ")"; + }, + [&](const ast::GroupAttribute* group) { + out << "group("; + EmitExpression(out, group->expr); + out << ")"; + }, + [&](const ast::LocationAttribute* location) { + out << "location("; + EmitExpression(out, location->expr); + out << ")"; + }, + [&](const ast::ColorAttribute* color) { + out << "color("; + EmitExpression(out, color->expr); + out << ")"; + }, + [&](const ast::BlendSrcAttribute* blend_src) { + out << "blend_src("; + EmitExpression(out, blend_src->expr); + out << ")"; + }, + [&](const ast::BuiltinAttribute* builtin) { + out << "builtin("; + out << core::ToString(builtin->builtin); + out << ")"; + }, + [&](const ast::DiagnosticAttribute* diagnostic) { + EmitDiagnosticControl(out, diagnostic->control); + }, + [&](const ast::InterpolateAttribute* interpolate) { + out << "interpolate("; + out << core::ToString(interpolate->interpolation.type); + if (interpolate->interpolation.sampling != + core::InterpolationSampling::kUndefined) { + out << ", "; + out << core::ToString(interpolate->interpolation.sampling); + } + out << ")"; + }, + [&](const ast::InvariantAttribute*) { out << "invariant"; }, + [&](const ast::IdAttribute* override_deco) { + out << "id("; + EmitExpression(out, override_deco->expr); + out << ")"; + }, + [&](const ast::MustUseAttribute*) { out << "must_use"; }, + [&](const ast::StructMemberSizeAttribute* size) { + out << "size("; + EmitExpression(out, size->expr); + out << ")"; + }, + [&](const ast::StructMemberAlignAttribute* align) { + out << "align("; + EmitExpression(out, align->expr); + out << ")"; + }, + [&](const ast::InputAttachmentIndexAttribute* index) { + out << "input_attachment_index("; + EmitExpression(out, index->expr); + out << ")"; + }, + [&](const ast::SubgroupSizeAttribute* subgroup_size) { + out << "subgroup_size("; + EmitExpression(out, subgroup_size->subgroup_size); + out << ")"; + }, // + TINT_ICE_ON_NO_MATCH); + } +} + +void ASTPrinter::EmitBinary(StringStream& out, const ast::BinaryExpression* expr) { + out << "("; + + EmitExpression(out, expr->lhs); + out << " "; + EmitBinaryOp(out, expr->op); + out << " "; + + EmitExpression(out, expr->rhs); + out << ")"; +} + +void ASTPrinter::EmitBinaryOp(StringStream& out, const core::BinaryOp op) { + switch (op) { + case core::BinaryOp::kAnd: + out << "&"; + return; + case core::BinaryOp::kOr: + out << "|"; + return; + case core::BinaryOp::kXor: + out << "^"; + return; + case core::BinaryOp::kLogicalAnd: + out << "&&"; + return; + case core::BinaryOp::kLogicalOr: + out << "||"; + return; + case core::BinaryOp::kEqual: + out << "=="; + return; + case core::BinaryOp::kNotEqual: + out << "!="; + return; + case core::BinaryOp::kLessThan: + out << "<"; + return; + case core::BinaryOp::kGreaterThan: + out << ">"; + return; + case core::BinaryOp::kLessThanEqual: + out << "<="; + return; + case core::BinaryOp::kGreaterThanEqual: + out << ">="; + return; + case core::BinaryOp::kShiftLeft: + out << "<<"; + return; + case core::BinaryOp::kShiftRight: + out << ">>"; + return; + case core::BinaryOp::kAdd: + out << "+"; + return; + case core::BinaryOp::kSubtract: + out << "-"; + return; + case core::BinaryOp::kMultiply: + out << "*"; + return; + case core::BinaryOp::kDivide: + out << "/"; + return; + case core::BinaryOp::kModulo: + out << "%"; + return; + } + TINT_ICE() << "invalid binary op " << op; +} + +void ASTPrinter::EmitUnaryOp(StringStream& out, const ast::UnaryOpExpression* expr) { + switch (expr->op) { + case core::UnaryOp::kAddressOf: + out << "&"; + break; + case core::UnaryOp::kComplement: + out << "~"; + break; + case core::UnaryOp::kIndirection: + out << "*"; + break; + case core::UnaryOp::kNot: + out << "!"; + break; + case core::UnaryOp::kNegation: + out << "-"; + break; + } + out << "("; + EmitExpression(out, expr->expr); + out << ")"; +} + +void ASTPrinter::EmitBlock(const ast::BlockStatement* stmt) { + { + auto out = Line(); + EmitBlockHeader(out, stmt); + } + EmitStatementsWithIndent(stmt->statements); + Line() << "}"; +} + +void ASTPrinter::EmitBlockHeader(StringStream& out, const ast::BlockStatement* stmt) { + if (!stmt->attributes.IsEmpty()) { + EmitAttributes(out, stmt->attributes); + out << " "; + } + out << "{"; +} + +void ASTPrinter::EmitStatement(const ast::Statement* stmt) { + Switch( + stmt, // + [&](const ast::AssignmentStatement* a) { EmitAssign(a); }, + [&](const ast::BlockStatement* b) { EmitBlock(b); }, + [&](const ast::BreakStatement* b) { EmitBreak(b); }, + [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); }, + [&](const ast::CallStatement* c) { + auto out = Line(); + EmitCall(out, c->expr); + out << ";"; + }, + [&](const ast::CompoundAssignmentStatement* c) { EmitCompoundAssign(c); }, + [&](const ast::ContinueStatement* c) { EmitContinue(c); }, + [&](const ast::DiscardStatement* d) { EmitDiscard(d); }, + [&](const ast::IfStatement* i) { EmitIf(i); }, + [&](const ast::IncrementDecrementStatement* l) { EmitIncrementDecrement(l); }, + [&](const ast::LoopStatement* l) { EmitLoop(l); }, + [&](const ast::ForLoopStatement* l) { EmitForLoop(l); }, + [&](const ast::WhileStatement* l) { EmitWhile(l); }, + [&](const ast::ReturnStatement* r) { EmitReturn(r); }, + [&](const ast::ConstAssert* c) { EmitConstAssert(c); }, + [&](const ast::SwitchStatement* s) { EmitSwitch(s); }, + [&](const ast::VariableDeclStatement* v) { EmitVariable(Line(), v->variable); }, // + TINT_ICE_ON_NO_MATCH); +} + +void ASTPrinter::EmitStatements(VectorRef stmts) { + for (auto* s : stmts) { + EmitStatement(s); + } +} + +void ASTPrinter::EmitStatementsWithIndent(VectorRef stmts) { + ScopedIndent si(this); + EmitStatements(stmts); +} + +void ASTPrinter::EmitAssign(const ast::AssignmentStatement* stmt) { + auto out = Line(); + + EmitExpression(out, stmt->lhs); + out << " = "; + EmitExpression(out, stmt->rhs); + out << ";"; +} + +void ASTPrinter::EmitBreak(const ast::BreakStatement*) { + Line() << "break;"; +} + +void ASTPrinter::EmitBreakIf(const ast::BreakIfStatement* b) { + auto out = Line(); + + out << "break if "; + EmitExpression(out, b->condition); + out << ";"; +} + +void ASTPrinter::EmitCase(const ast::CaseStatement* stmt) { + if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) { + auto out = Line(); + out << "default: "; + EmitBlockHeader(out, stmt->body); + } else { + auto out = Line(); + out << "case "; + + bool first = true; + for (auto* sel : stmt->selectors) { + if (!first) { + out << ", "; + } + + first = false; + + if (sel->IsDefault()) { + out << "default"; + } else { + EmitExpression(out, sel->expr); + } + } + out << ": "; + EmitBlockHeader(out, stmt->body); + } + EmitStatementsWithIndent(stmt->body->statements); + Line() << "}"; +} + +void ASTPrinter::EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt) { + auto out = Line(); + + EmitExpression(out, stmt->lhs); + out << " "; + EmitBinaryOp(out, stmt->op); + out << "= "; + EmitExpression(out, stmt->rhs); + out << ";"; +} + +void ASTPrinter::EmitContinue(const ast::ContinueStatement*) { + Line() << "continue;"; +} + +void ASTPrinter::EmitIf(const ast::IfStatement* stmt) { + { + auto out = Line(); + + if (!stmt->attributes.IsEmpty()) { + EmitAttributes(out, stmt->attributes); + out << " "; + } + + out << "if ("; + EmitExpression(out, stmt->condition); + out << ") "; + EmitBlockHeader(out, stmt->body); + } + + EmitStatementsWithIndent(stmt->body->statements); + + const ast::Statement* e = stmt->else_statement; + while (e) { + if (auto* elseif = e->As()) { + { + auto out = Line(); + out << "} else if ("; + EmitExpression(out, elseif->condition); + out << ") "; + EmitBlockHeader(out, elseif->body); + } + EmitStatementsWithIndent(elseif->body->statements); + e = elseif->else_statement; + } else { + auto* body = e->As(); + { + auto out = Line(); + out << "} else "; + EmitBlockHeader(out, body); + } + EmitStatementsWithIndent(body->statements); + break; + } + } + + Line() << "}"; +} + +void ASTPrinter::EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) { + auto out = Line(); + EmitExpression(out, stmt->lhs); + out << (stmt->increment ? "++" : "--") << ";"; +} + +void ASTPrinter::EmitDiscard(const ast::DiscardStatement*) { + Line() << "discard;"; +} + +void ASTPrinter::EmitLoop(const ast::LoopStatement* stmt) { + { + auto out = Line(); + + if (!stmt->attributes.IsEmpty()) { + EmitAttributes(out, stmt->attributes); + out << " "; + } + + out << "loop "; + EmitBlockHeader(out, stmt->body); + } + IncrementIndent(); + + EmitStatements(stmt->body->statements); + + if (stmt->continuing && !stmt->continuing->Empty()) { + Line(); + { + auto out = Line(); + out << "continuing "; + if (!stmt->continuing->attributes.IsEmpty()) { + EmitAttributes(out, stmt->continuing->attributes); + out << " "; + } + out << "{"; + } + EmitStatementsWithIndent(stmt->continuing->statements); + Line() << "}"; + } + + DecrementIndent(); + Line() << "}"; +} + +void ASTPrinter::EmitForLoop(const ast::ForLoopStatement* stmt) { + TextBuffer init_buf; + if (auto* init = stmt->initializer) { + TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf); + EmitStatement(init); + } + + TextBuffer cont_buf; + if (auto* cont = stmt->continuing) { + TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf); + EmitStatement(cont); + } + + { + auto out = Line(); + + if (!stmt->attributes.IsEmpty()) { + EmitAttributes(out, stmt->attributes); + out << " "; + } + + out << "for"; + { + ScopedParen sp(out); + switch (init_buf.lines.size()) { + case 0: // No initializer + break; + case 1: // Single line initializer statement + out << tint::TrimSuffix(init_buf.lines[0].content, ";"); + break; + default: // Block initializer statement + for (size_t i = 1; i < init_buf.lines.size(); i++) { + // Indent all by the first line + init_buf.lines[i].indent += current_buffer_->current_indent; + } + out << tint::TrimSuffix(init_buf.String(), "\n"); + break; + } + + out << "; "; + + if (auto* cond = stmt->condition) { + EmitExpression(out, cond); + } + + out << "; "; + + switch (cont_buf.lines.size()) { + case 0: // No continuing + break; + case 1: // Single line continuing statement + out << tint::TrimSuffix(cont_buf.lines[0].content, ";"); + break; + default: // Block continuing statement + for (size_t i = 1; i < cont_buf.lines.size(); i++) { + // Indent all by the first line + cont_buf.lines[i].indent += current_buffer_->current_indent; + } + out << tint::TrimSuffix(cont_buf.String(), "\n"); + break; + } + } + out << " "; + EmitBlockHeader(out, stmt->body); + } + + EmitStatementsWithIndent(stmt->body->statements); + + Line() << "}"; +} + +void ASTPrinter::EmitWhile(const ast::WhileStatement* stmt) { + { + auto out = Line(); + + if (!stmt->attributes.IsEmpty()) { + EmitAttributes(out, stmt->attributes); + out << " "; + } + + out << "while"; + { + ScopedParen sp(out); + + auto* cond = stmt->condition; + EmitExpression(out, cond); + } + out << " "; + EmitBlockHeader(out, stmt->body); + } + + EmitStatementsWithIndent(stmt->body->statements); + + Line() << "}"; +} + +void ASTPrinter::EmitReturn(const ast::ReturnStatement* stmt) { + auto out = Line(); + + out << "return"; + if (stmt->value) { + out << " "; + EmitExpression(out, stmt->value); + } + out << ";"; +} + +void ASTPrinter::EmitConstAssert(const ast::ConstAssert* stmt) { + auto out = Line(); + out << "const_assert "; + EmitExpression(out, stmt->condition); + out << ";"; +} + +void ASTPrinter::EmitSwitch(const ast::SwitchStatement* stmt) { + { + auto out = Line(); + + if (!stmt->attributes.IsEmpty()) { + EmitAttributes(out, stmt->attributes); + out << " "; + } + + out << "switch("; + EmitExpression(out, stmt->condition); + out << ") "; + + if (!stmt->body_attributes.IsEmpty()) { + EmitAttributes(out, stmt->body_attributes); + out << " "; + } + + out << "{"; + } + + { + ScopedIndent si(this); + for (auto* s : stmt->body) { + EmitCase(s); + } + } + + Line() << "}"; +} + +void ASTPrinter::BuildUnrenameableNames() { + // Find all the entry points and overrides and mark their names as unrenameable. + for (auto* func : program_.AST().Functions()) { + if (func->IsEntryPoint()) { + unrenameable_.Add(func->name->symbol.NameView()); + } + } + for (auto* var : program_.AST().GlobalVariables()) { + if (var->Is()) { + unrenameable_.Add(var->name->symbol.NameView()); + } + } +} + +std::string ASTPrinter::NextMinifiedName() { + constexpr std::string_view kMinifiedIdentifierChars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + constexpr auto kNumMinifiedIdentifierChars = kMinifiedIdentifierChars.length(); + + // Three characters is 140K names. + std::string name; + name.reserve(3); + + auto idx = next_minified_name_idx_++; + while (true) { + // Add the next character based on the modulo of the index. + name += kMinifiedIdentifierChars[idx % kNumMinifiedIdentifierChars]; + + // Reduce the index by a factor of `kNumMinifiedIdentifierChars`. + idx /= kNumMinifiedIdentifierChars; + if (idx == 0) { + break; + } + idx--; + } + return name; +} + +std::string_view ASTPrinter::GetSymbolName(tint::Symbol sym) { + if (!options_.minify) { + return sym.NameView(); + } + + // Returns `true` if `name` can be renamed, or can be used as a minified identifier. + auto can_rename_to_or_from = [&](std::string_view name) { + if (unrenameable_.Contains(name)) { + return false; + } + if (IsReserved(name) || IsKeyword(name) || IsEnumName(name) || IsTypeName(name) || + wgsl::ParseBuiltinFn(name) != wgsl::BuiltinFn::kNone) { + return false; + } + return true; + }; + + return symbol_to_name_.GetOrAdd(sym, [&] { + if (!can_rename_to_or_from(sym.NameView())) { + return sym.Name(); + } + + // Generate minified names until we find one that we can use. + while (true) { + auto name = NextMinifiedName(); + if (can_rename_to_or_from(name)) { + return name; + } + } + }); +} + +} // namespace tint::wgsl::writer diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.h new file mode 100644 index 000000000..0be81ebae --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/ast_printer/ast_printer.h @@ -0,0 +1,263 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_AST_PRINTER_AST_PRINTER_H_ +#define SRC_TINT_LANG_WGSL_WRITER_AST_PRINTER_AST_PRINTER_H_ + +#include +#include + +#include "src/tint/lang/core/binary_op.h" +#include "src/tint/lang/wgsl/writer/common/options.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/symbol/symbol.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text_generator/text_generator.h" + +// Forward declarations +namespace tint { +class Program; +} // namespace tint +namespace tint::ast { +class AssignmentStatement; +class Attribute; +class BinaryExpression; +class BitcastExpression; +class BlockStatement; +class BlockStatement; +class BreakIfStatement; +class BreakStatement; +class CallExpression; +class CaseStatement; +class CompoundAssignmentStatement; +class ConstAssert; +class ContinueStatement; +struct DiagnosticControl; +class DiscardStatement; +class Enable; +class Expression; +class ForLoopStatement; +class Function; +class Identifier; +class IdentifierExpression; +class IfStatement; +class IncrementDecrementStatement; +class IndexAccessorExpression; +class LiteralExpression; +class LoopStatement; +class MemberAccessorExpression; +class Requires; +class ReturnStatement; +class Statement; +class Statement; +class Statement; +class Struct; +class SwitchStatement; +class TypeDecl; +class UnaryOpExpression; +class Variable; +class WhileStatement; +} // namespace tint::ast + +namespace tint::core { +enum class TexelFormat : uint8_t; +} // namespace tint::core + +namespace tint::wgsl::writer { + +/// Implementation class for WGSL generator +class ASTPrinter : public tint::TextGenerator { + public: + /// Constructor + /// @param program the program + /// @param options the writer options + explicit ASTPrinter(const Program& program, const Options& options = {}); + ~ASTPrinter() override; + + /// Generates the result data + /// @returns true on successful generation, false otherwise + bool Generate(); + + /// @returns the result data + std::string Result() const override; + + /// Handles generating a diagnostic control + /// @param out the output stream + /// @param diagnostic the diagnostic control node + void EmitDiagnosticControl(StringStream& out, const ast::DiagnosticControl& diagnostic); + /// Handles generating an enable directive + /// @param enable the enable node + void EmitEnable(const ast::Enable* enable); + /// Handles generating a requires directive + /// @param req the requires node + void EmitRequires(const ast::Requires* req); + /// Handles generating a declared type + /// @param ty the declared type to generate + void EmitTypeDecl(const ast::TypeDecl* ty); + /// Handles an index accessor expression + /// @param out the output stream + /// @param expr the expression to emit + void EmitIndexAccessor(StringStream& out, const ast::IndexAccessorExpression* expr); + /// Handles an assignment statement + /// @param stmt the statement to emit + void EmitAssign(const ast::AssignmentStatement* stmt); + /// Handles generating a binary expression + /// @param out the output stream + /// @param expr the binary expression + void EmitBinary(StringStream& out, const ast::BinaryExpression* expr); + /// Handles generating a binary operator + /// @param out the output stream + /// @param op the binary operator + void EmitBinaryOp(StringStream& out, const core::BinaryOp op); + /// Handles a block statement + /// @param stmt the statement to emit + void EmitBlock(const ast::BlockStatement* stmt); + /// Handles emitting the start of a block statement (including attributes) + /// @param out the output stream to write the header to + /// @param stmt the block statement to emit the header for + void EmitBlockHeader(StringStream& out, const ast::BlockStatement* stmt); + /// Handles a break statement + /// @param stmt the statement to emit + void EmitBreak(const ast::BreakStatement* stmt); + /// Handles a break-if statement + /// @param stmt the statement to emit + void EmitBreakIf(const ast::BreakIfStatement* stmt); + /// Handles generating a call expression + /// @param out the output stream + /// @param expr the call expression + void EmitCall(StringStream& out, const ast::CallExpression* expr); + /// Handles a case statement + /// @param stmt the statement + void EmitCase(const ast::CaseStatement* stmt); + /// Handles a compound assignment statement + /// @param stmt the statement to emit + void EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt); + /// Handles generating a literal expression + /// @param out the output stream + /// @param expr the literal expression expression + void EmitLiteral(StringStream& out, const ast::LiteralExpression* expr); + /// Handles a continue statement + /// @param stmt the statement to emit + void EmitContinue(const ast::ContinueStatement* stmt); + /// Handles generate an Expression + /// @param out the output stream + /// @param expr the expression + void EmitExpression(StringStream& out, const ast::Expression* expr); + /// Handles generating a function + /// @param func the function to generate + void EmitFunction(const ast::Function* func); + /// Handles generating an identifier expression + /// @param out the output stream + /// @param expr the identifier expression + void EmitIdentifier(StringStream& out, const ast::IdentifierExpression* expr); + /// Handles generating an identifier + /// @param out the output of the expression stream + /// @param ident the identifier + void EmitIdentifier(StringStream& out, const ast::Identifier* ident); + /// Handles an if statement + /// @param stmt the statement to emit + void EmitIf(const ast::IfStatement* stmt); + /// Handles an increment/decrement statement + /// @param stmt the statement to emit + void EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt); + /// Handles generating a discard statement + /// @param stmt the discard statement + void EmitDiscard(const ast::DiscardStatement* stmt); + /// Handles a loop statement + /// @param stmt the statement to emit + void EmitLoop(const ast::LoopStatement* stmt); + /// Handles a for-loop statement + /// @param stmt the statement to emit + void EmitForLoop(const ast::ForLoopStatement* stmt); + /// Handles a while statement + /// @param stmt the statement to emit + void EmitWhile(const ast::WhileStatement* stmt); + /// Handles a member accessor expression + /// @param out the output stream + /// @param expr the member accessor expression + void EmitMemberAccessor(StringStream& out, const ast::MemberAccessorExpression* expr); + /// Handles return statements + /// @param stmt the statement to emit + void EmitReturn(const ast::ReturnStatement* stmt); + /// Handles const assertion statements + /// @param stmt the statement to emit + void EmitConstAssert(const ast::ConstAssert* stmt); + /// Handles statement + /// @param stmt the statement to emit + void EmitStatement(const ast::Statement* stmt); + /// Handles a statement list + /// @param stmts the statements to emit + void EmitStatements(VectorRef stmts); + /// Handles a statement list with an increased indentation + /// @param stmts the statements to emit + void EmitStatementsWithIndent(VectorRef stmts); + /// Handles generating a switch statement + /// @param stmt the statement to emit + void EmitSwitch(const ast::SwitchStatement* stmt); + /// Handles generating a struct declaration + /// @param str the struct + void EmitStructType(const ast::Struct* str); + /// Handles emitting an image format + /// @param out the output stream + /// @param fmt the format to generate + void EmitImageFormat(StringStream& out, const core::TexelFormat fmt); + /// Handles a unary op expression + /// @param out the output stream + /// @param expr the expression to emit + void EmitUnaryOp(StringStream& out, const ast::UnaryOpExpression* expr); + /// Handles generating a variable + /// @param out the output stream + /// @param var the variable to generate + void EmitVariable(StringStream& out, const ast::Variable* var); + /// Handles generating a attribute list + /// @param out the output stream + /// @param attrs the attribute list + void EmitAttributes(StringStream& out, VectorRef attrs); + + private: + /// Traverses the AST to build the set of names that cannot be changed. + void BuildUnrenameableNames(); + + /// @returns the next minified name. + std::string NextMinifiedName(); + + /// Get the generated name for a symbol, minifying it if required. + /// @param sym the symbol to get the name for. + /// @return the name for the symbol. + std::string_view GetSymbolName(tint::Symbol sym); + + const Program& program_; + const Options options_; + Hashset unrenameable_; + Hashmap symbol_to_name_; + uint64_t next_minified_name_idx_ = 0; +}; + +} // namespace tint::wgsl::writer + +#endif // SRC_TINT_LANG_WGSL_WRITER_AST_PRINTER_AST_PRINTER_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/common/common.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/common/common.cc new file mode 100644 index 000000000..162c3314b --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/common/common.cc @@ -0,0 +1,33 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +// A placeholder symbol used to emit a symbol for this lib target. +int tint_lang_wgsl_writer_common_symbol = 1; diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/common/options.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/common/options.h new file mode 100644 index 000000000..997adac47 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/common/options.h @@ -0,0 +1,58 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_COMMON_OPTIONS_H_ +#define SRC_TINT_LANG_WGSL_WRITER_COMMON_OPTIONS_H_ + +#include "src/tint/lang/wgsl/allowed_features.h" +#include "src/tint/utils/reflection.h" + +namespace tint::wgsl::writer { + +/// Configuration options used for producing a WGSL program from an IR module. +struct Options { + /// Set to `true` to allow calls to derivative builtins in non-uniform control flow. + bool allow_non_uniform_derivatives = false; + /// Set to `true` to insert a directive to disable uniformity checks for subgroup builtins. + bool allow_non_uniform_subgroup_operations = false; + /// The extensions and language features that are allowed to be used in the generated WGSL. + wgsl::AllowedFeatures allowed_features = {}; + + /// Set to `true` to minify the output WGSL. + bool minify = false; + + /// Reflect the fields of this class so that it can be used by tint::ForeachField(). + TINT_REFLECT(Options, + allow_non_uniform_derivatives, + allow_non_uniform_subgroup_operations, + allowed_features, + minify); +}; + +} // namespace tint::wgsl::writer + +#endif // SRC_TINT_LANG_WGSL_WRITER_COMMON_OPTIONS_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc new file mode 100644 index 000000000..d5b453903 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc @@ -0,0 +1,1428 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h" + +#include +#include +#include +#include + +#include "src/tint/lang/core/constant/splat.h" +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/fluent_types.h" +#include "src/tint/lang/core/ir/access.h" +#include "src/tint/lang/core/ir/binary.h" +#include "src/tint/lang/core/ir/bitcast.h" +#include "src/tint/lang/core/ir/block.h" +#include "src/tint/lang/core/ir/break_if.h" +#include "src/tint/lang/core/ir/call.h" +#include "src/tint/lang/core/ir/constant.h" +#include "src/tint/lang/core/ir/construct.h" +#include "src/tint/lang/core/ir/continue.h" +#include "src/tint/lang/core/ir/convert.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/discard.h" +#include "src/tint/lang/core/ir/exit_if.h" +#include "src/tint/lang/core/ir/exit_loop.h" +#include "src/tint/lang/core/ir/exit_switch.h" +#include "src/tint/lang/core/ir/if.h" +#include "src/tint/lang/core/ir/instruction.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/load_vector_element.h" +#include "src/tint/lang/core/ir/loop.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/multi_in_block.h" +#include "src/tint/lang/core/ir/next_iteration.h" +#include "src/tint/lang/core/ir/override.h" +#include "src/tint/lang/core/ir/phony.h" +#include "src/tint/lang/core/ir/return.h" +#include "src/tint/lang/core/ir/store.h" +#include "src/tint/lang/core/ir/store_vector_element.h" +#include "src/tint/lang/core/ir/switch.h" +#include "src/tint/lang/core/ir/swizzle.h" +#include "src/tint/lang/core/ir/unary.h" +#include "src/tint/lang/core/ir/unreachable.h" +#include "src/tint/lang/core/ir/user_call.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/atomic.h" +#include "src/tint/lang/core/type/binding_array.h" +#include "src/tint/lang/core/type/depth_multisampled_texture.h" +#include "src/tint/lang/core/type/depth_texture.h" +#include "src/tint/lang/core/type/input_attachment.h" +#include "src/tint/lang/core/type/multisampled_texture.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/core/type/sampler.h" +#include "src/tint/lang/core/type/storage_texture.h" +#include "src/tint/lang/core/type/texture.h" +#include "src/tint/lang/core/type/type.h" +#include "src/tint/lang/wgsl/ast/type.h" +#include "src/tint/lang/wgsl/ir/builtin_call.h" +#include "src/tint/lang/wgsl/ir/unary.h" +#include "src/tint/lang/wgsl/program/program_builder.h" +#include "src/tint/lang/wgsl/reserved_words.h" +#include "src/tint/lang/wgsl/resolver/resolve.h" +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/predicates.h" +#include "src/tint/utils/containers/reverse.h" +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/macros/scoped_assignment.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/rtti/switch.h" + +using namespace tint::core::fluent_types; // NOLINT + +namespace tint::wgsl::writer { +namespace { + +class State { + public: + explicit State(const core::ir::Module& m) : mod(m) {} + + Program Run(const Options& options) { + core::ir::Capabilities caps{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPhonyInstructions, + core::ir::Capability::kAllowRefTypes, + }; + if (auto res = core::ir::ValidateAndDumpIfNeeded(mod, "wgsl.to_program", caps); + res != Success) { + // IR module failed validation. + b.Diagnostics().AddError(Source{}) << res.Failure(); + return Program{resolver::Resolve(b)}; + } + + // Clone all symbols before we start. + // This ensures that we preserve the names of named values and prevents unnamed values + // receiving names that would conflict with named values that are emitted later than them. + mod.symbols.Foreach([&](Symbol s) { // + b.Symbols().New(s.Name()); + }); + + RootBlock(mod.root_block); + + // TODO(crbug.com/tint/1902): Emit user-declared types + for (auto& fn : mod.functions) { + Fn(fn); + } + + if (options.allow_non_uniform_derivatives) { + // Suppress errors regarding non-uniform derivative operations if requested, by adding a + // diagnostic directive to the module. + b.DiagnosticDirective(wgsl::DiagnosticSeverity::kOff, "derivative_uniformity"); + } + if (options.allow_non_uniform_subgroup_operations) { + // Suppress errors regarding non-uniform subgroups operations if requested, by adding a + // diagnostic directive to the module. + b.DiagnosticDirective(wgsl::DiagnosticSeverity::kOff, "subgroup_uniformity"); + } + + return Program{resolver::Resolve(b, options.allowed_features)}; + } + + private: + /// The source IR module + const core::ir::Module& mod; + + /// The target ProgramBuilder + ProgramBuilder b; + + /// The structure for a reusable value + struct ValueBinding { + Symbol name{}; + const core::ir::Value* ir_expr = nullptr; + const ast::Expression* ast_expr = nullptr; + }; + + /// IR values to their representation + Hashmap bindings_; + + /// Names for values + Hashmap names_; + + /// 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; + + using StatementList = + Vector; + StatementList* statements_ = nullptr; + + /// The current switch case block + const core::ir::Block* current_switch_case_ = nullptr; + + /// Set of enable directives emitted. + Hashset enables_; + + /// Map of struct to output program name. + Hashmap structs_; + + /// Map of struct members to their sanitized names. + Hashmap member_names_; + + /// The current function being emitted. + const core::ir::Function* current_function_ = nullptr; + + void RootBlock(const core::ir::Block* root) { + for (auto* inst : *root) { + tint::Switch( + inst, // + [&](const core::ir::Var* var) { Var(var); }, // + [&](const core::ir::Override* override_) { Override(override_); }, // + [&](const core::ir::Binary* binary) { Binary(binary); }, // + [&](const core::ir::Unary* unary) { Unary(unary); }, // + [&](const core::ir::Bitcast* c) { + auto ty = Type(c->Result()->Type()); + Bind(c->Result(), b.Bitcast(ty, Expr(c->Args()[0]))); + }, + TINT_ICE_ON_NO_MATCH); + } + } + const ast::Function* Fn(const core::ir::Function* fn) { + TINT_SCOPED_ASSIGNMENT(nesting_depth_, nesting_depth_ + 1); + TINT_SCOPED_ASSIGNMENT(current_function_, fn); + + // Emit parameters. + static constexpr size_t N = decltype(ast::Function::params)::static_length; + auto params = tint::Transform(fn->Params(), [&](const core::ir::FunctionParam* param) { + auto ty = Type(param->Type()); + auto name = NameFor(param); + Vector attrs{}; + Bind(param, name); + + // Emit parameter attributes. + if (auto builtin = param->Builtin()) { + switch (builtin.value()) { + case core::BuiltinValue::kVertexIndex: + attrs.Push(b.Builtin(core::BuiltinValue::kVertexIndex)); + break; + case core::BuiltinValue::kInstanceIndex: + attrs.Push(b.Builtin(core::BuiltinValue::kInstanceIndex)); + break; + case core::BuiltinValue::kPosition: + attrs.Push(b.Builtin(core::BuiltinValue::kPosition)); + break; + case core::BuiltinValue::kFrontFacing: + attrs.Push(b.Builtin(core::BuiltinValue::kFrontFacing)); + break; + case core::BuiltinValue::kLocalInvocationId: + attrs.Push(b.Builtin(core::BuiltinValue::kLocalInvocationId)); + break; + case core::BuiltinValue::kLocalInvocationIndex: + attrs.Push(b.Builtin(core::BuiltinValue::kLocalInvocationIndex)); + break; + case core::BuiltinValue::kGlobalInvocationId: + attrs.Push(b.Builtin(core::BuiltinValue::kGlobalInvocationId)); + break; + case core::BuiltinValue::kWorkgroupId: + attrs.Push(b.Builtin(core::BuiltinValue::kWorkgroupId)); + break; + case core::BuiltinValue::kNumWorkgroups: + attrs.Push(b.Builtin(core::BuiltinValue::kNumWorkgroups)); + break; + case core::BuiltinValue::kSampleIndex: + attrs.Push(b.Builtin(core::BuiltinValue::kSampleIndex)); + break; + case core::BuiltinValue::kSampleMask: + attrs.Push(b.Builtin(core::BuiltinValue::kSampleMask)); + break; + case core::BuiltinValue::kSubgroupInvocationId: + Enable(wgsl::Extension::kSubgroups); + attrs.Push(b.Builtin(core::BuiltinValue::kSubgroupInvocationId)); + break; + case core::BuiltinValue::kSubgroupSize: + Enable(wgsl::Extension::kSubgroups); + attrs.Push(b.Builtin(core::BuiltinValue::kSubgroupSize)); + break; + case core::BuiltinValue::kClipDistances: + Enable(wgsl::Extension::kClipDistances); + attrs.Push(b.Builtin(core::BuiltinValue::kClipDistances)); + break; + case core::BuiltinValue::kPrimitiveIndex: + Enable(wgsl::Extension::kPrimitiveIndex); + attrs.Push(b.Builtin(core::BuiltinValue::kPrimitiveIndex)); + break; + default: + TINT_IR_UNIMPLEMENTED(mod) << builtin.value(); + } + } + if (auto loc = param->Location()) { + attrs.Push(b.Location(u32(loc.value()))); + } + if (auto color = param->Color()) { + Enable(wgsl::Extension::kChromiumExperimentalFramebufferFetch); + attrs.Push(b.Color(u32(color.value()))); + } + if (auto interp = param->Interpolation()) { + attrs.Push(b.Interpolate(interp->type, interp->sampling)); + } + if (param->Invariant()) { + attrs.Push(b.Invariant()); + } + + return b.Param(name, ty, std::move(attrs)); + }); + + auto name = NameFor(fn); + auto ret_ty = Type(fn->ReturnType()); + auto* body = Block(fn->Block()); + Vector attrs{}; + Vector ret_attrs{}; + + // Emit entry point attributes. + switch (fn->Stage()) { + case core::ir::Function::PipelineStage::kUndefined: + break; + case core::ir::Function::PipelineStage::kCompute: { + auto wgsize = fn->WorkgroupSize().value(); + attrs.Push(b.Stage(ast::PipelineStage::kCompute)); + attrs.Push(b.WorkgroupSize(Expr(wgsize[0]), Expr(wgsize[1]), Expr(wgsize[2]))); + if (fn->SubgroupSize().has_value()) { + auto sgsize = fn->SubgroupSize().value(); + attrs.Push(b.SubgroupSize(Expr(sgsize))); + } + break; + } + case core::ir::Function::PipelineStage::kFragment: + attrs.Push(b.Stage(ast::PipelineStage::kFragment)); + break; + case core::ir::Function::PipelineStage::kVertex: + attrs.Push(b.Stage(ast::PipelineStage::kVertex)); + break; + } + + // Emit return type attributes. + if (auto builtin = fn->ReturnBuiltin()) { + switch (builtin.value()) { + case core::BuiltinValue::kPosition: + ret_attrs.Push(b.Builtin(core::BuiltinValue::kPosition)); + break; + case core::BuiltinValue::kFragDepth: + ret_attrs.Push(b.Builtin(core::BuiltinValue::kFragDepth)); + break; + case core::BuiltinValue::kSampleMask: + ret_attrs.Push(b.Builtin(core::BuiltinValue::kSampleMask)); + break; + default: + TINT_IR_UNIMPLEMENTED(mod) << builtin.value(); + } + } + if (auto loc = fn->ReturnLocation()) { + ret_attrs.Push(b.Location(u32(loc.value()))); + } + if (auto interp = fn->ReturnInterpolation()) { + ret_attrs.Push(b.Interpolate(interp->type, interp->sampling)); + } + if (fn->ReturnInvariant()) { + ret_attrs.Push(b.Invariant()); + } + + return b.Func(name, std::move(params), ret_ty, body, std::move(attrs), + std::move(ret_attrs)); + } + + const ast::BlockStatement* Block(const core::ir::Block* block) { + // TODO(crbug.com/tint/1902): Handle block arguments. + return b.Block(Statements(block)); + } + + StatementList Statements(const core::ir::Block* block) { + StatementList stmts; + if (block) { + TINT_SCOPED_ASSIGNMENT(statements_, &stmts); + for (auto* inst : *block) { + Instruction(inst); + } + } + return stmts; + } + + void Append(const ast::Statement* inst) { statements_->Push(inst); } + + void Instruction(const core::ir::Instruction* inst) { + tint::Switch( + inst, // + [&](const core::ir::Access* i) { Access(i); }, // + [&](const core::ir::Binary* i) { Binary(i); }, // + [&](const core::ir::BreakIf* i) { BreakIf(i); }, // + [&](const core::ir::Call* i) { Call(i); }, // + [&](const core::ir::Continue* c) { EmitContinue(c); }, // + [&](const core::ir::ExitIf*) {}, // + [&](const core::ir::ExitLoop* i) { ExitLoop(i); }, // + [&](const core::ir::ExitSwitch* i) { ExitSwitch(i); }, // + [&](const core::ir::If* i) { If(i); }, // + [&](const core::ir::Let* i) { Let(i); }, // + [&](const core::ir::Load* l) { Load(l); }, // + [&](const core::ir::LoadVectorElement* i) { LoadVectorElement(i); }, // + [&](const core::ir::Loop* l) { Loop(l); }, // + [&](const core::ir::NextIteration*) {}, // + [&](const core::ir::Phony* i) { Phony(i); }, // + [&](const core::ir::Return* i) { Return(i); }, // + [&](const core::ir::Store* i) { Store(i); }, // + [&](const core::ir::StoreVectorElement* i) { StoreVectorElement(i); }, // + [&](const core::ir::Switch* i) { Switch(i); }, // + [&](const core::ir::Swizzle* i) { Swizzle(i); }, // + [&](const core::ir::Unary* i) { Unary(i); }, // + [&](const core::ir::Unreachable* u) { Unreachable(u); }, // + [&](const core::ir::Var* i) { Var(i); }, // + TINT_ICE_ON_NO_MATCH); + } + + // In the case of an `unreachable` as the last statement in a non-void function, swap it to a + // `return` of the zero value for the return type. This is to satisfy the requirement for WGSL + // to always end in a `return` but `unreachable` really only meaning undefined behaviour if you + // get here. + void Unreachable(const core::ir::Unreachable* u) { + if (current_function_->ReturnType()->Is()) { + return; + } + if (u != current_function_->Block()->Terminator()) { + return; + } + + Append(b.Return(b.Call(Type(current_function_->ReturnType())))); + } + + void If(const core::ir::If* if_) { + TINT_SCOPED_ASSIGNMENT(nesting_depth_, nesting_depth_ + 1); + + auto true_stmts = Statements(if_->True()); + auto false_stmts = Statements(if_->False()); + if (AsShortCircuit(if_, true_stmts, false_stmts)) { + return; + } + + auto* cond = Expr(if_->Condition()); + auto* true_block = b.Block(std::move(true_stmts)); + + switch (false_stmts.Length()) { + case 0: + Append(b.If(cond, true_block)); + return; + case 1: + if (auto* else_if = false_stmts.Front()->As()) { + Append(b.If(cond, true_block, b.Else(else_if))); + return; + } + break; + } + + auto* false_block = b.Block(std::move(false_stmts)); + Append(b.If(cond, true_block, b.Else(false_block))); + } + + void Loop(const core::ir::Loop* l) { + TINT_SCOPED_ASSIGNMENT(nesting_depth_, nesting_depth_ + 1); + + // Build all the initializer statements + auto init_stmts = Statements(l->Initializer()); + + // If there's a single initializer statement and meets the WGSL 'for_init' pattern, then + // this can be used as the initializer for a for-loop. + // @see https://www.w3.org/TR/WGSL/#syntax-for_init + auto* init = (init_stmts.Length() == 1) && + init_stmts.Front() + ->IsAnyOf() + ? init_stmts.Front() + : nullptr; + + // Build the loop body statements. If the loop body starts with a if with the following + // pattern, then treat it as the loop condition: + // if cond { + // block { exit_if } + // block { exit_loop } + // } + const ast::Expression* cond = nullptr; + StatementList body_stmts; + { + TINT_SCOPED_ASSIGNMENT(statements_, &body_stmts); + for (auto* inst : *l->Body()) { + if (body_stmts.IsEmpty() && !cond) { + if (auto* if_ = inst->As()) { + if (if_->Results().IsEmpty() && // + if_->True()->Length() == 1 && // + if_->False()->Length() == 1 && // + tint::Is(if_->True()->Front()) && // + tint::Is(if_->False()->Front())) { + // Matched the loop condition. + cond = Expr(if_->Condition()); + continue; // Don't emit this as an instruction in the body. + } + } + } + + // Process the loop body instruction. Append to 'body_stmts' + Instruction(inst); + } + } + + // Build any continuing statements + auto cont_stmts = Statements(l->Continuing()); + // If there's a single continuing statement and meets the WGSL 'for_update' pattern then + // this can be used as the continuing for a for-loop. + // @see https://www.w3.org/TR/WGSL/#syntax-for_update + auto* cont = + (cont_stmts.Length() == 1) && + cont_stmts.Front() + ->IsAnyOf() + ? cont_stmts.Front() + : nullptr; + + // Depending on 'init', 'cond' and 'cont', build a 'for', 'while' or 'loop' + const ast::Statement* loop = nullptr; + bool non_trivial_continuing = !cont && !cont_stmts.IsEmpty(); + if (non_trivial_continuing || !cond) { + // Build a loop + if (cond) { + body_stmts.Insert(0, b.If(b.Not(cond), b.Block(b.Break()))); + } + auto* body = b.Block(std::move(body_stmts)); + loop = cont_stmts.IsEmpty() ? b.Loop(body) // + : b.Loop(body, b.Block(std::move(cont_stmts))); + if (!init_stmts.IsEmpty()) { + init_stmts.Push(loop); + loop = b.Block(std::move(init_stmts)); + } + } else if (init || cont) { + // Build a for-loop + auto* body = b.Block(std::move(body_stmts)); + loop = b.For(init, cond, cont, body); + if (!init && !init_stmts.IsEmpty()) { + init_stmts.Push(loop); + loop = b.Block(std::move(init_stmts)); + } + } else { + // Build a while-loop + auto* body = b.Block(std::move(body_stmts)); + loop = b.While(cond, body); + if (!init_stmts.IsEmpty()) { + init_stmts.Push(loop); + loop = b.Block(std::move(init_stmts)); + } + } + statements_->Push(loop); + } + + void Switch(const core::ir::Switch* s) { + TINT_SCOPED_ASSIGNMENT(nesting_depth_, nesting_depth_ + 1); + + auto* cond = Expr(s->Condition()); + + auto cases = tint::Transform<4>( + s->Cases(), // + [&](const core::ir::Switch::Case& c) -> const tint::ast::CaseStatement* { + TINT_SCOPED_ASSIGNMENT(nesting_depth_, nesting_depth_ + 1); + + const ast::BlockStatement* body = nullptr; + { + TINT_SCOPED_ASSIGNMENT(current_switch_case_, c.block); + body = Block(c.block); + } + + auto selectors = tint::Transform(c.selectors, // + [&](const core::ir::Switch::CaseSelector& cs) { + return cs.IsDefault() + ? b.DefaultCaseSelector() + : b.CaseSelector(Expr(cs.val)); + }); + return b.Case(std::move(selectors), body); + }); + + Append(b.Switch(cond, std::move(cases))); + } + + void ExitSwitch(const core::ir::ExitSwitch* e) { + if (current_switch_case_ && current_switch_case_->Terminator() == e) { + return; // No need to emit + } + Append(b.Break()); + } + + void EmitContinue(const core::ir::Continue* c) { + auto* loop = c->Loop(); + // No need to emit the continue as the last statement in loop as it's implicit + if (loop->Body()->Terminator() == c) { + return; + } + Append(b.Continue()); + } + + void ExitLoop(const core::ir::ExitLoop*) { Append(b.Break()); } + + void BreakIf(const core::ir::BreakIf* i) { Append(b.BreakIf(Expr(i->Condition()))); } + + void Return(const core::ir::Return* ret) { + if (ret->Args().IsEmpty()) { + // Return has no arguments. + // If this block is nested withing some control flow, then we must + // emit a 'return' statement, otherwise we've just naturally reached + // the end of the function where the 'return' is redundant. + if (nesting_depth_ > 1) { + Append(b.Return()); + } + return; + } + + // Return has arguments - this is the return value. + if (ret->Args().Length() != 1) { + TINT_IR_ICE(mod) << "expected 1 value for return, got " << ret->Args().Length(); + } + + Append(b.Return(Expr(ret->Args().Front()))); + } + + void Var(const core::ir::Var* var) { + auto* val = var->Result(); + auto* ref = As(val->Type()); + TINT_IR_ASSERT(mod, ref /* converted by PtrToRef */); + auto ty = Type(ref->StoreType()); + Symbol name = NameFor(var->Result()); + Bind(var->Result(), name); + + Vector attrs; + if (auto bp = var->BindingPoint()) { + attrs.Push(b.Group(u32(bp->group))); + attrs.Push(b.Binding(u32(bp->binding))); + } + + if (auto ii = var->InputAttachmentIndex()) { + attrs.Push(b.InputAttachmentIndex(u32(ii.value()))); + } + + const ast::Expression* init = nullptr; + if (var->Initializer()) { + init = Expr(var->Initializer()); + } + switch (ref->AddressSpace()) { + case core::AddressSpace::kFunction: + Append(b.Decl(b.Var(name, ty, init, std::move(attrs)))); + return; + case core::AddressSpace::kStorage: + b.GlobalVar(name, ty, init, ref->Access(), ref->AddressSpace(), std::move(attrs)); + return; + case core::AddressSpace::kHandle: + b.GlobalVar(name, ty, init, std::move(attrs)); + return; + case core::AddressSpace::kPixelLocal: + Enable(wgsl::Extension::kChromiumExperimentalPixelLocal); + b.GlobalVar(name, ty, init, ref->AddressSpace(), std::move(attrs)); + return; + case core::AddressSpace::kImmediate: + b.GlobalVar(name, ty, init, ref->AddressSpace(), std::move(attrs)); + return; + default: + b.GlobalVar(name, ty, init, ref->AddressSpace(), std::move(attrs)); + return; + } + } + + void Override(const core::ir::Override* override_) { + auto* val = override_->Result(); + Symbol name = NameFor(override_->Result()); + Bind(override_->Result(), name); + + Vector attrs; + if (override_->OverrideId().has_value()) { + attrs.Push(b.Id(override_->OverrideId().value())); + } + + auto ty = Type(val->Type()); + const ast::Expression* init = nullptr; + if (override_->Initializer()) { + init = Expr(override_->Initializer()); + } + b.Override(name, ty, init, attrs); + } + + void Let(const core::ir::Let* let) { + auto* result = let->Result(); + Symbol name = NameFor(result); + Append(b.Decl(b.Let(name, Expr(let->Value())))); + Bind(result, name); + } + + void Phony(const core::ir::Phony* phony) { Append(b.Assign(b.Phony(), Expr(phony->Value()))); } + + void Store(const core::ir::Store* store) { + auto* dst = Expr(store->To()); + auto* src = Expr(store->From()); + Append(b.Assign(dst, src)); + } + + void StoreVectorElement(const core::ir::StoreVectorElement* store) { + auto* ptr = Expr(store->To()); + auto* val = Expr(store->Value()); + Append(b.Assign(VectorMemberAccess(ptr, store->Index()), val)); + } + + void Call(const core::ir::Call* call) { + auto args = tint::Transform<4>(call->Args(), [&](const core::ir::Value* arg) { + // Pointer-like arguments are passed by pointer, never reference. + return Expr(arg); + }); + tint::Switch( + call, // + [&](const core::ir::UserCall* c) { + auto* expr = b.Call(NameFor(c->Target()), std::move(args)); + if (call->Results().IsEmpty() || !call->Result()->IsUsed()) { + Append(b.CallStmt(expr)); + return; + } + Bind(c->Result(), expr); + }, + [&](const wgsl::ir::BuiltinCall* c) { + switch (c->Func()) { + case wgsl::BuiltinFn::kSubgroupBallot: + case wgsl::BuiltinFn::kSubgroupElect: + case wgsl::BuiltinFn::kSubgroupBroadcast: + case wgsl::BuiltinFn::kSubgroupBroadcastFirst: + case wgsl::BuiltinFn::kSubgroupShuffle: + case wgsl::BuiltinFn::kSubgroupShuffleXor: + case wgsl::BuiltinFn::kSubgroupShuffleUp: + case wgsl::BuiltinFn::kSubgroupShuffleDown: + case wgsl::BuiltinFn::kSubgroupAdd: + case wgsl::BuiltinFn::kSubgroupInclusiveAdd: + case wgsl::BuiltinFn::kSubgroupExclusiveAdd: + case wgsl::BuiltinFn::kSubgroupMul: + case wgsl::BuiltinFn::kSubgroupInclusiveMul: + case wgsl::BuiltinFn::kSubgroupExclusiveMul: + case wgsl::BuiltinFn::kSubgroupAnd: + case wgsl::BuiltinFn::kSubgroupOr: + case wgsl::BuiltinFn::kSubgroupXor: + case wgsl::BuiltinFn::kSubgroupMin: + case wgsl::BuiltinFn::kSubgroupMax: + case wgsl::BuiltinFn::kSubgroupAny: + case wgsl::BuiltinFn::kSubgroupAll: + case wgsl::BuiltinFn::kQuadBroadcast: + case wgsl::BuiltinFn::kQuadSwapX: + case wgsl::BuiltinFn::kQuadSwapY: + case wgsl::BuiltinFn::kQuadSwapDiagonal: + Enable(wgsl::Extension::kSubgroups); + break; + default: + break; + } + + const ast::CallExpression* expr = nullptr; + if (!c->ExplicitTemplateParams().IsEmpty()) { + Vector tmpl_args; + for (auto* e : c->ExplicitTemplateParams()) { + tmpl_args.Push(Type(e).expr); + } + expr = b.Call(b.Ident(c->Func(), std::move(tmpl_args)), std::move(args)); + } else { + expr = b.Call(c->Func(), std::move(args)); + } + + if (call->Results().IsEmpty() || !call->Result()->IsUsed()) { + Append(b.CallStmt(expr)); + return; + } + Bind(c->Result(), expr); + }, + [&](const core::ir::Construct* c) { + auto ty = Type(c->Result()->Type()); + Bind(c->Result(), b.Call(ty, std::move(args))); + }, + [&](const core::ir::Convert* c) { + auto ty = Type(c->Result()->Type()); + Bind(c->Result(), b.Call(ty, std::move(args))); + }, + [&](const core::ir::Bitcast* c) { + auto ty = Type(c->Result()->Type()); + Bind(c->Result(), b.Bitcast(ty, args[0])); + }, + [&](const core::ir::Discard*) { Append(b.Discard()); }, // + TINT_ICE_ON_NO_MATCH); + } + + void Load(const core::ir::Load* l) { + bool reusable = false; + // Read-only pointer is reusable inline + if (auto* ptr = l->From()->Type()->As()) { + reusable = ptr->Access() == core::Access::kRead; + } + if (reusable) { + Bind(l->Result(), l->From()); + } else { + Bind(l->Result(), Expr(l->From())); + } + } + + void LoadVectorElement(const core::ir::LoadVectorElement* l) { + auto* vec = Expr(l->From()); + Bind(l->Result(), VectorMemberAccess(vec, l->Index())); + } + + void Unary(const core::ir::Unary* u) { + const ast::Expression* expr = nullptr; + switch (u->Op()) { + case core::UnaryOp::kComplement: + expr = b.Complement(Expr(u->Val())); + break; + case core::UnaryOp::kNegation: + expr = b.Negation(Expr(u->Val())); + break; + case core::UnaryOp::kNot: + expr = b.Not(Expr(u->Val())); + break; + case core::UnaryOp::kAddressOf: + expr = b.AddressOf(Expr(u->Val())); + break; + case core::UnaryOp::kIndirection: + expr = b.Deref(Expr(u->Val())); + break; + } + Bind(u->Result(), expr); + } + + void Access(const core::ir::Access* a) { + auto* expr = Expr(a->Object()); + auto* obj_ty = a->Object()->Type()->UnwrapRef(); + for (auto* index : a->Indices()) { + tint::Switch( + obj_ty, + [&](const core::type::Vector* vec) { + TINT_DEFER(obj_ty = vec->Type()); + expr = VectorMemberAccess(expr, index); + }, + [&](const core::type::Matrix* mat) { + obj_ty = mat->ColumnType(); + expr = b.IndexAccessor(expr, Expr(index)); + }, + [&](const core::type::Array* arr) { + obj_ty = arr->ElemType(); + expr = b.IndexAccessor(expr, Expr(index)); + }, + [&](const core::type::BindingArray* arr) { + obj_ty = arr->ElemType(); + expr = b.IndexAccessor(expr, Expr(index)); + }, + [&](const core::type::Struct* s) { + if (auto* c = index->As()) { + auto i = c->Value()->ValueAs(); + TINT_IR_ASSERT(mod, i < s->Members().Length()); + auto* member = s->Members()[i]; + obj_ty = member->Type(); + expr = b.MemberAccessor(expr, SanitizedMemberName(member)); + } else { + TINT_IR_ICE(mod) + << "invalid index for struct type: " << index->TypeInfo().name; + } + }, // + TINT_ICE_ON_NO_MATCH); + } + Bind(a->Result(), expr); + } + + void Swizzle(const core::ir::Swizzle* s) { + static constexpr std::array xyzw = {'x', 'y', 'z', 'w'}; + auto* vec = Expr(s->Object()); + Vector components; + for (uint32_t i : s->Indices()) { + if (i >= 4) { + TINT_IR_ICE(mod) << "invalid swizzle index: " << i; + } + components.Push(xyzw[i]); + } + auto* swizzle = + b.MemberAccessor(vec, std::string_view(components.begin(), components.Length())); + Bind(s->Result(), swizzle); + } + + void Binary(const core::ir::Binary* e) { + if (e->Op() == core::BinaryOp::kEqual) { + auto* rhs = e->RHS()->As(); + if (rhs && rhs->Type()->Is() && + rhs->Value()->ValueAs() == false) { + // expr == false + Bind(e->Result(), b.Not(Expr(e->LHS()))); + return; + } + } + auto* lhs = Expr(e->LHS()); + auto* rhs = Expr(e->RHS()); + const ast::Expression* expr = nullptr; + switch (e->Op()) { + case core::BinaryOp::kAdd: + expr = b.Add(lhs, rhs); + break; + case core::BinaryOp::kSubtract: + expr = b.Sub(lhs, rhs); + break; + case core::BinaryOp::kMultiply: + expr = b.Mul(lhs, rhs); + break; + case core::BinaryOp::kDivide: + expr = b.Div(lhs, rhs); + break; + case core::BinaryOp::kModulo: + expr = b.Mod(lhs, rhs); + break; + case core::BinaryOp::kAnd: + expr = b.And(lhs, rhs); + break; + case core::BinaryOp::kOr: + expr = b.Or(lhs, rhs); + break; + case core::BinaryOp::kXor: + expr = b.Xor(lhs, rhs); + break; + case core::BinaryOp::kEqual: + expr = b.Equal(lhs, rhs); + break; + case core::BinaryOp::kNotEqual: + expr = b.NotEqual(lhs, rhs); + break; + case core::BinaryOp::kLessThan: + expr = b.LessThan(lhs, rhs); + break; + case core::BinaryOp::kGreaterThan: + expr = b.GreaterThan(lhs, rhs); + break; + case core::BinaryOp::kLessThanEqual: + expr = b.LessThanEqual(lhs, rhs); + break; + case core::BinaryOp::kGreaterThanEqual: + expr = b.GreaterThanEqual(lhs, rhs); + break; + case core::BinaryOp::kShiftLeft: + expr = b.Shl(lhs, rhs); + break; + case core::BinaryOp::kShiftRight: + expr = b.Shr(lhs, rhs); + break; + case core::BinaryOp::kLogicalAnd: + expr = b.LogicalAnd(lhs, rhs); + break; + case core::BinaryOp::kLogicalOr: + expr = b.LogicalOr(lhs, rhs); + break; + } + Bind(e->Result(), expr); + } + + const ast::Expression* Expr(const core::ir::Value* value) { + if (auto* cnst = value->As()) { + return Constant(cnst); + } + + auto lookup = bindings_.Get(value); + if (!lookup) { + TINT_IR_ICE(mod) << "Expr(" << (value ? value->TypeInfo().name : "null") + << ") value has no expression"; + } + + if (lookup->ast_expr != nullptr) { + return lookup->ast_expr; + } + if (lookup->ir_expr != nullptr) { + return Expr(lookup->ir_expr); + } + return b.Expr(lookup->name); + } + + const ast::Expression* Constant(const core::ir::Constant* c) { return Constant(c->Value()); } + + const ast::Expression* Constant(const core::constant::Value* c) { + auto composite = [&](bool can_splat) { + auto ty = Type(c->Type()); + if (c->AllZero()) { + return b.Call(ty); + } + if (can_splat && c->Is()) { + return b.Call(ty, Constant(c->Index(0))); + } + + Vector els; + for (size_t i = 0, n = c->NumElements(); i < n; i++) { + els.Push(Constant(c->Index(i))); + } + return b.Call(ty, std::move(els)); + }; + return tint::Switch( + c->Type(), // + [&](const core::type::I32*) -> const ast::Expression* { + auto val = c->ValueAs(); + if (val == std::numeric_limits::min()) { + return b.Call(b.ty.i32(), b.create( + val, ast::IntLiteralExpression::Suffix::kNone)); + } + + return b.Expr(val); + }, + [&](const core::type::U32*) { return b.Expr(c->ValueAs()); }, + [&](const core::type::F32*) { return b.Expr(c->ValueAs()); }, + [&](const core::type::F16*) { + Enable(wgsl::Extension::kF16); + return b.Expr(c->ValueAs()); + }, + [&](const core::type::Bool*) { return b.Expr(c->ValueAs()); }, + [&](const core::type::Array*) { return composite(/* can_splat */ false); }, + [&](const core::type::Vector*) { return composite(/* can_splat */ true); }, + [&](const core::type::Matrix*) { return composite(/* can_splat */ false); }, + [&](const core::type::Struct*) { return composite(/* can_splat */ false); }, // + TINT_ICE_ON_NO_MATCH); + } + + void Enable(wgsl::Extension ext) { + if (enables_.Add(ext)) { + b.Enable(ext); + } + } + + /// @param ty the type::Type + /// @return an ast::Type from @p ty. + /// @note May be a semantically-invalid placeholder type on error. + ast::Type Type(const core::type::Type* ty) { + return tint::Switch( + ty, // + [&](const core::type::Void*) { return ast::Type{}; }, // + [&](const core::type::I32*) { return b.ty.i32(); }, // + [&](const core::type::U32*) { return b.ty.u32(); }, // + [&](const core::type::F16*) { + Enable(wgsl::Extension::kF16); + return b.ty.f16(); + }, + [&](const core::type::F32*) { return b.ty.f32(); }, // + [&](const core::type::Bool*) { return b.ty.bool_(); }, + [&](const core::type::Matrix* m) { + return b.ty.mat(Type(m->Type()), m->Columns(), m->Rows()); + }, + [&](const core::type::Vector* v) { + auto el = Type(v->Type()); + return b.ty.vec(el, v->Width()); + }, + [&](const core::type::Array* a) { + if (ContainsBuiltinStruct(a)) { + // The element type is untypeable, so we need to infer it instead. + return ast::Type{b.Expr(b.Ident("array"))}; + } + + auto el = Type(a->ElemType()); + if (a->Count()->Is()) { + return b.ty.array(el); + } + auto count = a->ConstantCount(); + if (!count) { + TINT_IR_ICE(mod) << core::type::Array::kErrExpectedConstantCount; + } + return b.ty.array(el, u32(count.value())); + }, + [&](const core::type::Struct* s) { return Struct(s); }, + [&](const core::type::Atomic* a) { return b.ty.atomic(Type(a->Type())); }, + [&](const core::type::DepthTexture* t) { return b.ty.depth_texture(t->Dim()); }, + [&](const core::type::DepthMultisampledTexture* t) { + return b.ty.depth_multisampled_texture(t->Dim()); + }, + [&](const core::type::ExternalTexture*) { return b.ty.external_texture(); }, + [&](const core::type::MultisampledTexture* t) { + auto el = Type(t->Type()); + return b.ty.multisampled_texture(t->Dim(), el); + }, + [&](const core::type::SampledTexture* t) { + auto el = Type(t->Type()); + return b.ty.sampled_texture(t->Dim(), el); + }, + [&](const core::type::StorageTexture* t) { + if (RequiresChromiumInternalGraphite(t)) { + Enable(wgsl::Extension::kChromiumInternalGraphite); + } + + return b.ty.storage_texture(t->Dim(), t->TexelFormat(), t->Access()); + }, + [&](const core::type::Sampler* s) { return b.ty.sampler(s->Kind()); }, + [&](const core::type::Pointer* p) { + // Note: type::Pointer always has an inferred access, but WGSL only allows an + // explicit access in the 'storage' address space. + auto el = Type(p->StoreType()); + auto address_space = p->AddressSpace(); + auto access = address_space == core::AddressSpace::kStorage + ? p->Access() + : core::Access::kUndefined; + return b.ty.ptr(address_space, el, access); + }, + [&](const core::type::Reference*) -> ast::Type { + TINT_IR_ICE(mod) << "reference types should never appear in the IR"; + }, + [&](const core::type::InputAttachment* i) { + Enable(wgsl::Extension::kChromiumInternalInputAttachments); + auto el = Type(i->Type()); + return b.ty.input_attachment(el); + }, // + [&](const core::type::SubgroupMatrix* m) { + Enable(wgsl::Extension::kChromiumExperimentalSubgroupMatrix); + auto el = Type(m->Type()); + return b.ty.subgroup_matrix(m->Kind(), el, m->Columns(), m->Rows()); + }, // + [&](const core::type::BindingArray* ba) { + auto el = Type(ba->ElemType()); + if (ba->Count()->Is()) { + TINT_IR_ICE(mod) << core::type::Array::kErrExpectedConstantCount; + } + + if (auto* count = ba->Count()->As()) { + return b.ty.binding_array(el, u32(count->value)); + } + TINT_IR_ICE(mod) << core::type::Array::kErrExpectedConstantCount; + }, // + [&](const core::type::Buffer* buf) { + if (buf->Size() == 0) { + return b.ty.buffer(); + } + return b.ty.buffer(buf->Size()); + }, // + TINT_ICE_ON_NO_MATCH); + } + + ast::Type Struct(const core::type::Struct* s) { + // Skip builtin structures. + if (ContainsBuiltinStruct(s)) { + return ast::Type{}; + } + + auto n = structs_.GetOrAdd(s, [&] { + TINT_IR_ASSERT(mod, s->Members().Length() > 0); + uint32_t current_offset = s->Members()[0]->Offset(); + + Vector members; + + // Add padding before the first member if necessary. + if (current_offset > 0) { + TINT_IR_ASSERT(mod, current_offset % 4 == 0); + for (uint32_t i = 0; i < current_offset; i += 4) { + members.Push(b.Member("tint_pad_" + std::to_string(i), b.ty.u32())); + } + } + + for (const auto* m : s->Members()) { + auto ty = Type(m->Type()); + const auto& ir_attrs = m->Attributes(); + Vector ast_attrs; + + TINT_IR_ASSERT(mod, current_offset == m->Offset()); + + // If the next member requires an offset that is not automatically satisfied by + // its required alignment, we will need to increase the size of this member. + uint32_t size = m->Size(); + if (m->Index() < s->Members().Length() - 1) { + auto* next_member = s->Members()[m->Index() + 1]; + auto next_offset = tint::RoundUp(next_member->Align(), current_offset + size); + auto next_member_required_offset = next_member->Offset(); + if (next_offset < next_member_required_offset) { + uint32_t new_size = next_member_required_offset - current_offset; + TINT_IR_ASSERT(mod, new_size > size); + size = new_size; + } + current_offset = next_member_required_offset; + } + + if (m->Type()->Align() != m->Align()) { + ast_attrs.Push(b.MemberAlign(u32(m->Align()))); + } + if (m->Type()->Size() != size) { + ast_attrs.Push(b.MemberSize(u32(size))); + } + if (auto location = ir_attrs.location) { + ast_attrs.Push(b.Location(u32(*location))); + } + if (auto blend_src = ir_attrs.blend_src) { + Enable(wgsl::Extension::kDualSourceBlending); + ast_attrs.Push(b.BlendSrc(u32(*blend_src))); + } + if (auto color = ir_attrs.color) { + Enable(wgsl::Extension::kChromiumExperimentalFramebufferFetch); + ast_attrs.Push(b.Color(u32(*color))); + } + if (auto builtin = ir_attrs.builtin) { + if (RequiresSubgroups(*builtin)) { + Enable(wgsl::Extension::kSubgroups); + } else if (*builtin == core::BuiltinValue::kClipDistances) { + Enable(wgsl::Extension::kClipDistances); + } + ast_attrs.Push(b.Builtin(*builtin)); + } + if (auto interpolation = ir_attrs.interpolation) { + ast_attrs.Push(b.Interpolate(interpolation->type, interpolation->sampling)); + } + if (ir_attrs.invariant) { + ast_attrs.Push(b.Invariant()); + } + + auto name = SanitizedMemberName(m); + members.Push(b.Member(name, ty, std::move(ast_attrs))); + } + + // TODO(crbug.com/tint/1902): Emit structure attributes + Vector attrs; + + // Sanitize the name of the structure. + Symbol name; + if (IsWGSLSafe(s->Name().NameView())) { + name = b.Symbols().Register(s->Name().NameView()); + } else { + name = b.Symbols().New("S"); + } + + b.Structure(name, std::move(members), std::move(attrs)); + return name; + }); + + return b.ty(n); + } + + bool ContainsBuiltinStruct(const core::type::Type* ty) { + if (auto* s = ty->As()) { + // Note: We don't need to check the members of the struct, as builtin structures cannot + // be nested inside other structures. + if (s->IsWgslInternal()) { + return true; + } + } else if (auto* a = ty->As()) { + return ContainsBuiltinStruct(a->ElemType()); + } + return false; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Bindings + //////////////////////////////////////////////////////////////////////////////////////////////// + + bool IsWGSLSafe(std::string_view name) { + if (name.empty()) { + return false; + } + + // Make sure the name starts with an alphabetic character or an underscore. + if (name[0] == '_') { + // Single underscores or names with two leading underscores are not allowed. + if (name.length() == 1) { + return false; + } else if (name[1] == '_') { + return false; + } + } else if (!std::isalpha(static_cast(name[0]))) { + return false; + } + + // Every other character must be alphanumeric or an underscore. + if (!std::all_of(name.begin(), name.end(), + [](unsigned char c) { // + return std::isalnum(c) || c == '_'; + })) { + return false; + } + + // Check for any kind of reserved identifier. + return !IsReserved(name) && !IsKeyword(name) && !IsEnumName(name) && !IsTypeName(name); + } + + /// @returns the AST name for the given value, creating and returning a new name on the first + /// call. + Symbol NameFor(const core::ir::Value* value, std::string_view suggested = {}) { + return names_.GetOrAdd(value, [&] { + if (!suggested.empty()) { + if (IsWGSLSafe(suggested)) { + return b.Symbols().Register(suggested); + } + } else if (auto sym = mod.NameOf(value)) { + if (IsWGSLSafe(sym.NameView())) { + return b.Symbols().Register(sym.NameView()); + } + } + return b.Symbols().New("v"); + }); + } + + /// @returns the AST name for the given struct member + Symbol SanitizedMemberName(const core::type::StructMember* member) { + return member_names_.GetOrAdd(member, [&] { + if (IsWGSLSafe(member->Name().NameView())) { + return b.Symbols().Register(member->Name().NameView()); + } + return b.Symbols().New("m"); + }); + } + + void Bind(const core::ir::Value* value, const core::ir::Value* expr) { + TINT_IR_ASSERT(mod, value); + if (value->IsUsed()) { + bindings_.Replace(value, ValueBinding{.ir_expr = expr}); + } else { + Append(b.Assign(b.Phony(), Expr(expr))); + } + } + + /// Associates the IR value @p value with the AST expression @p expr if it is used, otherwise + /// creates a phony assignment with @p expr. + void Bind(const core::ir::Value* value, const ast::Expression* expr) { + TINT_IR_ASSERT(mod, value); + if (value->IsUsed()) { + if (!bindings_.Add(value, ValueBinding{.ast_expr = expr})) { + TINT_IR_ICE(mod) << "Bind(" << value->TypeInfo().name + << ") called twice for same value"; + } + } else { + Append(b.Assign(b.Phony(), expr)); + } + } + + /// Associates the IR value @p value with the AST 'var', 'let' or parameter with the name @p + /// name. + void Bind(const core::ir::Value* value, Symbol name) { + TINT_IR_ASSERT(mod, value); + if (!bindings_.Add(value, ValueBinding{.name = name})) { + TINT_IR_ICE(mod) << "Bind(" << value->TypeInfo().name + << ") called twice for same value"; + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////////////////////////////// + bool AsShortCircuit(const core::ir::If* i, + const StatementList& true_stmts, + const StatementList& false_stmts) { + if (i->Results().IsEmpty()) { + return false; + } + auto* result = i->Result(); + if (!result->Type()->Is()) { + return false; // Wrong result type + } + if (i->Exits().Count() != 2) { + return false; // Doesn't have two exits + } + if (!true_stmts.IsEmpty() || !false_stmts.IsEmpty()) { + return false; // True or False blocks contain statements + } + + auto* cond = i->Condition(); + auto* true_val = i->True()->Back()->Operands().Front(); + auto* false_val = i->False()->Back()->Operands().Front(); + if (IsConstant(false_val, false)) { + // %res = if %cond { + // block { # true + // exit_if %true_val; + // } + // block { # false + // exit_if false; + // } + // } + // + // transform into: + // + // res = cond && true_val; + // + auto* lhs = Expr(cond); + auto* rhs = Expr(true_val); + Bind(result, b.LogicalAnd(lhs, rhs)); + return true; + } + if (IsConstant(true_val, true)) { + // %res = if %cond { + // block { # true + // exit_if true; + // } + // block { # false + // exit_if %false_val; + // } + // } + // + // transform into: + // + // res = cond || false_val; + // + auto* lhs = Expr(cond); + auto* rhs = Expr(false_val); + Bind(result, b.LogicalOr(lhs, rhs)); + return true; + } + return false; + } + + bool IsConstant(const core::ir::Value* val, bool value) { + if (auto* c = val->As()) { + if (c->Type()->Is()) { + return c->Value()->ValueAs() == value; + } + } + return false; + } + + const ast::Expression* VectorMemberAccess(const ast::Expression* expr, + const core::ir::Value* index) { + if (auto* c = index->As()) { + switch (c->Value()->ValueAs()) { + case 0: + return b.MemberAccessor(expr, "x"); + case 1: + return b.MemberAccessor(expr, "y"); + case 2: + return b.MemberAccessor(expr, "z"); + case 3: + return b.MemberAccessor(expr, "w"); + } + } + return b.IndexAccessor(expr, Expr(index)); + } + + /// @returns true if the builtin value requires the kSubgroups extension to be enabled. + bool RequiresSubgroups(core::BuiltinValue builtin) { + switch (builtin) { + case core::BuiltinValue::kSubgroupInvocationId: + case core::BuiltinValue::kSubgroupSize: + return true; + default: + return false; + } + } + + /// @returns true if the storage texture type requires the kChromiumInternalGraphite extension + /// to be enabled. + bool RequiresChromiumInternalGraphite(const core::type::StorageTexture* tex) { + return tex->TexelFormat() == core::TexelFormat::kR8Unorm; + } +}; + +} // namespace + +Program IRToProgram(const core::ir::Module& i, const Options& options) { + return State{i}.Run(options); +} + +} // namespace tint::wgsl::writer diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h new file mode 100644 index 000000000..c8e744e32 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_ +#define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_ + +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/writer/common/options.h" + +namespace tint::core::ir { +class Module; +} + +namespace tint::wgsl::writer { + +/// Builds a tint::Program from an core::ir::Module +/// @param module the IR module +/// @param options the configuration options +/// @return the tint::Program. +/// @note Check the returned Program::Diagnostics() for any errors. +Program IRToProgram(const core::ir::Module& module, const Options& options = {}); + +} // namespace tint::wgsl::writer + +#endif // SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/output.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/output.cc new file mode 100644 index 000000000..5f81b9515 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/output.cc @@ -0,0 +1,38 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/output.h" + +namespace tint::wgsl::writer { + +Output::Output() = default; + +Output::~Output() = default; + +Output::Output(const Output&) = default; + +} // namespace tint::wgsl::writer diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/output.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/output.h new file mode 100644 index 000000000..992e72606 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/output.h @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_OUTPUT_H_ +#define SRC_TINT_LANG_WGSL_WRITER_OUTPUT_H_ + +#include + +namespace tint::wgsl::writer { + +/// The output produced when generating WGSL. +struct Output { + /// Constructor + Output(); + + /// Destructor + ~Output(); + + /// Copy constructor + Output(const Output&); + + /// The generated WGSL. + std::string wgsl = ""; +}; + +} // namespace tint::wgsl::writer + +#endif // SRC_TINT_LANG_WGSL_WRITER_OUTPUT_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.cc new file mode 100644 index 000000000..610d3adfd --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.cc @@ -0,0 +1,156 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/raise/ptr_to_ref.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/function.h" +#include "src/tint/lang/core/ir/let.h" +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/lang/core/ir/phony.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/lang/core/ir/var.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/core/type/reference.h" +#include "src/tint/lang/wgsl/ir/unary.h" +#include "src/tint/utils/containers/reverse.h" + +namespace tint::wgsl::writer::raise { +namespace { + +struct Impl { + core::ir::Module& mod; + core::ir::Builder b{mod}; + + void Run() { + Vector blocks; + for (auto fn : mod.functions) { + blocks.Push(fn->Block()); + } + blocks.Push(mod.root_block); + + while (!blocks.IsEmpty()) { + auto* block = blocks.Pop(); + for (auto* inst : *block) { + tint::Switch( + inst, // + [&](core::ir::Var* var) { ResultPtrToRef(var); }, + [&](core::ir::Let* let) { + OperandRefToPtr({let, core::ir::Let::kValueOperandOffset}); + }, + [&](core::ir::Phony* p) { + OperandRefToPtr({p, core::ir::Phony::kValueOperandOffset}); + }, + [&](core::ir::Call* call) { OperandsRefToPtr(call); }, + [&](core::ir::Access* access) { + OperandPtrToRef({access, core::ir::Access::kObjectOperandOffset}); + ResultPtrToRef(access); + }, + [&](core::ir::Store* store) { + OperandPtrToRef({store, core::ir::Store::kToOperandOffset}); + }, + [&](core::ir::StoreVectorElement* store) { + OperandPtrToRef({store, core::ir::StoreVectorElement::kToOperandOffset}); + }, + [&](core::ir::Load* load) { + OperandPtrToRef({load, core::ir::Load::kFromOperandOffset}); + }, + [&](core::ir::LoadVectorElement* load) { + OperandPtrToRef({load, core::ir::LoadVectorElement::kFromOperandOffset}); + }, + [&](core::ir::ControlInstruction* ctrl) { + Vector children; + ctrl->ForeachBlock([&](core::ir::Block* child) { children.Push(child); }); + for (auto* child : Reverse(children)) { + blocks.Push(child); + } + }); + } + } + } + + void OperandsRefToPtr(core::ir::Instruction* inst) { + for (size_t i = 0, n = inst->Operands().Length(); i < n; i++) { + OperandRefToPtr({inst, i}); + } + } + + void OperandRefToPtr(const core::ir::Usage& use) { + auto* operand = use.instruction->Operand(use.operand_index); + TINT_IR_ASSERT(mod, operand); + if (auto* ref_ty = As(operand->Type())) { + auto* as_ptr = b.InstructionResult(RefToPtr(ref_ty)); + mod.CreateInstruction(as_ptr, core::UnaryOp::kAddressOf, operand) + ->InsertBefore(use.instruction); + use.instruction->SetOperand(use.operand_index, as_ptr); + } + } + + const core::type::Pointer* RefToPtr(const core::type::Reference* ref_ty) { + return mod.Types().ptr(ref_ty->AddressSpace(), ref_ty->StoreType(), ref_ty->Access()); + } + + void OperandPtrToRef(const core::ir::Usage& use) { + auto* operand = use.instruction->Operand(use.operand_index); + if (auto* ptr_ty = As(operand->Type())) { + auto* as_ptr = b.InstructionResult(PtrToRef(ptr_ty)); + mod.CreateInstruction(as_ptr, core::UnaryOp::kIndirection, operand) + ->InsertBefore(use.instruction); + use.instruction->SetOperand(use.operand_index, as_ptr); + } + } + + void ResultPtrToRef(core::ir::Instruction* inst) { + auto* result = inst->Result(); + if (auto* ptr = result->Type()->As()) { + result->SetType(PtrToRef(ptr)); + } + } + + const core::type::Reference* PtrToRef(const core::type::Pointer* ptr_ty) { + return mod.Types().ref(ptr_ty->AddressSpace(), ptr_ty->StoreType(), ptr_ty->Access()); + } +}; + +} // namespace + +Result PtrToRef(core::ir::Module& mod) { + TINT_CHECK_RESULT(core::ir::ValidateAndDumpIfNeeded( + mod, "wgsl.PtrToRef", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + core::ir::Capability::kAllowPhonyInstructions, + } + + )); + + Impl{mod}.Run(); + + return Success; +} + +} // namespace tint::wgsl::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.h new file mode 100644 index 000000000..3be16a386 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/ptr_to_ref.h @@ -0,0 +1,48 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_RAISE_PTR_TO_REF_H_ +#define SRC_TINT_LANG_WGSL_WRITER_RAISE_PTR_TO_REF_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::wgsl::writer::raise { + +/// PtrToRef is a transform that modifies values and instructions to convert from pointer types to +/// reference types. +/// @param module the module to transform +/// @returns success or failure +Result PtrToRef(core::ir::Module& module); + +} // namespace tint::wgsl::writer::raise + +#endif // SRC_TINT_LANG_WGSL_WRITER_RAISE_PTR_TO_REF_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.cc new file mode 100644 index 000000000..2876bdf92 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.cc @@ -0,0 +1,288 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/raise/raise.h" + +#include + +#include "src/tint/lang/core/enums.h" +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/core_builtin_call.h" +#include "src/tint/lang/core/ir/load.h" +#include "src/tint/lang/core/ir/transform/rename_conflicts.h" +#include "src/tint/lang/core/type/pointer.h" +#include "src/tint/lang/wgsl/enums.h" +#include "src/tint/lang/wgsl/ir/builtin_call.h" +#include "src/tint/lang/wgsl/writer/raise/ptr_to_ref.h" +#include "src/tint/lang/wgsl/writer/raise/value_to_let.h" + +namespace tint::wgsl::writer { +namespace { + +wgsl::BuiltinFn Convert(core::BuiltinFn fn) { +#define CASE(NAME) \ + case core::BuiltinFn::NAME: \ + return wgsl::BuiltinFn::NAME; + + switch (fn) { + CASE(kAbs) + CASE(kAcos) + CASE(kAcosh) + CASE(kAll) + CASE(kAny) + CASE(kArrayLength) + CASE(kAsin) + CASE(kAsinh) + CASE(kAtan) + CASE(kAtan2) + CASE(kAtanh) + CASE(kCeil) + CASE(kClamp) + CASE(kCos) + CASE(kCosh) + CASE(kCountLeadingZeros) + CASE(kCountOneBits) + CASE(kCountTrailingZeros) + CASE(kCross) + CASE(kDegrees) + CASE(kDeterminant) + CASE(kDistance) + CASE(kDot) + CASE(kDot4I8Packed) + CASE(kDot4U8Packed) + CASE(kDpdx) + CASE(kDpdxCoarse) + CASE(kDpdxFine) + CASE(kDpdy) + CASE(kDpdyCoarse) + CASE(kDpdyFine) + CASE(kExp) + CASE(kExp2) + CASE(kExtractBits) + CASE(kFaceForward) + CASE(kFirstLeadingBit) + CASE(kFirstTrailingBit) + CASE(kFloor) + CASE(kFma) + CASE(kFract) + CASE(kFrexp) + CASE(kFwidth) + CASE(kFwidthCoarse) + CASE(kFwidthFine) + CASE(kInsertBits) + CASE(kInverseSqrt) + CASE(kLdexp) + CASE(kLength) + CASE(kLog) + CASE(kLog2) + CASE(kMax) + CASE(kMin) + CASE(kMix) + CASE(kModf) + CASE(kNormalize) + CASE(kPack2X16Float) + CASE(kPack2X16Snorm) + CASE(kPack2X16Unorm) + CASE(kPack4X8Snorm) + CASE(kPack4X8Unorm) + CASE(kPack4XI8) + CASE(kPack4XU8) + CASE(kPack4XI8Clamp) + CASE(kPack4XU8Clamp) + CASE(kPow) + CASE(kQuantizeToF16) + CASE(kRadians) + CASE(kReflect) + CASE(kRefract) + CASE(kReverseBits) + CASE(kRound) + CASE(kSaturate) + CASE(kSelect) + CASE(kSign) + CASE(kSin) + CASE(kSinh) + CASE(kSmoothstep) + CASE(kSqrt) + CASE(kStep) + CASE(kStorageBarrier) + CASE(kTan) + CASE(kTanh) + CASE(kTranspose) + CASE(kTrunc) + CASE(kUnpack2X16Float) + CASE(kUnpack2X16Snorm) + CASE(kUnpack2X16Unorm) + CASE(kUnpack4X8Snorm) + CASE(kUnpack4X8Unorm) + CASE(kUnpack4XI8) + CASE(kUnpack4XU8) + CASE(kWorkgroupBarrier) + CASE(kTextureBarrier) + CASE(kTextureDimensions) + CASE(kTextureGather) + CASE(kTextureGatherCompare) + CASE(kTextureNumLayers) + CASE(kTextureNumLevels) + CASE(kTextureNumSamples) + CASE(kTextureSample) + CASE(kTextureSampleBias) + CASE(kTextureSampleCompare) + CASE(kTextureSampleCompareLevel) + CASE(kTextureSampleGrad) + CASE(kTextureSampleLevel) + CASE(kTextureSampleBaseClampToEdge) + CASE(kTextureStore) + CASE(kTextureLoad) + CASE(kAtomicLoad) + CASE(kAtomicStore) + CASE(kAtomicAdd) + CASE(kAtomicSub) + CASE(kAtomicMax) + CASE(kAtomicMin) + CASE(kAtomicAnd) + CASE(kAtomicOr) + CASE(kAtomicXor) + CASE(kAtomicExchange) + CASE(kAtomicCompareExchangeWeak) + CASE(kSubgroupBallot) + CASE(kSubgroupElect) + CASE(kSubgroupBroadcast) + CASE(kSubgroupBroadcastFirst) + CASE(kSubgroupShuffle) + CASE(kSubgroupShuffleXor) + CASE(kSubgroupShuffleUp) + CASE(kSubgroupShuffleDown) + CASE(kSubgroupAdd) + CASE(kSubgroupInclusiveAdd) + CASE(kSubgroupExclusiveAdd) + CASE(kSubgroupMul) + CASE(kSubgroupInclusiveMul) + CASE(kSubgroupExclusiveMul) + CASE(kInputAttachmentLoad) + CASE(kSubgroupAnd) + CASE(kSubgroupOr) + CASE(kSubgroupXor) + CASE(kSubgroupMin) + CASE(kSubgroupMax) + CASE(kSubgroupAny) + CASE(kSubgroupAll) + CASE(kQuadBroadcast) + CASE(kQuadSwapX) + CASE(kQuadSwapY) + CASE(kQuadSwapDiagonal) + CASE(kSubgroupMatrixLoad) + CASE(kSubgroupMatrixStore) + CASE(kSubgroupMatrixMultiply) + CASE(kSubgroupMatrixMultiplyAccumulate) + CASE(kSubgroupMatrixScalarAdd) + CASE(kSubgroupMatrixScalarSubtract) + CASE(kSubgroupMatrixScalarMultiply) + CASE(kPrint) + CASE(kHasResource) + CASE(kGetResource) + CASE(kBufferView) + CASE(kBufferLength) + case core::BuiltinFn::kNone: + break; + } + TINT_ICE() << "unhandled builtin function: " << fn; +} + +void ReplaceBuiltinFnCall(core::ir::Builder& b, core::ir::CoreBuiltinCall* call) { + Vector args(call->Args()); + auto* replacement = b.CallWithResult( + call->DetachResult(), Convert(call->Func()), std::move(args)); + if (!call->ExplicitTemplateParams().IsEmpty()) { + Vector tmpl_args; + for (auto p : call->ExplicitTemplateParams()) { + tmpl_args.Push(p); + } + replacement->SetExplicitTemplateParams(std::move(tmpl_args)); + } + call->ReplaceWith(replacement); + call->Destroy(); +} + +void ReplaceWorkgroupBarrier(core::ir::Builder& b, core::ir::CoreBuiltinCall* call) { + // Pattern match: + // call workgroupBarrier + // %value = load &ptr + // call workgroupBarrier + // And replace with: + // %value = call workgroupUniformLoad %ptr + + auto* load = As(call->next); + if (!load || load->From()->Type()->As()->AddressSpace() != + core::AddressSpace::kWorkgroup) { + // No match + ReplaceBuiltinFnCall(b, call); + return; + } + + auto* post_load = As(load->next); + if (!post_load || post_load->Func() != core::BuiltinFn::kWorkgroupBarrier) { + // No match + ReplaceBuiltinFnCall(b, call); + return; + } + + // Remove both calls to workgroupBarrier + post_load->Destroy(); + call->Destroy(); + + // Replace load with workgroupUniformLoad + auto* replacement = b.CallWithResult( + load->DetachResult(), wgsl::BuiltinFn::kWorkgroupUniformLoad, Vector{load->From()}); + load->ReplaceWith(replacement); + load->Destroy(); +} + +} // namespace + +Result Raise(core::ir::Module& mod) { + TINT_CHECK_RESULT(core::ir::transform::RenameConflicts(mod)); + + core::ir::Builder b{mod}; + for (auto* inst : mod.Instructions()) { + if (auto* call = inst->As()) { + switch (call->Func()) { + case core::BuiltinFn::kWorkgroupBarrier: + ReplaceWorkgroupBarrier(b, call); + break; + default: + ReplaceBuiltinFnCall(b, call); + break; + } + } + } + TINT_CHECK_RESULT(raise::ValueToLet(mod)); + TINT_CHECK_RESULT(raise::PtrToRef(mod)); + + return Success; +} + +} // namespace tint::wgsl::writer diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.h new file mode 100644 index 000000000..c4a60ae35 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/raise.h @@ -0,0 +1,43 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_RAISE_RAISE_H_ +#define SRC_TINT_LANG_WGSL_WRITER_RAISE_RAISE_H_ + +#include "src/tint/lang/core/ir/module.h" +#include "src/tint/utils/result.h" + +namespace tint::wgsl::writer { + +/// Raise converts a core-dialect IR module to a WGSL-dialect IR module +/// @param mod the IR module +/// @return the result of the operation +Result Raise(core::ir::Module& mod); + +} // namespace tint::wgsl::writer + +#endif // SRC_TINT_LANG_WGSL_WRITER_RAISE_RAISE_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.cc new file mode 100644 index 000000000..628534834 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.cc @@ -0,0 +1,214 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/raise/value_to_let.h" + +#include +#include + +#include "src/tint/lang/core/ir/builder.h" +#include "src/tint/lang/core/ir/phony.h" +#include "src/tint/lang/core/ir/validator.h" +#include "src/tint/utils/containers/reverse.h" + +namespace tint::wgsl::writer::raise { + +namespace { + +/// PIMPL state for the transform. +struct State { + /// The IR module. + core::ir::Module& ir; + + /// The IR builder. + core::ir::Builder b{ir}; + + /// The type manager. + core::type::Manager& ty{ir.Types()}; + + /// Process the module. + void Process() { + // Process each block. + for (auto* block : ir.blocks.Objects()) { + if (block != ir.root_block) { + Process(block); + } + } + } + + private: + void Process(core::ir::Block* block) { + // An ordered list of possibly-inlinable values returned by sequenced instructions that have + // not yet been marked-for or ruled-out-for inlining. + UniqueVector pending_resolution; + + auto hoist_pending = [&](size_t count = std::numeric_limits::max()) { + size_t n = std::min(count, pending_resolution.Length()); + if (n > 0) { + for (size_t i = 0; i < n; i++) { + MaybeReplaceWithLetOrPhony(pending_resolution[i]); + } + pending_resolution.Erase(0, n); + } + }; + + // Walk the instructions of the block starting with the first. + for (auto* inst = block->Front(); inst;) { + auto next = inst->next; + TINT_DEFER(inst = next); + + // Is the instruction sequenced? + bool sequenced = inst->Sequenced(); + + // Walk the instruction's operands starting with the right-most. + auto operands = inst->Operands(); + for (auto* operand : tint::Reverse(operands)) { + if (!operand) { + continue; + } + + auto* value = operand->As(); + if (!pending_resolution.Contains(value)) { + continue; + } + // Operand is in 'pending_resolution' + + if (pending_resolution.TryPop(value)) { + // Operand was the last sequenced value to be added to 'pending_resolution' + // This operand can be inlined as it does not change the sequencing order. + sequenced = true; // Inherit the 'sequenced' flag from the inlined value + } else { + // Operand was in 'pending_resolution', but was not the last sequenced value to + // be added. Inlining this operand would break the sequencing order, so must be + // emitted as a let. All preceding pending values must also be emitted as a + // let to prevent them being inlined and breaking the sequencing order. + // Remove all the values in pending up to and including 'operand'. + for (size_t i = 0; i < pending_resolution.Length(); i++) { + if (pending_resolution[i] == operand) { + hoist_pending(i + 1); + break; + } + } + } + } + + if (inst->Results().Length() == 1) { + // Instruction has a single result value. + // Check to see if the result of this instruction is a candidate for inlining. + auto* result = inst->Result(); + // Only values with a single usage can be inlined. + // Named values are not inlined, as we want to emit the name for a let. + if (CanInline(result)) { + if (sequenced) { + // The value comes from a sequenced instruction. We need to ensure + // instruction ordering so add it to 'pending_resolution'. + pending_resolution.Add(result); + } + continue; + } + + MaybeReplaceWithLetOrPhony(result); + } + + // At this point the value has been ruled out for inlining. + + if (sequenced) { + // A sequenced instruction with zero or multiple return values cannot be inlined. + // All preceding sequenced instructions cannot be inlined past this point. + hoist_pending(); + } + } + + hoist_pending(); + } + + bool CanInline(core::ir::InstructionResult* value) { + if (ir.NameOf(value).IsValid()) { + // Named values should become lets + return false; + } + + if (value->NumUsages() != 1) { + // Zero or multiple uses cannot be inlined + return false; + } + + return true; + } + + void MaybeReplaceWithLetOrPhony(core::ir::InstructionResult* value) { + auto* inst = value->Instruction(); + if (inst->IsAnyOf()) { + return; + } + // Never put handle types in lets or phonys + if (inst->Result()->Type()->IsHandle()) { + return; + } + if (inst->Is() && !value->IsUsed()) { + bool must_use = + inst->Is() && !value->Type()->Is(); + if (!must_use) { + return; // Call statement + } + } + + if (!value->IsUsed() && !ir.NameOf(value).IsValid()) { + auto* phony = b.Phony(value); + phony->InsertAfter(inst); + return; + } + + auto* let = b.Let(value->Type()); + value->ReplaceAllUsesWith(let->Result()); + let->SetValue(value); + let->InsertAfter(inst); + if (auto name = ir.NameOf(value); name.IsValid()) { + ir.SetName(let, name.Name()); + ir.ClearName(value); + } + } +}; + +} // namespace + +Result ValueToLet(core::ir::Module& ir) { + TINT_CHECK_RESULT(core::ir::ValidateAndDumpIfNeeded( + ir, "wgsl.ValueToLet", + core::ir::Capabilities{ + core::ir::Capability::kAllowMultipleEntryPoints, + core::ir::Capability::kAllowOverrides, + } + + )); + + State{ir}.Process(); + + return Success; +} + +} // namespace tint::wgsl::writer::raise diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.h new file mode 100644 index 000000000..7bc1bd3ed --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/raise/value_to_let.h @@ -0,0 +1,54 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_RAISE_VALUE_TO_LET_H_ +#define SRC_TINT_LANG_WGSL_WRITER_RAISE_VALUE_TO_LET_H_ + +#include "src/tint/utils/result.h" + +// Forward declarations. +namespace tint::core::ir { +class Module; +} + +namespace tint::wgsl::writer::raise { + +/// ValueToLet is a transform that moves "non-inlinable" instruction values to let instructions. +/// An expression is considered "non-inlinable" if any of the following are true: +/// * The value has multiple uses. +/// * The value's instruction is a load that when inlined would cross a store instruction. +/// * The value's instruction is a store instruction that when inlined would cross a load or store +/// instruction. +/// * The value is used in a block different to the value's instruction. +/// +/// @param module the module to transform +/// @returns error on failure +Result ValueToLet(core::ir::Module& module); + +} // namespace tint::wgsl::writer::raise + +#endif // SRC_TINT_LANG_WGSL_WRITER_RAISE_VALUE_TO_LET_H_ diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/writer.cc b/3rdparty/dawn/src/tint/lang/wgsl/writer/writer.cc new file mode 100644 index 000000000..964cdde83 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/writer.cc @@ -0,0 +1,69 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/lang/wgsl/writer/writer.h" + +#include + +#include "src/tint/lang/wgsl/program/program.h" +#include "src/tint/lang/wgsl/writer/ast_printer/ast_printer.h" +#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h" +#include "src/tint/lang/wgsl/writer/raise/raise.h" + +namespace tint::wgsl::writer { + +Result Generate(const Program& program, const Options& options) { + Output output; + + // Generate the WGSL code. + auto impl = std::make_unique(program, options); + if (!impl->Generate()) { + return Failure{impl->Diagnostics().Str()}; + } + output.wgsl = impl->Result(); + + return output; +} + +Result WgslFromIR(core::ir::Module& module, const Options& options) { + TINT_CHECK_RESULT_UNWRAP(res, ProgramFromIR(module, options)); + return Generate(res, options); +} + +Result ProgramFromIR(core::ir::Module& module, const Options& options) { + // core-dialect -> WGSL-dialect + TINT_CHECK_RESULT(Raise(module)); + + auto program = IRToProgram(module, options); + if (!program.IsValid()) { + return Failure{program.Diagnostics().Str()}; + } + + return program; +} + +} // namespace tint::wgsl::writer diff --git a/3rdparty/dawn/src/tint/lang/wgsl/writer/writer.h b/3rdparty/dawn/src/tint/lang/wgsl/writer/writer.h new file mode 100644 index 000000000..c35f05702 --- /dev/null +++ b/3rdparty/dawn/src/tint/lang/wgsl/writer/writer.h @@ -0,0 +1,65 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_LANG_WGSL_WRITER_WRITER_H_ +#define SRC_TINT_LANG_WGSL_WRITER_WRITER_H_ + +#include "src/tint/lang/wgsl/writer/common/options.h" +#include "src/tint/lang/wgsl/writer/output.h" +#include "src/tint/utils/result.h" + +// Forward declarations +namespace tint { +class Program; +} // namespace tint +namespace tint::core::ir { +class Module; +} // namespace tint::core::ir + +namespace tint::wgsl::writer { + +/// Generate WGSL for a program, according to a set of configuration options. +/// The result will contain the WGSL, or failure. +/// @param program the program to translate to WGSL +/// @param options the configuration options to use when printing WGSL +/// @returns the resulting WGSL, or failure +Result Generate(const Program& program, const Options& options = {}); + +/// Generate WGSL from a core-dialect ir::Module. +/// @param module the core-dialect ir::Module. +/// @param options the configuration options to use when generating WGSL +/// @returns the resulting WGSL, or failure +Result WgslFromIR(core::ir::Module& module, const Options& options); + +/// Generate a Program from a core-dialect ir::Module. +/// @param module the core-dialect ir::Module. +/// @returns the resulting Program, or failure +Result ProgramFromIR(core::ir::Module& module, const Options& options); + +} // namespace tint::wgsl::writer + +#endif // SRC_TINT_LANG_WGSL_WRITER_WRITER_H_ diff --git a/3rdparty/dawn/src/tint/tint.natvis b/3rdparty/dawn/src/tint/tint.natvis new file mode 100644 index 000000000..b5fb5f359 --- /dev/null +++ b/3rdparty/dawn/src/tint/tint.natvis @@ -0,0 +1,272 @@ + + + + + + + + + + + {{ length={len}, capacity={cap} }} + + + + len + data + + + + + + + + impl_.slice.cap > (int)$T2 + + + + Length() + impl_.slice.data + + + + + + + can_move_ + slice_ + + + + + + {name_,sb} + + + + + + + + {*lhs} = {*rhs}; + + *lhs + *rhs + + + + + if ({*condition}) {*body} + if ({*condition}) {*body} else { *else_statement } + + + + else {*body} + else if ({*condition}) {*body} + + + + {{ {*statements[0]} }} + {{ {*statements[0]} {*statements[1]} }} + {{ {*statements[0]} {*statements[1]} {*statements[2]} }} + {{ {*statements[0]} {*statements[1]} {*statements[2]} {statements.Length()-3} more... }} + + + + return; + return {*value}; + + + + fn {symbol}() -> {*return_type} {*body} + fn {symbol}({*params[0]}) -> {*return_type} {*body} + fn {symbol}({*params[0]} {*params[1]}) -> {*return_type} {*body} + fn {symbol}({*params[0]} {*params[1]} {*params[2]}) -> {*return_type} {*body} + fn {symbol}({*params[0]} {*params[1]} {*params[2]} {params.size()-3} more...) -> {*return_type} {*body} + + + + {symbol} + + symbol + + + + + {*identifier} + + identifier + + + + + {*object}[{*index}] + + *object + *index + + + + + {*member} + + *member + + + + + let {symbol} : {*type} = {*initializer} + let {symbol} = {*initializer} + + + + var {symbol} : {*type} = {*initializer} + var {symbol} : {*type} + var {symbol} = {*initializer} + var {symbol} + + + + {*variable}; + + + + {value} + + + + {value} + + + + &({*expr}) + ~({*expr}) + *({*expr}) + -({*expr}) + !({*expr}) + + + + ({*lhs} NONE {*rhs}) + ({*lhs} & {*rhs}) + ({*lhs} | {*rhs}) + ({*lhs} ^ {*rhs}) + ({*lhs} && {*rhs}) + ({*lhs} || {*rhs}) + ({*lhs} == {*rhs}) + ({*lhs} != {*rhs}) + ({*lhs} < {*rhs}) + ({*lhs} > {*rhs}) + ({*lhs} <= {*rhs}) + ({*lhs} >= {*rhs}) + ({*lhs} << {*rhs}) + ({*lhs} >> {*rhs}) + ({*lhs} + {*rhs}) + ({*lhs} - {*rhs}) + ({*lhs} * {*rhs}) + ({*lhs} / {*rhs}) + ({*lhs} % {*rhs}) + + + + {*target}() + {*target}({*args[0]}) + {*target}({*args[0]}, {*args[1]}) + {*target}({*args[0]}, {*args[1]}, {*args[2]}) + {*target}({*args[0]}, {*args[1]}, {*args[2]}, {*args[3]}) + {*target}({*args[0]}, {*args[1]}, {*args[2]}, {args.Length()-3} more...) + + + + + {*name} + {*type} + + + + array<{*type},{*count}> + array<{*type}> + + + + vec2 + vec3 + vec4 + vec2<{*type}> + vec3<{*type}> + vec4<{*type}> + + + + {name} + + + + + + + + AbstractInt + + + + AbstractFloat + + + + bool + + + + f32 + + + + i32 + + + + u32 + + + + vec{width_}<{*subtype_}> + + + + Type={*Type()} Value={InternalValue()} + + + + Decl={*declaration_} + + + diff --git a/3rdparty/dawn/src/tint/utils/bytes/buffer_reader.cc b/3rdparty/dawn/src/tint/utils/bytes/buffer_reader.cc new file mode 100644 index 000000000..5c790dd59 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/buffer_reader.cc @@ -0,0 +1,53 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/bytes/buffer_reader.h" + +#include + +#include "src/tint/utils/macros/compiler.h" + +namespace tint::bytes { + +BufferReader::~BufferReader() = default; + +// TODO(408010433): Rewrite internals using span to avoid UBU during read +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +size_t BufferReader::Read(std::byte* out, size_t count) { + size_t n = std::min(count, bytes_remaining_); + memcpy(out, data_, n); + data_ += n; + bytes_remaining_ -= n; + return n; +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +bool BufferReader::IsEOF() const { + return bytes_remaining_ == 0; +} + +} // namespace tint::bytes diff --git a/3rdparty/dawn/src/tint/utils/bytes/buffer_reader.h b/3rdparty/dawn/src/tint/utils/bytes/buffer_reader.h new file mode 100644 index 000000000..f75c7f692 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/buffer_reader.h @@ -0,0 +1,81 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_BYTES_BUFFER_READER_H_ +#define SRC_TINT_UTILS_BYTES_BUFFER_READER_H_ + +#include +#include +#include + +#include "src/tint/utils/bytes/reader.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::bytes { + +/// BufferReader is an implementation of the Reader interface backed by a buffer. +class BufferReader final : public Reader { + public: + // Destructor + ~BufferReader() override; + + /// Constructor + /// @param data the data to read from + /// @param size the number of bytes in the buffer + BufferReader(const std::byte* data, size_t size) : data_(data), bytes_remaining_(size) { + TINT_ASSERT(data); + } + + /// Constructor + /// @param str the string to read from + explicit BufferReader(std::string_view str) + : data_(reinterpret_cast(str.data())), bytes_remaining_(str.length()) {} + + /// Constructor + /// @param span the byte span to read from + explicit BufferReader(std::span span) + : data_(span.data()), bytes_remaining_(span.size()) { + TINT_ASSERT(span.data()); + } + + /// @copydoc Reader::Read + size_t Read(std::byte* out, size_t count) override; + + /// @copydoc Reader::IsEOF + bool IsEOF() const override; + + private: + /// The data to read from + const std::byte* data_ = nullptr; + + /// The number of bytes remaining + size_t bytes_remaining_ = 0; +}; + +} // namespace tint::bytes + +#endif // SRC_TINT_UTILS_BYTES_BUFFER_READER_H_ diff --git a/3rdparty/dawn/src/tint/utils/bytes/decoder.h b/3rdparty/dawn/src/tint/utils/bytes/decoder.h new file mode 100644 index 000000000..7e11538fe --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/decoder.h @@ -0,0 +1,273 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_BYTES_DECODER_H_ +#define SRC_TINT_UTILS_BYTES_DECODER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/utils/bytes/reader.h" +#include "src/tint/utils/reflection.h" +#include "src/tint/utils/result.h" + +namespace tint::bytes { + +template +struct Decoder; + +/// Decodes T from @p reader. +/// @param reader the byte reader +/// @param args additional arguments used by Decoder::Decode() +/// @returns the decoded object +template +Result Decode(Reader& reader, ARGS&&... args) { + return Decoder::Decode(reader, std::forward(args)...); +} + +/// Decoder specialization for integer types +template +struct Decoder>> { + /// Decode decodes the integer type from @p reader. + /// @param reader the reader to decode from + /// @param endianness the endianness of the integer + /// @returns the decoded integer type, or an error if the stream is too short. + static Result Decode(Reader& reader, Endianness endianness = Endianness::kLittle) { + return reader.Int(endianness); + } +}; + +/// Decoder specialization for floating point types +template +struct Decoder>> { + /// Decode decodes the floating point type from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded floating point type, or an error if the stream is too short. + static Result Decode(Reader& reader) { return reader.Float(); } +}; + +/// Decoder specialization for a uint16_t length prefixed string. +template <> +struct Decoder { + /// Decode decodes the string from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded string, or an error if the stream is too short. + static Result Decode(Reader& reader) { + TINT_CHECK_RESULT_UNWRAP(len, reader.Int()); + return reader.String(len); + } +}; + +/// Decoder specialization for bool types +template <> +struct Decoder { + /// Decode decodes the boolean from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded boolean, or an error if the stream is too short. + static Result Decode(Reader& reader) { return reader.Bool(); } +}; + +/// Decoder specialization for types that use TINT_REFLECT +template + requires(HasReflection) +struct Decoder { + /// Decode decodes the reflected type from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded reflected type, or an error if the stream is too short. + static Result Decode(Reader& reader) { + T object{}; + std::stringstream errs{}; + ForeachField(object, [&](auto& field) { // + auto value = bytes::Decode>(reader); + if (value == Success) { + field = value.Get(); + } else { + errs << value.Failure() << "\n"; + } + }); + auto err = errs.str(); + if (err.empty()) { + return object; + } + return Failure{err}; + } +}; + +/// Decoder specialization for std::unordered_map +template +struct Decoder, void> { + /// Decode decodes the map from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded map, or an error if the stream is too short. + static Result> Decode(Reader& reader) { + std::unordered_map out; + + while (!reader.IsEOF()) { + TINT_CHECK_RESULT_UNWRAP(stop, bytes::Decode(reader)); + if (stop) { + break; + } + TINT_CHECK_RESULT_UNWRAP(key, bytes::Decode(reader)); + TINT_CHECK_RESULT_UNWRAP(val, bytes::Decode(reader)); + out.emplace(std::move(key), std::move(val)); + } + + return out; + } +}; + +/// Decoder specialization for std::unordered_set +template +struct Decoder, void> { + /// Decode decodes the set from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded set, or an error if the stream is too short. + static Result> Decode(Reader& reader) { + std::unordered_set out; + + while (!reader.IsEOF()) { + TINT_CHECK_RESULT_UNWRAP(stop, bytes::Decode(reader)); + if (stop) { + break; + } + TINT_CHECK_RESULT_UNWRAP(val, bytes::Decode(reader)); + out.emplace(std::move(val)); + } + + return out; + } +}; + +/// Decoder specialization for std::vector +template +struct Decoder, void> { + /// Decode decodes the vector from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded vector, or an error if the stream is too short. + static Result> Decode(Reader& reader) { + std::vector out; + + while (!reader.IsEOF()) { + TINT_CHECK_RESULT_UNWRAP(stop, bytes::Decode(reader)); + if (stop) { + break; + } + TINT_CHECK_RESULT_UNWRAP(val, bytes::Decode(reader)); + out.emplace_back(std::move(val)); + } + + return out; + } +}; + +/// Decoder specialization for std::optional +template +struct Decoder, void> { + /// Decode decodes the optional from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded optional, or an error if the stream is too short. + static Result> Decode(Reader& reader) { + TINT_CHECK_RESULT_UNWRAP(has_value, bytes::Decode(reader)); + if (!has_value) { + return std::optional{std::nullopt}; + } + TINT_CHECK_RESULT_UNWRAP(value, bytes::Decode(reader)); + return std::optional{value}; + } +}; + +/// Decoder specialization for std::bitset +template +struct Decoder, void> { + /// Decode decodes the bitset from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded bitset, or an error if the stream is too short. + static Result> Decode(Reader& reader) { + Vector vec; + vec.Resize((N + CHAR_BIT - 1) / CHAR_BIT); + + if (auto len = reader.Read(&vec[0], vec.Length()); len != vec.Length()) { + return Failure{"EOF"}; + } + + std::bitset out; + for (std::size_t i = 0; i < N; i++) { + std::size_t w = i / CHAR_BIT; + std::size_t b = i - (w * CHAR_BIT); + out[i] = ((vec[w] >> b) & std::byte{1}) != std::byte{0}; + } + return out; + } +}; + +/// Decoder specialization for std::tuple +template +struct Decoder, void> { + /// Decode decodes the tuple from @p reader. + /// @param reader the reader to decode from + /// @returns the decoded tuple, or an error if the stream is too short. + static Result> Decode(Reader& reader) { + TINT_CHECK_RESULT_UNWRAP(first, bytes::Decode(reader)); + if constexpr (sizeof...(OTHERS) > 0) { + TINT_CHECK_RESULT_UNWRAP(others, bytes::Decode>(reader)); + return std::tuple_cat(std::tuple(first), others); + } else { + return std::tuple(first); + } + } +}; + +/// Decoder specialization for enum types that have a range defined with TINT_REFLECT_ENUM_RANGE +template +struct Decoder::kMax)>> { + /// Decode decodes the enum type from @p reader. + /// @param reader the reader to decode from + /// @param endianness the endianness of the enum + /// @returns the decoded enum type, or an error if the stream is too short. + static Result Decode(Reader& reader, Endianness endianness = Endianness::kLittle) { + using Range = tint::EnumRange; + using U = std::underlying_type_t; + TINT_CHECK_RESULT_UNWRAP(value, reader.Int(endianness)); + static constexpr U kMin = static_cast(Range::kMin); + static constexpr U kMax = static_cast(Range::kMax); + if (value < kMin || value > kMax) { + return Failure{"value " + std::to_string(value) + " out of range for enum"}; + } + return static_cast(value); + } +}; + +} // namespace tint::bytes + +#endif // SRC_TINT_UTILS_BYTES_DECODER_H_ diff --git a/3rdparty/dawn/src/tint/utils/bytes/endianness.h b/3rdparty/dawn/src/tint/utils/bytes/endianness.h new file mode 100644 index 000000000..9eeacbf5f --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/endianness.h @@ -0,0 +1,52 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#ifndef SRC_TINT_UTILS_BYTES_ENDIANNESS_H_ +#define SRC_TINT_UTILS_BYTES_ENDIANNESS_H_ + +#include +#include + +namespace tint::bytes { + +enum class Endianness : uint8_t { kBig, kLittle }; + +inline Endianness NativeEndianness() { + uint8_t u8[4]; + uint32_t u32 = 0x01020304; + memcpy(u8, &u32, 4); + return u8[0] == 1 ? Endianness::kBig : Endianness::kLittle; +} + +} // namespace tint::bytes + +#endif // SRC_TINT_UTILS_BYTES_ENDIANNESS_H_ diff --git a/3rdparty/dawn/src/tint/utils/bytes/reader.cc b/3rdparty/dawn/src/tint/utils/bytes/reader.cc new file mode 100644 index 000000000..e12a0200a --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/reader.cc @@ -0,0 +1,34 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/bytes/reader.h" + +namespace tint::bytes { + +Reader::~Reader() = default; + +} // namespace tint::bytes diff --git a/3rdparty/dawn/src/tint/utils/bytes/reader.h b/3rdparty/dawn/src/tint/utils/bytes/reader.h new file mode 100644 index 000000000..40a279f28 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/reader.h @@ -0,0 +1,116 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_BYTES_READER_H_ +#define SRC_TINT_UTILS_BYTES_READER_H_ + +#include + +#include "src/tint/utils/bytes/endianness.h" +#include "src/tint/utils/bytes/swap.h" +#include "src/tint/utils/result.h" + +namespace tint::bytes { + +/// A binary stream reader interface +class Reader { + public: + /// Destructor + virtual ~Reader(); + + /// Read reads bytes from the stream, blocking until there are @p count bytes available, or the + /// end of the stream has been reached. + /// @param out a pointer to the byte buffer that will be filled with the read data. Must be at + /// least @p count size. + /// @param count the number of bytes to read. Must be greater than 0. + /// @returns the number of bytes read from the stream. If Read() returns less than @p count, + /// then the end of the stream has been reached. + virtual size_t Read(std::byte* out, size_t count) = 0; + + /// @returns true if the Reader has no more bytes to read. + virtual bool IsEOF() const = 0; + + /// Reads an integer from the stream, performing byte swapping if the stream's endianness + /// differs from the native endianness. + /// If there are too few bytes remaining in the stream, then a failure is returned. + /// @param endianness the encoded endianness of the integer + /// @return the deserialized integer + template + Result Int(Endianness endianness = Endianness::kLittle) { + static_assert(std::is_integral_v); + T out = 0; + if (size_t n = Read(reinterpret_cast(&out), sizeof(T)); n != sizeof(T)) { + return Failure{"EOF"}; + } + if (NativeEndianness() != endianness) { + out = Swap(out); + } + return out; + } + + /// Reads a float from the stream. + /// If there are too few bytes remaining in the stream, then a failure is returned. + /// @return the deserialized floating point number + template + Result Float() { + static_assert(std::is_floating_point_v); + T out = 0; + if (size_t n = Read(reinterpret_cast(&out), sizeof(T)); n != sizeof(T)) { + return Failure{"EOF"}; + } + return out; + } + + /// Reads a boolean from the stream + /// If there are too few bytes remaining in the stream, then a failure is returned. + /// @returns true if the next byte is non-zero + Result Bool() { + std::byte b{0}; + if (size_t n = Read(&b, 1); n != 1) { + return Failure{"EOF"}; + } + return b != std::byte{0}; + } + + /// Reads a string of @p len bytes from the stream. + /// If there are too few bytes remaining in the stream, then a failure is returned. + /// @param len the length of the returned string in bytes + /// @return the deserialized string + Result String(size_t len) { + std::string out; + out.resize(len); + if (size_t n = Read(reinterpret_cast(out.data()), sizeof(char) * len); + n != len) { + return Failure{"EOF"}; + } + return out; + } +}; + +} // namespace tint::bytes + +#endif // SRC_TINT_UTILS_BYTES_READER_H_ diff --git a/3rdparty/dawn/src/tint/utils/bytes/swap.h b/3rdparty/dawn/src/tint/utils/bytes/swap.h new file mode 100644 index 000000000..dcabecfe8 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/bytes/swap.h @@ -0,0 +1,64 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_BYTES_SWAP_H_ +#define SRC_TINT_UTILS_BYTES_SWAP_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/macros/compiler.h" + + +namespace tint::bytes { + +/// @returns the input value with all bytes reversed +/// @param value the input value, can be any type that passes std::is_integral +/// (this includes non-obvious types like wchar_t) +/// TODO(394825124): Once ranges from C++20 is available this code can be +/// rewritten to avoid needing to disable warnings. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +template +[[nodiscard]] inline T Swap(T value) { + static_assert(std::is_integral_v); + uint8_t bytes[sizeof(T)]; + memcpy(bytes, &value, sizeof(T)); + for (size_t i = 0; i < sizeof(T) / 2; i++) { + std::swap(bytes[i], bytes[sizeof(T) - i - 1]); + } + T out; + memcpy(&out, bytes, sizeof(T)); + return out; +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +} // namespace tint::bytes + + +#endif // SRC_TINT_UTILS_BYTES_SWAP_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/bitset.h b/3rdparty/dawn/src/tint/utils/containers/bitset.h new file mode 100644 index 000000000..a53622ebd --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/bitset.h @@ -0,0 +1,134 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_BITSET_H_ +#define SRC_TINT_UTILS_CONTAINERS_BITSET_H_ + +#include + +#include "src/tint/utils/containers/vector.h" + +namespace tint { + +/// Bitset is a dynamically sized, vector of bits, packed into integer words. +/// Bits can be individually read and written using the index operator. +/// +/// Bitset will fit at least `N` bits internally before spilling to heap allocations. +template +class Bitset { + /// The integer word type used to hold the bits + using Word = size_t; + /// Number of bits per word + static constexpr size_t kWordBits = sizeof(Word) * 8; + + /// Number of words required to hold the number of bits + static constexpr size_t NumWords(size_t num_bits) { + return ((num_bits + kWordBits - 1) / kWordBits); + } + + public: + /// Constructor + Bitset() = default; + + /// Destructor + ~Bitset() = default; + + /// Accessor for a single bit + struct Bit { + /// The word that contains the bit + Word& word; + /// A word with a single bit set, which masks the targetted bit + Word const mask; + + /// Assignment operator + /// @param value the new value for the bit + /// @returns this Bit so calls can be chained + const Bit& operator=(bool value) const { + if (value) { + word = word | mask; + } else { + word = word & ~mask; + } + return *this; + } + + /// Conversion operator + /// @returns the bit value + operator bool() const { return (word & mask) != 0; } + }; + + /// @param new_len the new size of the bitmap, in bits. + void Resize(size_t new_len) { + vec_.Resize(NumWords(new_len)); + + // Clear any potentially set bits that are in the top part of the word + if (size_t high_bit = new_len % kWordBits; high_bit > 0) { + vec_.Back() &= (static_cast(1) << high_bit) - 1; + } + + len_ = new_len; + } + + /// @return the number of bits in the bitset. + size_t Length() const { return len_; } + + /// Index operator + /// @param index the index of the bit to access + /// @return the accessor for the indexed bit + Bit operator[](size_t index) { + auto& word = vec_[index / kWordBits]; + auto mask = static_cast(1) << (index % kWordBits); + return Bit{word, mask}; + } + + /// Const index operator + /// @param index the index of the bit to access + /// @return bool value of the indexed bit + bool operator[](size_t index) const { + const auto& word = vec_[index / kWordBits]; + auto mask = static_cast(1) << (index % kWordBits); + return word & mask; + } + + /// @returns true iff the all bits are unset (0) + bool AllBitsZero() const { + for (auto word : vec_) { + if (word) { + return false; + } + } + return true; + } + + private: + Vector vec_; + size_t len_ = 0; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_BITSET_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/containers.cc b/3rdparty/dawn/src/tint/utils/containers/containers.cc new file mode 100644 index 000000000..750c95296 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/containers.cc @@ -0,0 +1,33 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +// A placeholder symbol used to emit a symbol for this lib target. +int tint_utils_containers_symbol = 1; diff --git a/3rdparty/dawn/src/tint/utils/containers/enum_set.h b/3rdparty/dawn/src/tint/utils/containers/enum_set.h new file mode 100644 index 000000000..54443b862 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/enum_set.h @@ -0,0 +1,276 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_ENUM_SET_H_ +#define SRC_TINT_UTILS_CONTAINERS_ENUM_SET_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint { + +/// EnumSet is a set of enum values. +/// @note As the EnumSet is backed by a single uint64_t value, it can only hold +/// enum values in the range [0 .. 63]. +template +struct EnumSet { + public: + /// Enum is the enum type this EnumSet wraps + using Enum = ENUM; + + /// Constructor. Initializes the EnumSet with zero. + constexpr EnumSet() = default; + + /// Copy constructor. + /// @param s the EnumSet to copy + constexpr EnumSet(const EnumSet& s) = default; + + /// Constructor. Initializes the EnumSet with the given values. + /// @param values the enumerator values to construct the EnumSet with + template + explicit constexpr EnumSet(VALUES... values) : set(Union(values...)) {} + + /// Copy assignment operator. + /// @param set the EnumSet to assign to this set + /// @returns this EnumSet so calls can be chained + inline EnumSet& operator=(const EnumSet& set) = default; + + /// Copy assignment operator. + /// @param e the enum value + /// @returns this EnumSet so calls can be chained + inline EnumSet& operator=(Enum e) { return *this = EnumSet{e}; } + + /// Adds all the given values to this set + /// @param values the values to add + /// @returns this EnumSet so calls can be chained + template + inline EnumSet& Add(VALUES... values) { + return Add(EnumSet(std::forward(values)...)); + } + + /// Removes all the given values from this set + /// @param values the values to remove + /// @returns this EnumSet so calls can be chained + template + inline EnumSet& Remove(VALUES... values) { + return Remove(EnumSet(std::forward(values)...)); + } + + /// Adds all of @p s to this set + /// @param s the enum value + /// @returns this EnumSet so calls can be chained + inline EnumSet& Add(EnumSet s) { return (*this = *this + s); } + + /// Removes all of @p s from this set + /// @param s the enum value + /// @returns this EnumSet so calls can be chained + inline EnumSet& Remove(EnumSet s) { return (*this = *this - s); } + + /// Adds or removes @p e to the set + /// @param e the enum value + /// @param add if true the enum value is added, otherwise removed + /// @returns this EnumSet so calls can be chained + inline EnumSet& Set(Enum e, bool add = true) { return add ? Add(e) : Remove(e); } + + /// @param e the enum value + /// @returns a copy of this EnumSet with @p e added + inline EnumSet operator+(Enum e) const { + EnumSet out; + out.set = set | Bit(e); + return out; + } + + /// @param e the enum value + /// @returns a copy of this EnumSet with @p e removed + inline EnumSet operator-(Enum e) const { + EnumSet out; + out.set = set & ~Bit(e); + return out; + } + + /// @param s the other set + /// @returns the union of this EnumSet with @p s (`this` ∪ @p s) + inline EnumSet operator+(EnumSet s) const { + EnumSet out; + out.set = set | s.set; + return out; + } + + /// @param s the other set + /// @returns the set of entries found in this but not in s (`this` \ @p s) + inline EnumSet operator-(EnumSet s) const { + EnumSet out; + out.set = set & ~s.set; + return out; + } + + /// @param s the other set + /// @returns the intersection of this EnumSet with s (`this` ∩ @p s) + inline EnumSet operator&(EnumSet s) const { + EnumSet out; + out.set = set & s.set; + return out; + } + + /// @param e the enum value + /// @return true if the set contains @p e + inline bool Contains(Enum e) const { return (set & Bit(e)) != 0; } + + /// @return true if the set is empty + inline bool Empty() const { return set == 0; } + + /// @returns number of enums currently in the set + /// This is an O(N) operation, where N can be upto 64 + inline size_t Size() const { + size_t result = 0; + uint64_t bits = set; + while (bits) { + result += bits & 1; + bits >>= 1; + } + return result; + } + + /// @return the hash value of this object + tint::HashCode HashCode() const { return Hash(Value()); } + + /// Equality operator + /// @param rhs the other EnumSet to compare this to + /// @return true if this EnumSet is equal to @p rhs + inline bool operator==(EnumSet rhs) const { return set == rhs.set; } + + /// Inequality operator + /// @param rhs the other EnumSet to compare this to + /// @return true if this EnumSet is not equal to @p rhs + inline bool operator!=(EnumSet rhs) const { return set != rhs.set; } + + /// Equality operator + /// @param rhs the enum to compare this to + /// @return true if this EnumSet only contains @p rhs + inline bool operator==(Enum rhs) const { return set == Bit(rhs); } + + /// Inequality operator + /// @param rhs the enum to compare this to + /// @return false if this EnumSet only contains @p rhs + inline bool operator!=(Enum rhs) const { return set != Bit(rhs); } + + /// @return the underlying value for the EnumSet + inline uint64_t Value() const { return set; } + + /// Iterator provides read-only, unidirectional iterator over the enums of an + /// EnumSet. + class Iterator { + static constexpr int8_t kEnd = 63; + + Iterator(uint64_t s, int8_t b) : set(s), pos(b) {} + + /// Make the constructor accessible to the EnumSet. + friend struct EnumSet; + + public: + /// @return the Enum value at this point in the iterator + Enum operator*() const { return static_cast(pos); } + + /// Increments the iterator + /// @returns this iterator + Iterator& operator++() { + while (pos < kEnd) { + pos++; + if (set & (static_cast(1) << static_cast(pos))) { + break; + } + } + return *this; + } + + /// Equality operator + /// @param rhs the Iterator to compare this to + /// @return true if the two iterators are equal + bool operator==(const Iterator& rhs) const { return set == rhs.set && pos == rhs.pos; } + + /// Inequality operator + /// @param rhs the Iterator to compare this to + /// @return true if the two iterators are different + bool operator!=(const Iterator& rhs) const { return !(*this == rhs); } + + private: + const uint64_t set; + int8_t pos; + }; + + /// @returns an read-only iterator to the beginning of the set + Iterator begin() const { + auto it = Iterator{set, -1}; + ++it; // Move to first set bit + return it; + } + + /// @returns an iterator to the beginning of the set + Iterator end() const { return Iterator{set, Iterator::kEnd}; } + + private: + static constexpr uint64_t Bit(Enum value) { + return static_cast(1) << static_cast(value); + } + + static constexpr uint64_t Union() { return 0; } + + template + static constexpr uint64_t Union(FIRST first, VALUES... values) { + return Bit(first) | Union(values...); + } + + uint64_t set = 0; +}; + +/// Writes the EnumSet to the stream. +/// @param out the stream to write to +/// @param set the EnumSet to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, EnumSet set) { + out << "{"; + bool first = true; + for (auto e : set) { + if (!first) { + out << ", "; + } + first = false; + out << e; + } + return out << "}"; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_ENUM_SET_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/filtered_iterator.h b/3rdparty/dawn/src/tint/utils/containers/filtered_iterator.h new file mode 100644 index 000000000..b12064332 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/filtered_iterator.h @@ -0,0 +1,135 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_FILTERED_ITERATOR_H_ +#define SRC_TINT_UTILS_CONTAINERS_FILTERED_ITERATOR_H_ + +#include + +namespace tint { + +/// FilteredIterator is an iterator that skip over elements where the predicate function returns +/// false. +/// @tparam PREDICATE the filter predicate function +/// @tparam ITERATOR the inner iterator type +template +class FilteredIterator { + public: + /// @param current the current iterator. + /// @param end the end iterator. + FilteredIterator(ITERATOR current, ITERATOR end) : current_(current), end_(end) { + // Skip to first element that passes the predicate + while (current_ != end && !PREDICATE{}(*current_)) { + ++current_; + } + } + + /// Copy constructor + FilteredIterator(const FilteredIterator&) = default; + + /// Copy assignment operator + FilteredIterator& operator=(const FilteredIterator&) = default; + + /// Move constructor + FilteredIterator(FilteredIterator&&) = default; + + /// Move assignment operator + FilteredIterator& operator=(FilteredIterator&&) = default; + + /// Increments the iterator until PREDICATE returns true, or the end is reached. + /// @return this FilteredIterator + FilteredIterator& operator++() { + ++current_; + while (current_ != end_ && !PREDICATE{}(*current_)) { + ++current_; + } + return *this; + } + + /// @returns the element at the current iterator + auto operator*() const { return *current_; } + + /// @returns the element at the current iterator + auto operator->() const { return current_.operator->(); } + + /// Equality operator + /// @returns true if this iterator is equal to @p other + bool operator==(const FilteredIterator& other) const { return current_ == other.current_; } + + /// Inequality operator + /// @returns true if this iterator is not equal to @p other + bool operator!=(const FilteredIterator& other) const { return current_ != other.current_; } + + private: + /// The current iterator. + ITERATOR current_; + /// The end iterator. + ITERATOR end_; +}; + +/// FilteredIterable is a wrapper around an object with begin() / end() methods, that returns +/// iterators that skip over elements where the predicate function returns false. +/// @tparam PREDICATE the filter predicate function +/// @tparam ITERABLE the inner iterable object type +template +struct FilteredIterable { + /// The iterator type + using iterator = typename std::decay_t::iterator; + /// The const iterator type + using const_iterator = typename std::decay_t::const_iterator; + + /// The wrapped iterable object. + ITERABLE iterable; + + /// @return the filtered start iterator + FilteredIterator begin() { return {iterable.begin(), iterable.end()}; } + + /// @return the filtered end iterator + FilteredIterator end() { return {iterable.end(), iterable.end()}; } + + /// @return the filtered const start iterator + FilteredIterator begin() const { + return {iterable.begin(), iterable.end()}; + } + + /// @return the filtered const end iterator + FilteredIterator end() const { + return {iterable.end(), iterable.end()}; + } +}; + +/// @returns a FilteredIterable from the filter function `PREDICATE`, wrapping @p iterable +/// @tparam PREDICATE the filter predicate function +/// @tparam ITERABLE the inner iterable object type +template +FilteredIterable Filter(ITERABLE& iterable) { + return {iterable}; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_FILTERED_ITERATOR_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/hashmap.h b/3rdparty/dawn/src/tint/utils/containers/hashmap.h new file mode 100644 index 000000000..14c449277 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/hashmap.h @@ -0,0 +1,365 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_HASHMAP_H_ +#define SRC_TINT_UTILS_CONTAINERS_HASHMAP_H_ + +#include +#include +#include + +#include "src/tint/utils/containers/hashmap_base.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" + +namespace tint { + +/// HashmapEntry is a key-value pair used by Hashmap as the Entry datatype. +template +struct HashmapEntry { + /// The key type + using Key = KEY; + /// The value type + using Value = VALUE; + + /// @param entry a HashmapEntry + /// @return `entry.key` + static const Key& KeyOf(const HashmapEntry& entry) { return entry.key; } + + /// The key + Key key; + + /// The value + Value value; +}; + +/// Equality operator for HashmapEntry +/// @param lhs the LHS HashmapEntry +/// @param rhs the RHS HashmapEntry +/// @return true if both entries have equal keys and values. +template +inline static bool operator==(const HashmapEntry& lhs, const HashmapEntry& rhs) { + return lhs.key == rhs.key && lhs.value == rhs.value; +} + +/// Writes the HashmapEntry to the stream. +/// @param out the stream to write to +/// @param key_value the HashmapEntry to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const HashmapEntry& key_value) { + return out << "[" << key_value.key << ": " << key_value.value << "]"; +} + +/// The return value of Hashmap::Get(Key). +/// GetResult supports equality operators and acts similarly to std::optional, but does not make a +/// copy. +template +struct GetResult { + /// The value found in the map, or null if the entry was not found. + /// This pointer is guaranteed to be valid until the owning entry is removed, the map is + /// cleared, or the map is destructed. + T* value = nullptr; + + /// @returns `true` if #value is not null. + explicit operator bool() const { return value; } + + /// @returns the dereferenced value, which must not be null. + T& operator*() const { return *value; } + + /// @returns the pointer to the value, which must not be null. + T* operator->() const { return value; } + + /// @param other the value to compare against the object that #value points to. + /// @returns true if #value is not null and the object that #value points to is equal to @p + /// other. + template + bool operator==(const O& other) const { + return value && *value == other; + } + + /// @param other the value to compare against the object that #value points to. + /// @returns true if #value is null or the object that #value points to is not equal to @p + /// other. + template + bool operator!=(const O& other) const { + return !value || *value != other; + } +}; + +/// The return value of Hashmap::Add(Key, Value) +template +struct AddResult { + /// A reference to the value of the entry with the given key. + /// If an existing entry was found with the key, then this is the value of the existing entry, + /// otherwise the value of the newly inserted entry. + /// This reference is guaranteed to be valid until the owning entry is removed, the map is + /// cleared, or the map is destructed. + T& value; + + /// True if an entry did not already exist in the map with the given key. + bool added = false; + + /// @returns #added + explicit operator bool() const { return added; } +}; + +/// An unordered hashmap, with a fixed-size capacity that avoids heap allocations. +template , + typename EQUAL = EqualTo> +class Hashmap : public HashmapBase, VALUE>, N> { + using Base = HashmapBase, VALUE>, N>; + + public: + /// The key type + using Key = typename Base::Key; + /// The value type + using Value = VALUE; + /// The key-value type for a map entry + using Entry = HashmapEntry; + + /// Add attempts to insert a new entry into the map. + /// If an existing entry exists with the given key, then the entry is not replaced. + /// @param key the new entry's key + /// @param value the new entry's value + /// @return an AddResult. + template + AddResult Add(K&& key, V&& value) { + if (auto idx = this->EditAt(key); idx.entry) { + return {idx.entry->value, /* added */ false}; + } else { + idx.Insert(std::forward(key), std::forward(value)); + return {idx.entry->value, /* added */ true}; + } + } + + /// Inserts a new entry into the map or updates an existing entry. + /// @param key the new entry's key + /// @param value the new entry's value + template + void Replace(K&& key, V&& value) { + if (auto idx = this->EditAt(key); idx.entry) { + idx.Replace(std::forward(key), std::forward(value)); + } else { + idx.Insert(std::forward(key), std::forward(value)); + } + } + + /// Looks up an entry with the given key. + /// @param key the entry's key to search for. + /// @returns a GetResult holding the found entry's value, or null if the entry was not found. + template + GetResult Get(K&& key) { + if (auto* entry = this->GetEntry(key)) { + return {&entry->value}; + } + return {nullptr}; + } + + /// Looks up an entry with the given key. + /// @param key the entry's key to search for. + /// @returns a GetResult holding the found entry's value, or null if the entry was not found. + template + GetResult Get(K&& key) const { + if (auto* entry = this->GetEntry(key)) { + return {&entry->value}; + } + return {nullptr}; + } + + /// Searches for an entry with the given key value returning that value if found, otherwise + /// returns @p not_found. + /// @param key the entry's key value to search for. + /// @param not_found the value to return if a node is not found. + /// @returns the a reference to the value of the entry, if found otherwise @p not_found. + /// @note The returned reference is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + const Value& GetOr(K&& key, const Value& not_found) const { + if (auto* entry = this->GetEntry(key)) { + return entry->value; + } + return not_found; + } + + /// Searches for an entry with the given key, returning a reference to that entry if found, + /// otherwise a reference to a newly added entry with the key @p key and the value from calling + /// @p create. + /// @note: Before calling `create`, the map will insert a zero-initialized value for the given + /// key, which will be replaced with the value returned by @p create. If @p create adds an entry + /// with @p key to this map, it will be replaced. + /// @param key the entry's key value to search for. + /// @param create the create function to call if the map does not contain the key. Must have the + /// signature `Key()`. + /// @returns a reference to the existing entry, or the newly added entry. + /// @note The returned reference is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + Entry& GetOrAddEntry(K&& key, CREATE&& create) { + auto idx = this->EditAt(key); + if (!idx.entry) { + idx.Insert(std::forward(key), Value{}); + idx.entry->value = create(); + } + return *idx.entry; + } + + /// Searches for an entry with the given key, returning a reference to that entry if found, + /// otherwise a reference to a newly added entry with the key @p key and a zero value. + /// @param key the entry's key value to search for. + /// @returns a reference to the existing entry, or the newly added entry. + /// @note The returned reference is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + Entry& GetOrAddZeroEntry(K&& key) { + auto idx = this->EditAt(key); + if (!idx.entry) { + idx.Insert(std::forward(key), Value{}); + } + return *idx.entry; + } + + /// Searches for an entry with the given key, adding and returning the result of calling + /// @p create if the entry was not found. + /// @note: Before calling `create`, the map will insert a zero-initialized value for the given + /// key, which will be replaced with the value returned by @p create. If @p create adds an entry + /// with @p key to this map, it will be replaced. + /// @param key the entry's key value to search for. + /// @param create the create function to call if the map does not contain the key. + /// @returns the value of the entry. + /// @note The returned reference is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + Value& GetOrAdd(K&& key, CREATE&& create) { + return GetOrAddEntry(std::forward(key), std::forward(create)).value; + } + + /// Searches for an entry with the given key value, adding and returning a newly created + /// zero-initialized value if the entry was not found. + /// @param key the entry's key value to search for. + /// @returns the value of the entry. + /// @note The returned reference is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + Value& GetOrAddZero(K&& key) { + return GetOrAddZeroEntry(std::forward(key)).value; + } + + /// @returns the keys of the map as a vector. + /// @note the order of the returned vector is non-deterministic between compilers. + template + Vector Keys() const { + Vector out; + out.Reserve(this->Count()); + for (auto& it : *this) { + out.Push(it.key.Value()); + } + return out; + } + + /// @returns the values of the map as a vector + /// @note the order of the returned vector is non-deterministic between compilers. + template + Vector Values() const { + Vector out; + out.Reserve(this->Count()); + for (auto& it : *this) { + out.Push(it.value); + } + return out; + } + + /// Equality operator + /// @param other the other Hashmap to compare this Hashmap to + /// @returns true if this Hashmap has the same key and value pairs as @p other + template + bool operator==(const Hashmap& other) const { + if (this->Count() != other.Count()) { + return false; + } + for (auto& it : *this) { + auto other_val = other.Get(it.key.Value()); + if (!other_val || it.value != *other_val) { + return false; + } + } + return true; + } + + /// Inequality operator + /// @param other the other Hashmap to compare this Hashmap to + /// @returns false if this Hashmap has the same key and value pairs as @p other + template + bool operator!=(const Hashmap& other) const { + return !(*this == other); + } +}; + +/// Hasher specialization for Hashmap +template +struct Hasher> { + /// @param map the Hashmap to hash + /// @returns a hash of the map + HashCode operator()(const Hashmap& map) const { + auto hash = Hash(map.Count()); + for (auto it : map) { + // Use an XOR to ensure that the non-deterministic ordering of the map still produces + // the same hash value for the same entries. + hash ^= Hash(it.key.Value(), it.value); + } + return hash; + } +}; + +/// Writes the Hashmap to the stream. +/// @param out the stream to write to +/// @param map the Hashmap to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Hashmap& map) { + out << "Hashmap{"; + bool first = true; + for (auto it : map) { + if (!first) { + out << ", "; + } + first = false; + out << it; + } + out << "}"; + return out; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_HASHMAP_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/hashmap_base.h b/3rdparty/dawn/src/tint/utils/containers/hashmap_base.h new file mode 100644 index 000000000..d8d7c23a2 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/hashmap_base.h @@ -0,0 +1,693 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_HASHMAP_BASE_H_ +#define SRC_TINT_UTILS_CONTAINERS_HASHMAP_BASE_H_ + +#include +#include +#include +#include +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/memory/aligned_storage.h" +#include "src/tint/utils/rtti/traits.h" + +// This file implements a custom STL style container & iterator in a performant manner, using +// C-style data access. It is not unexpected that -Wunsafe-buffer-usage triggers in this code, since +// the type of dynamic access being used cannot be guaranteed to be safe via static analysis. +// Attempting to change this code in simple ways to quiet these errors either a) negatively affects +// the performance by introducing unneeded copes, or b) uses typing shenanigans to work around the +// warning that other linters/analyses are unhappy with. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +namespace tint { + +/// HashmapKey wraps the comparator type for a Hashmap and Hashset. +/// HashmapKey acts like a read-only `T`, but can be reassigned so long as the value is equivalent. +/// @tparam T the key comparator type. +/// @tparam HASH the hash function for the key type. +/// @tparam EQUAL the equality function for the key type. +template , typename EQUAL = std::equal_to> +class HashmapKey { + T value_; + + public: + /// Key is an alias to this templated class. + using Key = HashmapKey; + /// Hash is an alias to the hash function for the key type. + using Hash = HASH; + /// Equal is an alias to the equality function for the key type. + using Equal = EQUAL; + + /// KeyOf() returns @p key, so a HashmapKey can be used as the entry type for a Hashset. + /// @param key the HashmapKey + /// @return @p key + static const Key& KeyOf(const Key& key) { return key; } + + /// Constructor using copied value. + /// @param value the key value. + HashmapKey(const T& value) : value_(value), hash(HASH{}(value_)) {} // NOLINT + + /// Constructor using moved value. + /// @param value the key value. + HashmapKey(T&& value) : value_(std::forward(value)), hash(HASH{}(value_)) {} // NOLINT + + /// Constructor using pre-computed hash and copied value. + /// @param hash_ the precomputed hash of @p value + /// @param value the key value + HashmapKey(HashCode hash_, const T& value) : value_(value), hash(hash_) {} + + /// Constructor using pre-computed hash and moved value. + /// @param hash_ the precomputed hash of @p value + /// @param value the key value + HashmapKey(HashCode hash_, T&& value) : value_(std::forward(value)), hash(hash_) {} + + /// Copy constructor + HashmapKey(const HashmapKey&) = default; + + /// Move constructor + HashmapKey(HashmapKey&&) = default; + + /// Destructor + ~HashmapKey() = default; + + /// Copy-assignment operator. + /// @note As a hashmap uses the HashmapKey for indexing, the new value *must* have the same hash + /// value and be equal to this key. + /// @param other the key to copy to this key. + /// @return this HashmapKey. + HashmapKey& operator=(const HashmapKey& other) { + TINT_ASSERT(*this == other); + value_ = other.Value(); + return *this; + } + + /// Move-assignment operator. + /// @note As a hashmap uses the HashmapKey for indexing, the new value *must* have the same hash + /// value and be equal to this key. + /// @param other the key to move to this key. + /// @return this HashmapKey. + HashmapKey& operator=(HashmapKey&& other) { + TINT_ASSERT(*this == other); + value_ = std::move(other.Value()); + return *this; + } + + /// Equality operator + /// @param other the other key. + /// @return true if the hash and value of @p other are equal to this key. + bool operator==(const HashmapKey& other) const { + return hash == other.hash && EQUAL{}(value_, other.Value()); + } + + /// Equality operator + /// @param other the other key. + /// @return true if the hash of other and value of @p other are equal to this key. + template + bool operator==(const RHS& other) const { + return hash == HASH{}(other) && EQUAL{}(value_, other); + } + + /// @returns the value of the key + const T& Value() const { return value_; } + + /// @returns the value of the key + operator const T&() const { return value_; } + + /// @returns the pointer to the value, or the value itself if T is a pointer. + auto operator->() const { + if constexpr (std::is_pointer_v) { + // operator-> is useless if the T is a pointer, so automatically unwrap a pointer. + return value_; + } else { + return &value_; + } + } + + /// The hash of value + const HashCode hash; +}; + +/// Writes the HashmapKey to the stream. +/// @param out the stream to write to +/// @param key the HashmapKey to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const HashmapKey& key) { + if constexpr (traits::HasOperatorShiftLeft) { + return out << key.Value(); + } else { + return out << ""; + } +} + +/// HashmapBase is the base class for Hashmap and Hashset. +/// @tparam ENTRY is the single record in the map. The entry type must alias 'Key' to the HashmapKey +/// type, and implement the method `static HashmapKey<...> KeyOf(ENTRY)` to return the key for the +/// entry. +template +class HashmapBase { + protected: + struct Node; + struct Slot; + + public: + /// Entry is the type of a single record in the hashmap. + using Entry = ENTRY; + /// Key is the HashmapKey type used to find entries. + using Key = typename Entry::Key; + /// Hash is the + using Hash = typename Key::Hash; + /// Equal is the + using Equal = typename Key::Equal; + + /// The minimum capacity of the map. + static constexpr size_t kMinCapacity = std::max(N, 8); + + /// The target number of slots, expressed as a fractional percentage of the map capacity. + /// e.g. a kLoadFactor of 75, would mean a target slots count of (0.75 * capacity). + static constexpr size_t kLoadFactor = 75; + + /// @param capacity the capacity of the map, as total number of entries. + /// @returns the target slot vector size to hold @p capacity map entries. + static constexpr size_t NumSlots(size_t capacity) { + return (std::max(capacity, kMinCapacity) * kLoadFactor) / 100; + } + + /// Constructor. + /// Constructs an empty map. + HashmapBase() { + slots_.Resize(slots_.Capacity()); + for (auto& node : fixed_) { + free_.Add(&node); + } + } + + /// Copy constructor. + /// Constructs a map with a copy of @p other. + /// @param other the map to copy. + HashmapBase(const HashmapBase& other) : HashmapBase() { + if (&other != this) { + Copy(other); + } + } + + /// Move constructor. + /// Constructs a map with the moved entries of @p other. + /// @param other the map to move. + HashmapBase(HashmapBase&& other) : HashmapBase() { + if (&other != this) { + Move(std::move(other)); + } + } + + /// Destructor. + ~HashmapBase() { + // Call the destructor on all entries in the map. + for (size_t slot_idx = 0; slot_idx < slots_.Length(); slot_idx++) { + auto* node = slots_[slot_idx].nodes; + while (node) { + auto next = node->next; + node->Destroy(); + node = next; + } + } + } + + /// Assignment operator. + /// Clears this map, and populates this map with a copy of @p other. + /// @param other the map to copy. + /// @returns this HashmapBase + HashmapBase& operator=(const HashmapBase& other) { + if (&other != this) { + Clear(); + Copy(other); + } + return *this; + } + + /// Move-assignment operator. + /// Clears this map, and populates this map with the moved entries of @p other. + /// @param other the map to move. + /// @returns this HashmapBase + HashmapBase& operator=(HashmapBase&& other) { + if (&other != this) { + Clear(); + Move(std::move(other)); + } + return *this; + } + + /// @returns the number of entries in the map. + size_t Count() const { return count_; } + + /// @returns true if the map holds no entries. + bool IsEmpty() const { return count_ == 0; } + + /// Removes all the entries from the map. + /// @note the map's capacity is not reduced, as it is assumed that a reused map will likely fill + /// to a similar size as before. + void Clear() { + for (size_t slot_idx = 0; slot_idx < slots_.Length(); slot_idx++) { + auto* node = slots_[slot_idx].nodes; + while (node) { + auto next = node->next; + node->Destroy(); + free_.Add(node); + node = next; + } + slots_[slot_idx].nodes = nullptr; + } + count_ = 0; + } + + /// Ensures that the map can hold @p n entries without heap reallocation or rehashing. + /// @param n the number of entries to ensure can fit in the map without reallocation or + /// rehashing. + void Reserve(size_t n) { + if (n > capacity_) { + size_t count = n - capacity_; + free_.Allocate(count); + capacity_ += count; + } + } + + /// Looks up an entry with the given key. + /// @param key the entry's key to search for. + /// @returns a pointer to the matching entry, or null if no entry was found. + /// @note The returned pointer is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + Entry* GetEntry(K&& key) { + HashCode hash = Hash{}(key); + auto& slot = slots_[hash % slots_.Length()]; + return slot.Find(hash, key); + } + + /// Looks up an entry with the given key. + /// @param key the entry's key to search for. + /// @returns a pointer to the matching entry, or null if no entry was found. + /// @note The returned pointer is guaranteed to be valid until the owning entry is removed, + /// the map is cleared, or the map is destructed. + template + const Entry* GetEntry(K&& key) const { + HashCode hash = Hash{}(key); + auto& slot = slots_[hash % slots_.Length()]; + return slot.Find(hash, key); + } + + /// @returns true if the map contains an entry with a key that matches @p key. + /// @param key the key to look for. + template + bool Contains(K&& key) const { + return GetEntry(key) != nullptr; + } + + /// Removes an entry from the map that has a key which matches @p key. + /// @returns true if the entry was found and removed, otherwise false. + /// @param key the key to look for. + template + bool Remove(K&& key) { + HashCode hash = Hash{}(key); + auto& slot = slots_[hash % slots_.Length()]; + Node** edge = &slot.nodes; + for (auto* node = *edge; node; node = node->next) { + if (node->Equals(hash, key)) { + *edge = node->next; + node->Destroy(); + free_.Add(node); + count_--; + return true; + } + edge = &node->next; + } + return false; + } + + /// Iterator for entries in the map. + template + class IteratorT { + private: + using MAP = std::conditional_t; + using NODE = std::conditional_t; + + public: + /// @returns the entry pointed to by this iterator + auto& operator->() { return node_->Entry(); } + + /// @returns a reference to the entry at the iterator + auto& operator*() { return node_->Entry(); } + + /// Increments the iterator + /// @returns this iterator + IteratorT& operator++() { + node_ = node_->next; + SkipEmptySlots(); + return *this; + } + + /// Equality operator + /// @param other the other iterator to compare this iterator to + /// @returns true if this iterator is equal to other + bool operator==(const IteratorT& other) const { return node_ == other.node_; } + + /// Inequality operator + /// @param other the other iterator to compare this iterator to + /// @returns true if this iterator is not equal to other + bool operator!=(const IteratorT& other) const { return node_ != other.node_; } + + private: + /// Friend class + friend class HashmapBase; + + IteratorT(MAP& map, size_t slot, NODE* node) : map_(map), slot_(slot), node_(node) { + SkipEmptySlots(); + } + + void SkipEmptySlots() { + while (!node_ && slot_ + 1 < map_.slots_.Length()) { + node_ = map_.slots_[++slot_].nodes; + } + } + + MAP& map_; + size_t slot_ = 0; + NODE* node_ = nullptr; + }; + + /// An immutable key and mutable value iterator + using Iterator = IteratorT; + + /// An immutable key and value iterator + using ConstIterator = IteratorT; + + /// @returns an immutable iterator to the start of the map. + ConstIterator begin() const { return ConstIterator{*this, 0, slots_.Front().nodes}; } + + /// @returns an immutable iterator to the end of the map. + ConstIterator end() const { return ConstIterator{*this, slots_.Length(), nullptr}; } + + /// @returns an iterator to the start of the map. + Iterator begin() { return Iterator{*this, 0, slots_.Front().nodes}; } + + /// @returns an iterator to the end of the map. + Iterator end() { return Iterator{*this, slots_.Length(), nullptr}; } + + /// STL-friendly alias to Entry. Used by gmock. + using value_type = const Entry&; + + protected: + /// Node holds an Entry in a linked list. + struct Node { + /// Destructs the entry. + void Destroy() { Entry().~ENTRY(); } + + /// @returns the storage reinterpreted as an `Entry&` + ENTRY& Entry() { return storage.Get(); } + + /// @returns the storage reinterpreted as a `const Entry&` + const ENTRY& Entry() const { return storage.Get(); } + + /// @returns a reference to the Entry's HashmapKey + const HashmapBase::Key& Key() const { return HashmapBase::Entry::KeyOf(Entry()); } + + /// @param hash the hash value to compare against the Entry's key hash value + /// @param value the value to compare against the Entry's key + /// @returns true if the Entry's hash is equal to @p hash, and the Entry's key is equal to + /// @p value. + template + bool Equals(HashCode hash, T&& value) const { + auto& key = Key(); + return key.hash == hash && HashmapBase::Equal{}(key.Value(), value); + } + + /// storage is a buffer that has the same size and alignment as Entry. + /// The storage holds a constructed Entry when linked in the slots, and is destructed when + /// removed from slots. + AlignedStorage storage; + + /// next is the next Node in the slot, or in the free list. + Node* next; + }; + + /// Copies the hashmap @p other into this empty hashmap. + /// @note This hashmap must be empty before calling + /// @param other the hashmap to copy + void Copy(const HashmapBase& other) { + Reserve(other.capacity_); + slots_.Resize(other.slots_.Length()); + for (size_t slot_idx = 0; slot_idx < slots_.Length(); slot_idx++) { + for (auto* o = other.slots_[slot_idx].nodes; o; o = o->next) { + auto* node = free_.Take(); + new (&node->Entry()) Entry{o->Entry()}; + slots_[slot_idx].Add(node); + } + } + count_ = other.count_; + } + + /// Moves the hashmap @p other into this empty hashmap. + /// @note This hashmap must be empty before calling + /// @param other the hashmap to move + void Move(HashmapBase&& other) { + Reserve(other.capacity_); + slots_.Resize(other.slots_.Length()); + for (size_t slot_idx = 0; slot_idx < slots_.Length(); slot_idx++) { + for (auto* o = other.slots_[slot_idx].nodes; o; o = o->next) { + auto* node = free_.Take(); + new (&node->Entry()) Entry{std::move(o->Entry())}; + slots_[slot_idx].Add(node); + } + } + count_ = other.count_; + other.Clear(); + } + + /// EditIndex is the structure returned by EditAt(), used to simplify entry replacement and + /// insertion. + struct EditIndex { + /// The HashmapBase that created this EditIndex + HashmapBase& map; + /// The slot that will hold the edit. + Slot& slot; + /// The hash of the key, passed to EditAt(). + HashCode hash; + /// The resolved node entry, or nullptr if EditAt() did not resolve to an existing entry. + Entry* entry = nullptr; + + /// Replace will replace the entry with a new Entry built from @p key and @p values. + /// @note #entry must not be null before calling. + /// @note the new key must have equality to the old key. + /// @param key the key value (inner value of a HashmapKey). + /// @param values optional additional values to pass to the Entry constructor. + template + void Replace(K&& key, V&&... values) { + *entry = Entry{Key{hash, std::forward(key)}, std::forward(values)...}; + } + + /// Insert will create a new entry using @p key and @p values and insert it into the slot. + /// The created entry will be assigned to #entry before returning. + /// @note #entry must be null before calling. + /// @note the key must not already exist in the map. + /// @param key the key value (inner value of a HashmapKey). + /// @param values optional additional values to pass to the Entry constructor. + template + void Insert(K&& key, V&&... values) { + auto* node = map.free_.Take(); + slot.Add(node); + map.count_++; + entry = &node->Entry(); + new (entry) Entry{Key{hash, std::forward(key)}, std::forward(values)...}; + } + }; + + /// EditAt is a helper for map entry replacement and entry insertion. + /// Before indexing, EditAt will ensure there's at least one free node available, potentially + /// allocating and rehashing if there's no free nodes available. + /// @param key the key used to compute the hash, look up the slot and search for the existing + /// node. + /// @returns a EditIndex used to modify or insert a new entry into the map with the given key. + template + EditIndex EditAt(K&& key) { + if (!free_.nodes_) { + free_.Allocate(capacity_); + capacity_ += capacity_; + Rehash(); + } + HashCode hash = Hash{}(key); + auto& slot = slots_[hash % slots_.Length()]; + auto* entry = slot.Find(hash, key); + return {*this, slot, hash, entry}; + } + + /// Rehash resizes the slots vector proportionally to the map capacity, and then reinserts the + /// nodes so they're linked in the correct slots linked lists. + void Rehash() { + size_t num_slots = NumSlots(capacity_); + decltype(slots_) old_slots; + std::swap(slots_, old_slots); + slots_.Resize(num_slots); + for (size_t old_slot_idx = 0; old_slot_idx < old_slots.Length(); old_slot_idx++) { + auto* node = old_slots[old_slot_idx].nodes; + while (node) { + auto next = node->next; + size_t new_slot_idx = node->Key().hash % num_slots; + slots_[new_slot_idx].Add(node); + node = next; + } + } + } + + /// Slot holds a linked list of nodes. Nodes are assigned to the slot list by calculating the + /// modulo of the entry's hash with the slot_ vector length. + struct Slot { + /// The linked list of nodes in this slot. + Node* nodes = nullptr; + + /// Add adds the node @p node to this slot. + /// @note The node must be unlinked from any existing list before calling. + /// @param node the node to add. + void Add(Node* node) { + node->next = nodes; + nodes = node; + } + + /// @returns the node in the slot with the given hash and key. + /// @param hash the key hash to search for. + /// @param key the key value to search for. + template + const Entry* Find(HashCode hash, K&& key) const { + for (auto* node = nodes; node; node = node->next) { + if (node->Equals(hash, key)) { + return &node->Entry(); + } + } + return nullptr; + } + + /// @returns the node in the slot with the given hash and key. + /// @param hash the key hash to search for. + /// @param key the key value to search for. + template + Entry* Find(HashCode hash, K&& key) { + for (auto* node = nodes; node; node = node->next) { + if (node->Equals(hash, key)) { + return &node->Entry(); + } + } + return nullptr; + } + }; + + /// Free holds a linked list of nodes which are currently not used by entries in the map, and a + /// linked list of node allocations. + struct FreeNodes { + /// Allocation is the header of a block of memory that holds Nodes. + struct Allocation { + /// The linked list of allocations. + Allocation* next = nullptr; + // Node[] array follows this structure. + }; + + /// The linked list of free nodes. + Node* nodes_ = nullptr; + + /// The linked list of allocations. + Allocation* allocations_ = nullptr; + + /// Destructor. + /// Frees all the allocations made. + ~FreeNodes() { + auto* allocation = allocations_; + while (allocation) { + auto* next = allocation->next; + free(allocation); + allocation = next; + } + } + + /// @returns the next free node in the list + Node* Take() { + auto* node = nodes_; + nodes_ = node->next; + node->next = nullptr; + return node; + } + + /// Add adds the node @p node to the list of free nodes. + /// @note The node must be unlinked from any existing list before calling. + /// @param node the node to add. + void Add(Node* node) { + node->next = nodes_; + nodes_ = node; + } + + /// Allocate allocates an additional @p count nodes and adds them to the free node list. + /// @param count the number of new nodes to allocate. + /// @note callers must remember to increment HashmapBase::capacity_ by the same amount. + void Allocate(size_t count) { + static_assert(std::is_trivial_v, + "Node is not trivial, and will require construction / destruction"); + constexpr size_t kAllocationSize = RoundUp(alignof(Node), sizeof(Allocation)); + auto* memory = + reinterpret_cast(malloc(kAllocationSize + sizeof(Node) * count)); + TINT_ASSERT(memory) << "out of memory"; + auto* nodes_allocation = Bitcast(memory); + nodes_allocation->next = allocations_; + allocations_ = nodes_allocation; + + auto* nodes = Bitcast(memory + kAllocationSize); + for (size_t i = 0; i < count; i++) { + Add(&nodes[i]); + } + } + }; + + /// The fixed-size array of nodes, used for the first kMinCapacity entries of the map, before + /// allocating from the heap. + std::array fixed_; + /// The vector of slots. Each slot holds a linked list of nodes which hold entries in the map. + Vector slots_; + /// The linked list of free nodes, and node allocations from the heap. + FreeNodes free_; + /// The total number of nodes, including free nodes (kMinCapacity + heap-allocated) + size_t capacity_ = kMinCapacity; + /// The total number of nodes that currently hold map entries. + size_t count_ = 0; +}; + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_CONTAINERS_HASHMAP_BASE_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/hashset.h b/3rdparty/dawn/src/tint/utils/containers/hashset.h new file mode 100644 index 000000000..9bdc7efc7 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/hashset.h @@ -0,0 +1,122 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_HASHSET_H_ +#define SRC_TINT_UTILS_CONTAINERS_HASHSET_H_ + +#include +#include +#include +#include +#include +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint { + +/// An unordered hashset, with a fixed-size capacity that avoids heap allocations. +template , typename EQUAL = std::equal_to> +class Hashset : public HashmapBase, N> { + using Base = HashmapBase, N>; + + public: + using Base::Base; + + /// Constructor with initializer list of items + /// @param items the items to place into the set + Hashset(std::initializer_list 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. + template + bool Add(V&& value) { + auto idx = this->EditAt(value); + if (idx.entry) { + return false; // Entry already exists + } + idx.Insert(std::forward(value)); + return true; + } + + /// @returns the set entries of the map as a vector + /// @note the order of the returned vector is non-deterministic between compilers. + template + tint::Vector Vector() const { + tint::Vector out; + out.Reserve(this->Count()); + for (auto& key : *this) { + out.Push(key.Value()); + } + 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 + bool Any(PREDICATE&& pred) const { + for (const auto& key : *this) { + if (pred(key.Value())) { + 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 + bool All(PREDICATE&& pred) const { + for (const auto& key : *this) { + if (!pred(key.Value())) { + return false; + } + } + return true; + } + + /// Looks up an entry in the set that is equal to @p key + /// @param key the key to search for. + /// @returns the entry that is equal to @p key + std::optional Get(const KEY& key) const { + if (auto [found, index] = this->IndexOf(key); found) { + return this->slots_[index].entry; + } + return std::nullopt; + } +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_HASHSET_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/map.h b/3rdparty/dawn/src/tint/utils/containers/map.h new file mode 100644 index 000000000..5de553855 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/map.h @@ -0,0 +1,69 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_MAP_H_ +#define SRC_TINT_UTILS_CONTAINERS_MAP_H_ + +#include + +namespace tint { + +/// Lookup is a utility function for fetching a value from an unordered map if +/// it exists, otherwise returning the `if_missing` argument. +/// @param map the unordered_map +/// @param key the map key of the item to query +/// @param if_missing the value to return if the map does not contain the given +/// key. Defaults to the zero-initializer for the value type. +/// @return the map item value, or `if_missing` if the map does not contain the +/// given key +template +V Lookup(const std::unordered_map& map, const KV& key, const V& if_missing = {}) { + auto it = map.find(key); + return it != map.end() ? it->second : if_missing; +} + +/// GetOrAdd is a utility function for lazily adding to an unordered map. +/// If the map already contains the key `key` then this is returned, otherwise +/// `create()` is called and the result is added to the map and is returned. +/// @param map the unordered_map +/// @param key the map key of the item to query or add +/// @param create a callable function-like object with the signature `V()` +/// @return the value of the item with the given key, or the newly created item +template +V GetOrAdd(std::unordered_map& map, const K& key, CREATE&& create) { + auto it = map.find(key); + if (it != map.end()) { + return it->second; + } + V value = create(); + map.emplace(key, value); + return value; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_MAP_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/predicates.h b/3rdparty/dawn/src/tint/utils/containers/predicates.h new file mode 100644 index 000000000..e042c3ccc --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/predicates.h @@ -0,0 +1,91 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_PREDICATES_H_ +#define SRC_TINT_UTILS_CONTAINERS_PREDICATES_H_ + +namespace tint { + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// equal to +/// @p value +template +auto Eq(const T& value) { + return [value](const T& v) { return v == value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is not +/// equal to @p value +template +auto Ne(const T& value) { + return [value](const T& v) { return v != value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// greater than @p value +template +auto Gt(const T& value) { + return [value](const T& v) { return v > value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// less than +/// @p value +template +auto Lt(const T& value) { + return [value](const T& v) { return v < value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// greater or equal to @p value +template +auto Ge(const T& value) { + return [value](const T& v) { return v >= value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// less than or equal to @p value +template +auto Le(const T& value) { + return [value](const T& v) { return v <= value; }; +} + +/// @param ptr the pointer +/// @return true if the pointer argument is null. +static inline bool IsNull(const void* ptr) { + return ptr == nullptr; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_PREDICATES_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/reverse.h b/3rdparty/dawn/src/tint/utils/containers/reverse.h new file mode 100644 index 000000000..b3f255cc0 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/reverse.h @@ -0,0 +1,77 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_REVERSE_H_ +#define SRC_TINT_UTILS_CONTAINERS_REVERSE_H_ + +#include + +namespace tint { + +namespace detail { +/// Used by tint::Reverse to hold the underlying iterable. +/// begin(ReverseIterable) and end(ReverseIterable) are automatically +/// called for range-for loops, via argument-dependent lookup. +/// See https://en.cppreference.com/w/cpp/language/range-for +template +struct ReverseIterable { + /// The wrapped iterable object. + T& iterable; +}; + +template +auto begin(ReverseIterable r_it) { + return std::rbegin(r_it.iterable); +} + +template +auto end(ReverseIterable r_it) { + return std::rend(r_it.iterable); +} +} // namespace detail + +/// Reverse returns an iterable wrapper that when used in range-for loops, +/// performs a reverse iteration over the object `iterable`. +/// Example: +/// ``` +/// /* Equivalent to: +/// * for (auto it = vec.rbegin(); i != vec.rend(); ++it) { +/// * auto v = *it; +/// */ +/// for (auto v : tint::Reverse(vec)) { +/// } +/// ``` +/// @param iterable the object to iterate +/// @returns the reverse iterable object +template +detail::ReverseIterable Reverse(T&& iterable) { + return {iterable}; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_REVERSE_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/scope_stack.h b/3rdparty/dawn/src/tint/utils/containers/scope_stack.h new file mode 100644 index 000000000..b98b0472a --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/scope_stack.h @@ -0,0 +1,113 @@ +// Copyright 2020 The Dawn & Tint Authors // +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_SCOPE_STACK_H_ +#define SRC_TINT_UTILS_CONTAINERS_SCOPE_STACK_H_ + +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/macros/compiler.h" + +namespace tint { + +/// Used to store a stack of scope information. +/// The stack starts with a global scope which can not be popped. +template +class ScopeStack { + public: + ScopeStack() { Push(); } + + /// Push a new scope on to the stack + void Push() { + depth_++; + if (DAWN_LIKELY(stack_.Length() >= depth_)) { + Top().Clear(); + } else { + stack_.Push({}); + } + } + + /// Pop the scope off the top of the stack + void Pop() { + if (depth_ > 1) { + depth_--; + } + } + + /// Assigns the value into the top most scope of the stack. + /// @param key the key of the value + /// @param val the value + /// @returns the old value if there was an existing key at the top of the + /// stack, otherwise the zero initializer for type T. + V Set(const K& key, V val) { + if (auto el = Top().Get(key)) { + std::swap(val, *el); + return val; + } + Top().Add(key, val); + return {}; + } + + /// Retrieves a value from the stack + /// @param key the key to look for + /// @returns the value, or the zero initializer if the value was not found + V Get(const K& key) const { + for (size_t i = depth_; i > 0; i--) { + if (auto val = stack_[i - 1].Get(key)) { + return *val; + } + } + + return V{}; + } + + /// Return the top scope of the stack. + /// @returns the top scope of the stack + const Hashmap& Top() const { return stack_[depth_ - 1]; } + + /// Return the top scope of the stack. + /// @returns the top scope of the stack + Hashmap& Top() { return stack_[depth_ - 1]; } + + /// Clear the scope stack. + void Clear() { + depth_ = 1; + stack_.Resize(1); + stack_.Front().Clear(); + } + + private: + Vector, 8> stack_; + /// The active count in stack. We don't push and pop the stack to avoid frequent re-allocations + /// of the hashmaps. + size_t depth_ = 0; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_SCOPE_STACK_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/slice.h b/3rdparty/dawn/src/tint/utils/containers/slice.h new file mode 100644 index 000000000..2aad8ced2 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/slice.h @@ -0,0 +1,311 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_SLICE_H_ +#define SRC_TINT_UTILS_CONTAINERS_SLICE_H_ + +#include +#include +#include + +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/memory/bitcast.h" +#include "src/tint/utils/rtti/castable.h" +#include "src/tint/utils/rtti/traits.h" + +// tint::Slice is a memory view into a contiguous range of memory, to allow safer access and avoid +// unneeded copies, similar to std::string_view. +// There are external implementations of this type of container, //base/container/span in Chromium +// and std::span in C++20. Unfortunately Abseil does not implement its own version of this, and Tint +// cannot currently use the other options. +// +// Because this class is fundamentally working with T* values to avoid copying, and using asserts +// for bounds checking, -Wunsafe-buffer-usage will always trigger in here, since the compiler cannot +// guarantee it is safe. +// +// TODO(408010433): Revisit once C++20 is available +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +namespace tint { + +/// A type used to indicate an empty array. +struct EmptyType {}; + +/// An instance of the EmptyType. +static constexpr EmptyType Empty; + +/// Mode enumerator for ReinterpretSlice +enum class ReinterpretMode { + /// Only upcasts of pointers are permitted + kSafe, + /// Potentially unsafe downcasts of pointers are also permitted + kUnsafe, +}; + +namespace detail { + +template +static constexpr bool ConstRemoved = std::is_const_v && !std::is_const_v; + +/// Private implementation of tint::CanReinterpretSlice. +/// Specialized for the case of TO equal to FROM, which is the common case, and avoids inspection of +/// the base classes, which can be troublesome if the slice is of an incomplete type. +template +struct CanReinterpretSlice { + private: + using TO_EL = std::remove_pointer_t>; + using FROM_EL = std::remove_pointer_t>; + + public: + /// @see tint::CanReinterpretSlice + static constexpr bool value = + // const can only be applied, not removed + !ConstRemoved && + + // Both TO and FROM are the same type (ignoring const) + (std::is_same_v, std::remove_const_t> || + + // Both TO and FROM are pointers... + ((std::is_pointer_v && std::is_pointer_v) && + + // const can only be applied to element type, not removed + !ConstRemoved && + + // Either: + // * Both the pointer elements are of the same type (ignoring const) + // * Both the pointer elements are both Castable, and MODE is kUnsafe, or FROM is of, + // or + // derives from TO + (std::is_same_v, std::remove_const_t> || + (IsCastable && + (MODE == ReinterpretMode::kUnsafe || tint::traits::IsTypeOrDerived))))); +}; + +/// Specialization of 'CanReinterpretSlice' for when TO and FROM are equal types. +template +struct CanReinterpretSlice { + /// Always `true` as TO and FROM are the same type. + static constexpr bool value = true; +}; + +} // namespace detail + +/// Evaluates whether a `Slice` and be reinterpreted as a `Slice`. +/// Slices can be reinterpreted if: +/// * TO has the same or more 'constness' than FROM. +/// * And either: +/// * `FROM` and `TO` are pointers to the same type +/// * `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 +static constexpr bool CanReinterpretSlice = + tint::detail::CanReinterpretSlice::value; + +/// A slice represents a contiguous array of elements of type T. +template +struct Slice { + /// Type of `T`. + using value_type = T; + + /// The pointer to the first element in the slice + T* data = nullptr; + + /// The total number of elements in the slice + size_t len = 0; + + /// The total capacity of the backing store for the slice + size_t cap = 0; + + /// Constructor + constexpr Slice() = default; + + /// Constructor + constexpr Slice(EmptyType) {} // NOLINT + + /// Copy constructor with covariance / const conversion + /// @param other the vector to copy + /// @see CanReinterpretSlice for rules about conversion + template >> + Slice(const Slice& other) { // NOLINT(runtime/explicit) + *this = other.template Reinterpret(); + } + + /// Constructor + /// @param d pointer to the first element in the slice + /// @param l total number of elements in the slice + /// @param c total capacity of the backing store for the slice + constexpr Slice(T* d, size_t l, size_t c) : data(d), len(l), cap(c) {} + + /// Constructor + /// @param d pointer to the first element in the slice + /// @param l total number of elements in the slice + constexpr Slice(T* d, size_t l) : data(d), len(l), cap(l) {} + + /// Constructor + /// @param elements c-array of elements + template + constexpr Slice(T (&elements)[N]) // NOLINT + : data(elements), len(N), cap(N) {} + + /// Constructor + /// @param array std::array of elements + template + constexpr Slice(std::array& array) // NOLINT + : data(array.data()), len(N), cap(N) {} + + /// Reinterprets this slice as `const Slice&` + /// @returns the reinterpreted slice + /// @see CanReinterpretSlice + template + const Slice& Reinterpret() const { + static_assert(CanReinterpretSlice); + return *Bitcast*>(this); + } + + /// Reinterprets this slice as `Slice&` + /// @returns the reinterpreted slice + /// @see CanReinterpretSlice + template + Slice& Reinterpret() { + static_assert(CanReinterpretSlice); + return *Bitcast*>(this); + } + + /// @return true if the slice length is zero + bool IsEmpty() const { return len == 0; } + + /// @return the length of the slice + size_t Length() const { return len; } + + /// Create a new slice that represents an offset into this slice + /// @param offset the number of elements to offset + /// @return the new slice + Slice Offset(size_t offset) const { + if (offset > len) { + offset = len; + } + return Slice(data + offset, len - offset, cap - offset); + } + + /// Create a new slice that represents a truncated version of this slice + /// @param length the new length + /// @return a new slice that is truncated to `length` elements + Slice Truncate(size_t length) const { + if (length > len) { + length = len; + } + return Slice(data, length, length); + } + + /// Index operator + /// @param i the element index. Must be less than `len`. + /// @returns a reference to the i'th element. + T& operator[](size_t i) { + TINT_ASSERT(i < Length()); + return data[i]; + } + + /// Index operator + /// @param i the element index. Must be less than `len`. + /// @returns a reference to the i'th element. + const T& operator[](size_t i) const { + TINT_ASSERT(i < Length()); + return data[i]; + } + + /// @returns a reference to the first element in the vector + T& Front() { + TINT_ASSERT(!IsEmpty()); + return data[0]; + } + + /// @returns a reference to the first element in the vector + const T& Front() const { + TINT_ASSERT(!IsEmpty()); + return data[0]; + } + + /// @returns a reference to the last element in the vector + T& Back() { + TINT_ASSERT(!IsEmpty()); + return data[len - 1]; + } + + /// @returns a reference to the last element in the vector + const T& Back() const { + TINT_ASSERT(!IsEmpty()); + return data[len - 1]; + } + + /// @returns a pointer to the first element in the vector + T* begin() { return data; } + + /// @returns a pointer to the first element in the vector + const T* begin() const { return data; } + + /// @returns a pointer to one past the last element in the vector + T* end() { return data + len; } + + /// @returns a pointer to one past the last element in the vector + const T* end() const { return data + len; } + + /// @returns a reverse iterator starting with the last element in the vector + auto rbegin() { return std::reverse_iterator(end()); } + + /// @returns a reverse iterator starting with the last element in the vector + auto rbegin() const { return std::reverse_iterator(end()); } + + /// @returns the end for a reverse iterator + auto rend() { return std::reverse_iterator(begin()); } + + /// @returns the end for a reverse iterator + auto rend() const { return std::reverse_iterator(begin()); } + + /// Equality operator. + /// @param other the other slice to compare against + /// @returns true if all fields of this slice are equal to the fields of @p other + bool operator==(const Slice& other) const { + return data == other.data && len == other.len && cap == other.cap; + } + + /// Inequality operator. + /// @param other the other slice to compare against + /// @returns false if any fields of this slice are not equal to the fields of @p other + bool operator!=(const Slice& other) const { return !(*this == other); } +}; + +/// Deduction guide for Slice from c-array +/// @param elements the input elements +template +Slice(T (&elements)[N]) -> Slice; + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_CONTAINERS_SLICE_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/transform.h b/3rdparty/dawn/src/tint/utils/containers/transform.h new file mode 100644 index 000000000..6f934b5df --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/transform.h @@ -0,0 +1,191 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_TRANSFORM_H_ +#define SRC_TINT_UTILS_CONTAINERS_TRANSFORM_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/rtti/traits.h" + +namespace tint { +//! @cond Doxygen_Suppress +// Doxygen gets confused by Transform()'s SFINAE + +/// Transform performs an element-wise transformation of a vector. +/// @param in the input vector. +/// @param transform the transformation function with signature: `OUT(IN)` +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(const std::vector& in, TRANSFORMER&& transform) + -> std::vector { + std::vector result(in.size()); + for (size_t i = 0; i < result.size(); ++i) { + result[i] = transform(in[i]); + } + return result; +} + +/// Transform performs an element-wise transformation of a vector. +/// @param in the input vector. +/// @param transform the transformation function with signature: `OUT(IN, size_t)` +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(const std::vector& in, TRANSFORMER&& transform) + -> std::vector { + std::vector result(in.size()); + for (size_t i = 0; i < result.size(); ++i) { + result[i] = transform(in[i], i); + } + return result; +} + +/// Transform performs an element-wise transformation of a vector. +/// @param in the input vector. +/// @param transform the transformation function with signature: `OUT(IN)` +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(const Vector& in, TRANSFORMER&& transform) + -> Vector { + const auto count = in.Length(); + Vector result; + result.Reserve(count); + for (size_t i = 0; i < count; ++i) { + result.Push(transform(in[i])); + } + return result; +} + +/// Transform performs an element-wise transformation of a vector. +/// @param in the input vector. +/// @param transform the transformation function with signature: `OUT(IN, size_t)` +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(const Vector& in, TRANSFORMER&& transform) + -> Vector { + const auto count = in.Length(); + Vector result; + result.Reserve(count); + for (size_t i = 0; i < count; ++i) { + result.Push(transform(in[i], i)); + } + return result; +} + +/// Transform performs an element-wise transformation of a slice. +/// @param in the input slice. +/// @param transform the transformation function with signature: `OUT(IN)` +/// @tparam N the small-array size of the returned Vector +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(Slice in, TRANSFORMER&& transform) -> Vector { + Vector result; + result.Reserve(in.len); + for (size_t i = 0; i < in.len; ++i) { + result.Push(transform(in[i])); + } + return result; +} + +/// Transform performs an element-wise transformation of a slice. +/// @param in the input slice. +/// @param transform the transformation function with signature: `OUT(IN, size_t)` +/// @tparam N the small-array size of the returned Vector +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(Slice in, TRANSFORMER&& transform) -> Vector { + Vector result; + result.Reserve(in.len); + for (size_t i = 0; i < in.len; ++i) { + result.Push(transform(in[i], i)); + } + return result; +} + +/// Transform performs an element-wise transformation of a vector reference. +/// @param in the input vector. +/// @param transform the transformation function with signature: `OUT(IN)` +/// @tparam N the small-array size of the returned Vector +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(VectorRef in, TRANSFORMER&& transform) -> Vector { + return Transform(in.Slice(), std::forward(transform)); +} + +/// Transform performs an element-wise transformation of a vector reference. +/// @param in the input vector. +/// @param transform the transformation function with signature: `OUT(IN, size_t)` +/// @tparam N the small-array size of the returned Vector +/// @returns a new vector with each element of the source vector transformed by `transform`. +template +auto Transform(VectorRef in, TRANSFORMER&& transform) + -> Vector { + return Transform(in.Slice(), std::forward(transform)); +} + +/// TransformN performs an element-wise transformation of a vector, transforming and returning at +/// most `n` elements. +/// @param in the input vector. +/// @param n the maximum number of elements to transform. +/// @param transform the transformation function with signature: `OUT(IN)` +/// @returns a new vector with at most n-elements of the source vector transformed by `transform`. +template +auto TransformN(const std::vector& in, size_t n, TRANSFORMER&& transform) + -> std::vector { + const auto count = std::min(n, in.size()); + std::vector result(count); + for (size_t i = 0; i < count; ++i) { + result[i] = transform(in[i]); + } + return result; +} + +/// TransformN performs an element-wise transformation of a vector, transforming and returning at +/// most `n` elements. +/// @param in the input vector. +/// @param n the maximum number of elements to transform. +/// @param transform the transformation function with signature: `OUT(IN, size_t)` +/// @returns a new vector with at most n-elements of the source vector transformed by `transform`. +template +auto TransformN(const std::vector& in, size_t n, TRANSFORMER&& transform) + -> std::vector { + const auto count = std::min(n, in.size()); + std::vector result(count); + for (size_t i = 0; i < count; ++i) { + result[i] = transform(in[i], i); + } + return result; +} + +} // namespace tint + +//! @endcond +#endif // SRC_TINT_UTILS_CONTAINERS_TRANSFORM_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/unique_allocator.h b/3rdparty/dawn/src/tint/utils/containers/unique_allocator.h new file mode 100644 index 000000000..b6d72246d --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/unique_allocator.h @@ -0,0 +1,138 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_UNIQUE_ALLOCATOR_H_ +#define SRC_TINT_UTILS_CONTAINERS_UNIQUE_ALLOCATOR_H_ + +#include +#include + +#include "src/tint/utils/containers/hashmap_base.h" +#include "src/tint/utils/memory/block_allocator.h" + +namespace tint { + +/// UniqueAllocator is used to allocate unique instances of the template type `T`. +template , typename EQUAL = std::equal_to> +class UniqueAllocator { + public: + /// Iterator is the type returned by begin() and end() + using Iterator = typename BlockAllocator::ConstIterator; + + /// @param args the arguments used to construct the object. + /// @return a pointer to an instance of `T` with the provided arguments. + /// If an existing instance of `T` has been constructed, then the same + /// pointer is returned. + template + TYPE* Get(ARGS&&... args) { + // Create a temporary T instance on the stack so that we can hash it, and use it for + // equality lookup for the Set. If the item is not found in the set, then we create the + // persisted instance with the allocator. + TYPE prototype{args...}; + Key& key = items.Add(&prototype); + if (key.Value() == &prototype) { + key = allocator.template Create(std::forward(args)...); + } + return static_cast(key.Value()); + } + + /// @param args the arguments used to create the temporary used for the search. + /// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item + /// was not found. + template + TYPE* Find(ARGS&&... args) const { + // Create a temporary T instance on the stack so that we can hash it, and use it for + // equality lookup for the Set. + TYPE prototype{std::forward(args)...}; + return static_cast(items.Get(&prototype)); + } + + /// Wrap sets this allocator to the objects created with the content of `inner`. + /// The allocator after Wrap is intended to temporarily extend the objects + /// of an existing immutable UniqueAllocator. + /// As the copied objects are owned by `inner`, `inner` must not be destructed + /// or assigned while using this allocator. + /// @param o the immutable UniqueAlllocator to extend + void Wrap(const UniqueAllocator& o) { items = o.items; } + + /// @returns an iterator to the beginning of the types + Iterator begin() const { return allocator.Objects().begin(); } + /// @returns an iterator to the end of the types + Iterator end() const { return allocator.Objects().end(); } + + private: + /// Comparator is the hashing function used by the Hashset + struct Hasher { + /// Hashing function + /// @param e the entry + /// @returns the hash of the entry + HashCode operator()(T* e) const { return HASH{}(*e); } + }; + + /// Equality is the equality function used by the Hashset + struct Equality { + /// Equality function + /// @param a the first entry to compare + /// @param b the second entry to compare + /// @returns true if the two entries are equal + bool operator()(T* a, T* b) const { return EQUAL{}(*a, *b); } + }; + + /// The maximum capacity of Set before it performs heap allocations. + static constexpr size_t kFixedSize = 32; + + /// The key type of Set. + using Key = HashmapKey; + + /// A custom Hashset implementation that allows keys to be modified. + class Set : public HashmapBase { + public: + Key& Add(T* key) { + auto idx = this->EditAt(key); + if (!idx.entry) { + idx.Insert(std::forward(key)); + } + return *idx.entry; + } + + T* Get(T* key) const { + if (auto* entry = this->GetEntry(key)) { + return *entry; + } + return nullptr; + } + }; + + /// The block allocator used to allocate the unique objects + BlockAllocator allocator; + /// The set of unique item entries + Set items; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_UNIQUE_ALLOCATOR_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/unique_vector.h b/3rdparty/dawn/src/tint/utils/containers/unique_vector.h new file mode 100644 index 000000000..38e471456 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/unique_vector.h @@ -0,0 +1,162 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_UNIQUE_VECTOR_H_ +#define SRC_TINT_UTILS_CONTAINERS_UNIQUE_VECTOR_H_ + +#include +#include +#include +#include +#include + +#include "src/tint/utils/containers/hashset.h" +#include "src/tint/utils/containers/vector.h" + +namespace tint { + +/// UniqueVector is an ordered container that only contains unique items. +/// Attempting to add a duplicate is a no-op. +template , typename EQUAL = std::equal_to> +struct UniqueVector { + /// STL-friendly alias to T. Used by gmock. + using value_type = T; + + /// Constructor + UniqueVector() = default; + + /// Constructor + /// @param v the vector to construct this UniqueVector with. Duplicate + /// elements will be removed. + explicit UniqueVector(std::vector&& v) { + for (auto& el : v) { + Add(el); + } + } + + /// Add appends the item to the end of the vector, if the vector does not + /// already contain the given item. + /// @param item the item to append to the end of the vector + /// @returns true if the item was added, otherwise false. + bool Add(const T& item) { + if (set.Add(item)) { + vector.Push(item); + return true; + } + return false; + } + + /// Removes @p count elements from the vector + /// @param start the index of the first element to remove + /// @param count the number of elements to remove + void Erase(size_t start, size_t count = 1) { + for (size_t i = 0; i < count; i++) { + set.Remove(vector[start + i]); + } + vector.Erase(start, count); + } + + /// @returns true if the vector contains `item` + /// @param item the item + bool Contains(const T& item) const { return set.Contains(item); } + + /// @param i the index of the element to retrieve + /// @returns the element at the index `i` + T& operator[](size_t i) { return vector[i]; } + + /// @param i the index of the element to retrieve + /// @returns the element at the index `i` + const T& operator[](size_t i) const { return vector[i]; } + + /// @returns true if the vector is empty + bool IsEmpty() const { return vector.IsEmpty(); } + + /// Removes all elements from the vector + void Clear() { + vector.Clear(); + set.Clear(); + } + + /// @returns the number of items in the vector + size_t Length() const { return vector.Length(); } + + /// @returns the pointer to the first element in the vector, or nullptr if the vector is empty. + const T* Data() const { return vector.IsEmpty() ? nullptr : &vector[0]; } + + /// @returns an iterator to the beginning of the vector + auto begin() const { return vector.begin(); } + + /// @returns an iterator to the end of the vector + auto end() const { return vector.end(); } + + /// @returns an iterator to the beginning of the reversed vector + auto rbegin() const { return vector.rbegin(); } + + /// @returns an iterator to the end of the reversed vector + auto rend() const { return vector.rend(); } + + /// @returns a reference to the internal vector + operator VectorRef() const { return vector; } + + /// @returns the std::move()'d vector. + /// @note The UniqueVector must not be used after calling this method + VectorRef Release() { return std::move(vector); } + + /// Pre-allocates `count` elements in the vector and set + /// @param count the number of elements to pre-allocate + void Reserve(size_t count) { + vector.Reserve(count); + set.Reserve(count); + } + + /// Removes the last element from the vector + /// @returns the popped element + T Pop() { + set.Remove(vector.Back()); + return vector.Pop(); + } + + /// Removes the last element from the vector if it is equal to @p value + /// @param value the value to pop if it is at the back of the vector + /// @returns true if the value was popped, otherwise false + bool TryPop(T value) { + if (!vector.IsEmpty() && vector.Back() == value) { + set.Remove(vector.Back()); + vector.Pop(); + return true; + } + return false; + } + + private: + Vector vector; + Hashset set; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_CONTAINERS_UNIQUE_VECTOR_H_ diff --git a/3rdparty/dawn/src/tint/utils/containers/vector.h b/3rdparty/dawn/src/tint/utils/containers/vector.h new file mode 100644 index 000000000..41e8020f8 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/containers/vector.h @@ -0,0 +1,1331 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_CONTAINERS_VECTOR_H_ +#define SRC_TINT_UTILS_CONTAINERS_VECTOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/utils/containers/slice.h" +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/memory/aligned_storage.h" +#include "src/tint/utils/memory/bitcast.h" + +// This file implements a custom STL style container & iterator in a performant manner, using +// C-style data access. It is not unexpected that -Wunsafe-buffer-usage triggers in this code, since +// the type of dynamic access being used cannot be guaranteed to be safe via static analysis. +// Attempting to change this code in simple ways to quiet these errors either a) negatively affects +// the performance by introducing unneeded copes, or b) uses typing shenanigans to work around the +// warning that other linters/analyses are unhappy with. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#ifndef TINT_VECTOR_MUTATION_CHECKS_ENABLED +#ifdef NDEBUG +#define TINT_VECTOR_MUTATION_CHECKS_ENABLED 0 +#else +#define TINT_VECTOR_MUTATION_CHECKS_ENABLED 1 +#endif +#endif + +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED +#define TINT_VECTOR_MUTATION_CHECK_ASSERT(x) TINT_ASSERT(x) +#else +#define TINT_VECTOR_MUTATION_CHECK_ASSERT(x) +#endif + +/// Forward declarations +namespace tint { +template +class VectorRef; +} // namespace tint + +namespace tint { + +/// VectorIterator is a forward iterator of Vector elements. +template +class VectorIterator { + public: + /// The iterator trait + using iterator_category = std::random_access_iterator_tag; + /// The type of an element that this iterator points to + using value_type = T; + /// The type of the difference of two iterators + using difference_type = std::ptrdiff_t; + /// A pointer of the element type + using pointer = T*; + /// A reference of the element type + using reference = T&; + + /// Constructor + VectorIterator() = default; + + /// Destructor + ~VectorIterator() { +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + if (iterator_count_) { + TINT_ASSERT(*iterator_count_ > 0); + (*iterator_count_)--; + } +#endif + } + +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + /// Constructor + /// @param p the pointer to the vector element + /// @param it_cnt a pointer to an iterator count + VectorIterator(T* p, std::atomic* it_cnt) : ptr_(p), iterator_count_(it_cnt) { + (*iterator_count_)++; + } + + /// Copy constructor + /// @param other the VectorIterator to copy + VectorIterator(const VectorIterator& other) + : ptr_(other.ptr_), iterator_count_(other.iterator_count_) { + if (iterator_count_) { + (*iterator_count_)++; + } + } + + /// Move constructor + /// @param other the VectorIterator to move + VectorIterator(VectorIterator&& other) + : ptr_(other.ptr_), iterator_count_(other.iterator_count_) { + other.ptr_ = nullptr; + other.iterator_count_ = nullptr; + } +#else + /// Constructor + /// @param p the pointer to the vector element + explicit VectorIterator(T* p) : ptr_(p) {} + + /// Copy constructor + /// @param other the VectorIterator to copy + VectorIterator(const VectorIterator& other) : ptr_(other.ptr_) {} + + /// Move constructor + /// @param other the VectorIterator to move + VectorIterator(VectorIterator&& other) : ptr_(other.ptr_) { other.ptr_ = nullptr; } +#endif + + /// Assignment operator + /// @param other the VectorIterator to copy + /// @return this VectorIterator + VectorIterator& operator=(const VectorIterator& other) { + ptr_ = other.ptr_; +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + if (iterator_count_ != other.iterator_count_) { + if (iterator_count_) { + (*iterator_count_)--; + } + iterator_count_ = other.iterator_count_; + if (iterator_count_) { + (*iterator_count_)++; + } + } +#endif + return *this; + } + + /// Move-assignment operator + /// @param other the VectorIterator to move + /// @return this VectorIterator + VectorIterator& operator=(VectorIterator&& other) { + ptr_ = other.ptr_; + other.ptr_ = nullptr; +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + if (iterator_count_) { + (*iterator_count_)--; + } + iterator_count_ = other.iterator_count_; + other.iterator_count_ = nullptr; +#endif + return *this; + } + + /// @return the element this iterator currently points at + operator T*() const { return ptr_; } + + /// @return the element this iterator currently points at + T& operator*() const { return *ptr_; } + + /// @return the element this iterator currently points at + T* operator->() const { return ptr_; } + + /// Equality operator + /// @param other the other VectorIterator + /// @return true if this iterator is equal to @p other + bool operator==(const VectorIterator& other) const { return ptr_ == other.ptr_; } + + /// Inequality operator + /// @param other the other VectorIterator + /// @return true if this iterator is not equal to @p other + bool operator!=(const VectorIterator& other) const { return ptr_ != other.ptr_; } + + /// Less-than operator + /// @param other the other iterator + /// @returns true if this iterator comes before @p other + bool operator<(const VectorIterator& other) const { return other - *this > 0; } + + /// Greater-than operator + /// @param other the other iterator + /// @returns true if this iterator comes after @p other + bool operator>(const VectorIterator& other) const { return *this - other > 0; } + + /// Index operator + /// @param i the number of elements from the element this iterator points to + /// @return the element + T& operator[](std::ptrdiff_t i) const { return *(*this + i); } + + /// Increments the iterator (prefix) + /// @returns this VectorIterator + VectorIterator& operator++() { + this->ptr_ = FORWARD ? this->ptr_ + 1 : this->ptr_ - 1; + return *this; + } + + /// Decrements the iterator (prefix) + /// @returns this VectorIterator + VectorIterator& operator--() { + this->ptr_ = FORWARD ? this->ptr_ - 1 : this->ptr_ + 1; + return *this; + } + + /// Increments the iterator (postfix) + /// @returns a VectorIterator that points to the element before the increment + VectorIterator operator++(int) { + VectorIterator res = *this; + this->ptr_ = FORWARD ? this->ptr_ + 1 : this->ptr_ - 1; + return res; + } + + /// Decrements the iterator (postfix) + /// @returns a VectorIterator that points to the element before the decrement + VectorIterator operator--(int) { + VectorIterator res = *this; + this->ptr_ = FORWARD ? this->ptr_ - 1 : this->ptr_ + 1; + return res; + } + + /// Moves the iterator forward by @p n elements + /// @param n the number of elements + /// @returns this VectorIterator + VectorIterator operator+=(std::ptrdiff_t n) { + this->ptr_ = FORWARD ? this->ptr_ + n : this->ptr_ - n; + return *this; + } + + /// Moves the iterator backwards by @p n elements + /// @param n the number of elements + /// @returns this VectorIterator + VectorIterator operator-=(std::ptrdiff_t n) { + this->ptr_ = FORWARD ? this->ptr_ - n : this->ptr_ + n; + return *this; + } + + /// @param n the number of elements + /// @returns a new VectorIterator progressed by @p n elements + VectorIterator operator+(std::ptrdiff_t n) const { +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + return VectorIterator{FORWARD ? ptr_ + n : ptr_ - n, iterator_count_}; +#else + return VectorIterator{FORWARD ? ptr_ + n : ptr_ - n}; +#endif + } + + /// @param n the number of elements + /// @returns a new VectorIterator regressed by @p n elements + VectorIterator operator-(std::ptrdiff_t n) const { +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + return VectorIterator{FORWARD ? ptr_ - n : ptr_ + n, iterator_count_}; +#else + return VectorIterator{FORWARD ? ptr_ - n : ptr_ + n}; +#endif + } + + /// @param other the other iterator + /// @returns the number of elements between this iterator and @p other + std::ptrdiff_t operator-(const VectorIterator& other) const { + return FORWARD ? ptr_ - other.ptr_ : other.ptr_ - ptr_; + } + + private: + T* ptr_ = nullptr; +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + std::atomic* iterator_count_ = nullptr; +#endif +}; + +/// @param out the stream to write to +/// @param it the VectorIterator +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const VectorIterator& it) { + return out << *it; +} + +/// Vector is a small-object-optimized, dynamically-sized vector of contigious elements of type T. +/// +/// Vector will fit `N` elements internally before spilling to heap allocations. If `N` is greater +/// than zero, the internal elements are stored in a 'small array' held internally by the Vector. +/// +/// Vectors can be copied or moved. +/// +/// Copying a vector will either copy to the 'small array' if the number of elements is equal to or +/// less than N, otherwise elements will be copied into a new heap allocation. +/// +/// Moving a vector will reassign ownership of the heap-allocation memory, if the source vector +/// holds its elements in a heap allocation, otherwise a copy will be made as described above. +/// +/// Vector is optimized for CPU performance over memory efficiency. For example: +/// * Moving a vector that stores its elements in a heap allocation to another vector will simply +/// assign the heap allocation, even if the target vector can hold the elements in its 'small +/// array'. This reduces memory copying, but may incur additional memory usage. +/// * Resizing, or popping elements from a vector that has spilled to a heap allocation does not +/// revert back to using the 'small array'. Again, this is to reduce memory copying. +template +class Vector { + public: + /// Alias to the non-const forward iterator + using iterator = VectorIterator; + /// Alias to the const forward iterator + using const_iterator = VectorIterator; + /// Alias to the non-const reverse iterator + using reverse_iterator = VectorIterator; + /// Alias to the const reverse iterator + using const_reverse_iterator = VectorIterator; + /// Alias to `T`. + using value_type = T; + /// Value of `N` + static constexpr size_t static_length = N; + + /// Constructor + Vector() = default; + + /// Constructor + Vector(EmptyType) {} // NOLINT(runtime/explicit) + + /// Constructor + /// @param elements the elements to place into the vector + Vector(std::initializer_list elements) { + Reserve(elements.size()); + for (auto& el : elements) { + new (&impl_.slice.data[impl_.slice.len++]) T{el}; + } + } + + /// Copy constructor + /// @param other the vector to copy + Vector(const Vector& other) { Copy(other.impl_.slice); } + + /// Move constructor + /// @param other the vector to move + Vector(Vector&& other) { Move(std::move(other)); } + + /// Copy constructor (differing N length) + /// @param other the vector to copy + template + Vector(const Vector& other) { + Copy(other.impl_.slice); + } + + /// Move constructor (differing N length) + /// @param other the vector to move + template + Vector(Vector&& other) { + Move(std::move(other)); + } + + /// Copy constructor with covariance / const conversion + /// @param other the vector to copy + /// @see CanReinterpretSlice for rules about conversion + template >> + Vector(const Vector& other) { // NOLINT(runtime/explicit) + Copy(other.impl_.slice.template Reinterpret); + } + + /// Move constructor with covariance / const conversion + /// @param other the vector to move + /// @see CanReinterpretSlice for rules about conversion + template >> + Vector(Vector&& other) { // NOLINT(runtime/explicit) + Move(std::move(other)); + } + + /// Move constructor from a mutable vector reference + /// @param other the vector reference to move + Vector(VectorRef&& other) { MoveOrCopy(std::move(other)); } // NOLINT(runtime/explicit) + + /// Copy constructor from an immutable vector reference + /// @param other the vector reference to copy + Vector(const VectorRef& other) { Copy(other.slice_); } // NOLINT(runtime/explicit) + + /// Copy constructor from an immutable slice + /// @param other the slice to copy + Vector(const Slice& other) { // NOLINT(runtime/explicit) + Copy(other); + } + + /// Copy constructor from an immutable slice + /// @param other the slice to copy + /// @note This overload only exists to keep MSVC happy. The compiler should be able to match + /// `Slice`. + Vector(const Slice& other) { // NOLINT(runtime/explicit) + Copy(other); + } + + /// Copy constructor from an immutable slice + /// @param other the slice to copy + template + Vector(const Slice& other) { // NOLINT(runtime/explicit) + Copy(other); + } + + /// Destructor + ~Vector() { ClearAndFree(); } + + /// Assignment operator + /// @param other the vector to copy + /// @returns this vector so calls can be chained + Vector& operator=(const Vector& other) { + if (&other != this) { + Copy(other.impl_.slice); + } + return *this; + } + + /// Move operator + /// @param other the vector to move + /// @returns this vector so calls can be chained + Vector& operator=(Vector&& other) { + if (&other != this) { + Move(std::move(other)); + } + return *this; + } + + /// Assignment operator (differing N length) + /// @param other the vector to copy + /// @returns this vector so calls can be chained + template + Vector& operator=(const Vector& other) { + Copy(other.impl_.slice); + return *this; + } + + /// Move operator (differing N length) + /// @param other the vector to copy + /// @returns this vector so calls can be chained + template + Vector& operator=(Vector&& other) { + Move(std::move(other)); + return *this; + } + + /// Assignment operator (differing N length) + /// @param other the vector reference to copy + /// @returns this vector so calls can be chained + Vector& operator=(const VectorRef& other) { + if (&other.slice_ != &impl_.slice) { + Copy(other.slice_); + } + return *this; + } + + /// Move operator (differing N length) + /// @param other the vector reference to copy + /// @returns this vector so calls can be chained + Vector& operator=(VectorRef&& other) { + if (&other.slice_ != &impl_.slice) { + MoveOrCopy(std::move(other)); + } + return *this; + } + + /// Assignment operator for Slice + /// @param other the slice to copy + /// @returns this vector so calls can be chained + Vector& operator=(const Slice& other) { + Copy(other); + return *this; + } + + /// Index operator + /// @param i the element index. Must be less than `len`. + /// @returns a reference to the i'th element. + T& operator[](size_t i) { return impl_.slice[i]; } + + /// Index operator + /// @param i the element index. Must be less than `len`. + /// @returns a reference to the i'th element. + const T& operator[](size_t i) const { return impl_.slice[i]; } + + /// @return the number of elements in the vector + size_t Length() const { return impl_.slice.len; } + + /// @return the number of elements that the vector could hold before a heap allocation needs to + /// be made + size_t Capacity() const { return impl_.slice.cap; } + + /// Reserves memory to hold at least `new_cap` elements + /// @param new_cap the new vector capacity + void Reserve(size_t new_cap) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + if (new_cap > impl_.slice.cap) { + auto* old_data = impl_.slice.data; + impl_.Allocate(new_cap); + for (size_t i = 0; i < impl_.slice.len; i++) { + new (&impl_.slice.data[i]) T(std::move(old_data[i])); + old_data[i].~T(); + } + impl_.Free(old_data); + } + } + + /// Resizes the vector to the given length, expanding capacity if necessary. + /// New elements are zero-initialized + /// @param new_len the new vector length + void Resize(size_t new_len) { + Reserve(new_len); + for (size_t i = impl_.slice.len; i > new_len; i--) { // Shrink + impl_.slice.data[i - 1].~T(); + } + for (size_t i = impl_.slice.len; i < new_len; i++) { // Grow + new (&impl_.slice.data[i]) T{}; + } + impl_.slice.len = new_len; + } + + /// Resizes the vector to the given length, expanding capacity if necessary. + /// @param new_len the new vector length + /// @param value the value to copy into the new elements + void Resize(size_t new_len, const T& value) { + Reserve(new_len); + for (size_t i = impl_.slice.len; i > new_len; i--) { // Shrink + impl_.slice.data[i - 1].~T(); + } + for (size_t i = impl_.slice.len; i < new_len; i++) { // Grow + new (&impl_.slice.data[i]) T{value}; + } + impl_.slice.len = new_len; + } + + /// Copies all the elements from `other` to this vector, replacing the content of this vector. + /// @param other the + template + void Copy(const Vector& other) { + Copy(other.impl_.slice); + } + + /// Clears all elements from the vector, keeping the capacity the same. + void Clear() { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + for (size_t i = 0; i < impl_.slice.len; i++) { + impl_.slice.data[i].~T(); + } + impl_.slice.len = 0; + } + + /// Appends a new element to the vector. + /// @param el the element to copy to the vector. + void Push(const T& el) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + if (impl_.slice.len >= impl_.slice.cap) { + Grow(); + } + new (&impl_.slice.data[impl_.slice.len++]) T(el); + } + + /// Appends a new element to the vector. + /// @param el the element to move to the vector. + void Push(T&& el) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + if (impl_.slice.len >= impl_.slice.cap) { + Grow(); + } + new (&impl_.slice.data[impl_.slice.len++]) T(std::move(el)); + } + + /// Appends a new element to the vector. + /// @param args the arguments to pass to the element constructor. + template + void Emplace(ARGS&&... args) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + if (impl_.slice.len >= impl_.slice.cap) { + Grow(); + } + new (&impl_.slice.data[impl_.slice.len++]) T{std::forward(args)...}; + } + + /// Removes and returns the last element from the vector. + /// @returns the popped element + T Pop() { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + TINT_ASSERT(!IsEmpty()); + auto& el = impl_.slice.data[--impl_.slice.len]; + auto val = std::move(el); + el.~T(); + return val; + } + + /// Inserts the element @p element before the element at @p before + /// @param before the index of the element to insert before + /// @param element the element to insert + template + void Insert(size_t before, EL&& element) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + TINT_ASSERT(before <= Length()); + size_t n = Length(); + Resize(Length() + 1); + // Shuffle + for (size_t i = n; i > before; i--) { + auto& src = impl_.slice.data[i - 1]; + auto& dst = impl_.slice.data[i]; + dst = std::move(src); + } + // Insert + impl_.slice.data[before] = std::forward(element); + } + + /// Removes @p count elements from the vector + /// @param start the index of the first element to remove + /// @param count the number of elements to remove + void Erase(size_t start, size_t count = 1) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + TINT_ASSERT(start < Length()); + TINT_ASSERT((start + count) <= Length()); + // Shuffle + for (size_t i = start + count; i < impl_.slice.len; i++) { + auto& src = impl_.slice.data[i]; + auto& dst = impl_.slice.data[i - count]; + dst = std::move(src); + } + // Pop + for (size_t i = 0; i < count; i++) { + auto& el = impl_.slice.data[--impl_.slice.len]; + el.~T(); + } + } + + /// Removes all the elements from the vector that match the predicate function. + /// @param predicate the predicate function with the signature `bool(const T&)`. This function + /// should return `true` for elements that should be removed from the vector. + template + void EraseIf(PREDICATE&& predicate) { + TINT_VECTOR_MUTATION_CHECK_ASSERT(iterator_count_ == 0); + // Shuffle + size_t num_removed = 0; + for (size_t i = 0; i < impl_.slice.len; i++) { + auto& el = impl_.slice.data[i]; + bool remove = predicate(const_cast(el)); + if (num_removed > 0) { + auto& dst = impl_.slice.data[i - num_removed]; + dst = std::move(el); + } + if (remove) { + num_removed++; + } + } + // Pop + for (size_t i = 0; i < num_removed; i++) { + auto& el = impl_.slice.data[--impl_.slice.len]; + el.~T(); + } + } + + /// Sort sorts the vector in-place using the predicate function @p pred + /// @param pred a function that has the signature `bool(const T& a, const T& b)` which returns + /// true if `a` is ordered before `b`. + template + void Sort(PREDICATE&& pred) { + std::sort(begin(), end(), std::forward(pred)); + } + + /// Sort sorts the vector in-place using `T::operator<()` + /// @returns this vector so calls can be chained + Vector& Sort() { + Sort([](auto& a, auto& b) { return a < b; }); + return *this; + } + + /// Reverse reversed the vector in-place + void Reverse() { + size_t n = Length(); + size_t mid = n / 2; + auto& self = *this; + for (size_t i = 0; i < mid; i++) { + std::swap(self[i], self[n - i - 1]); + } + } + + /// @returns true if the predicate function returns true for any of the elements of the vector + /// @param pred a function-like with the signature `bool(T)` + template + bool Any(PREDICATE&& pred) const { + return std::any_of(begin(), end(), std::forward(pred)); + } + + /// @returns false if the predicate function returns false for any of the elements of the vector + /// @param pred a function-like with the signature `bool(T)` + template + bool All(PREDICATE&& pred) const { + return std::all_of(begin(), end(), std::forward(pred)); + } + + /// @returns true if the vector is empty. + bool IsEmpty() const { return impl_.slice.len == 0; } + + /// @returns a reference to the first element in the vector + T& Front() { return impl_.slice.Front(); } + + /// @returns a reference to the first element in the vector + const T& Front() const { return impl_.slice.Front(); } + + /// @returns a reference to the last element in the vector + T& Back() { return impl_.slice.Back(); } + + /// @returns a reference to the last element in the vector + const T& Back() const { return impl_.slice.Back(); } + +#if TINT_VECTOR_MUTATION_CHECKS_ENABLED + /// @returns a forward iterator to the first element of the vector + iterator begin() { return iterator{impl_.slice.begin(), &iterator_count_}; } + + /// @returns a forward iterator to the first element of the vector + const const_iterator begin() const { + return const_iterator{impl_.slice.begin(), &iterator_count_}; + } + + /// @returns a forward iterator to one-pass the last element of the vector + iterator end() { return iterator{impl_.slice.end(), &iterator_count_}; } + + /// @returns a forward iterator to one-pass the last element of the vector + const const_iterator end() const { return const_iterator{impl_.slice.end(), &iterator_count_}; } + + /// @returns a reverse iterator to the last element of the vector + reverse_iterator rbegin() { return reverse_iterator{impl_.slice.end(), &iterator_count_} + 1; } + + /// @returns a reverse iterator to the last element of the vector + const const_reverse_iterator rbegin() const { + return const_reverse_iterator{impl_.slice.end(), &iterator_count_} + 1; + } + + /// @returns a reverse iterator to one element before the first element of the vector + reverse_iterator rend() { return reverse_iterator{impl_.slice.begin(), &iterator_count_} + 1; } + + /// @returns a reverse iterator to one element before the first element of the vector + const const_reverse_iterator rend() const { + return const_reverse_iterator{impl_.slice.begin(), &iterator_count_} + 1; + } +#else + /// @returns a forward iterator to the first element of the vector + iterator begin() { return iterator{impl_.slice.begin()}; } + + /// @returns a forward iterator to the first element of the vector + const const_iterator begin() const { return const_iterator{impl_.slice.begin()}; } + + /// @returns a forward iterator to one-pass the last element of the vector + iterator end() { return iterator{impl_.slice.end()}; } + + /// @returns a forward iterator to one-pass the last element of the vector + const const_iterator end() const { return const_iterator{impl_.slice.end()}; } + + /// @returns a reverse iterator to the last element of the vector + reverse_iterator rbegin() { return reverse_iterator{impl_.slice.end()} + 1; } + + /// @returns a reverse iterator to the last element of the vector + const const_reverse_iterator rbegin() const { + return const_reverse_iterator{impl_.slice.end()} + 1; + } + + /// @returns a reverse iterator to one element before the first element of the vector + reverse_iterator rend() { return reverse_iterator{impl_.slice.begin()} + 1; } + + /// @returns a reverse iterator to one element before the first element of the vector + const const_reverse_iterator rend() const { + return const_reverse_iterator{impl_.slice.begin()} + 1; + } +#endif + + /// @returns a hash code for this Vector + tint::HashCode HashCode() const { + auto hash = Hash(Length()); + for (auto& el : *this) { + hash = HashCombine(hash, el); + } + return hash; + } + + /// Equality operator + /// @param other the other vector + /// @returns true if this vector is the same length as `other`, and all elements are equal. + template + bool operator==(const Vector& other) const { + const size_t len = Length(); + if (len != other.Length()) { + return false; + } + for (size_t i = 0; i < len; i++) { + if ((*this)[i] != other[i]) { + return false; + } + } + return true; + } + + /// Inequality operator + /// @param other the other vector + /// @returns true if this vector is not the same length as `other`, or all elements are not + /// equal. + template + bool operator!=(const Vector& other) const { + return !(*this == other); + } + + /// @returns the internal slice of the vector + tint::Slice Slice() { return impl_.slice; } + + /// @returns the internal slice of the vector + tint::Slice Slice() const { return impl_.slice; } + + /// @returns the internal data of the vector as a std::span + std::span AsSpan() { return {impl_.slice.data, impl_.slice.len}; } + + /// @returns the internal data of the vector as a std::span + std::span AsSpan() const { return {impl_.slice.data, impl_.slice.len}; } + + private: + /// Friend class (differing specializations of this class) + template + friend class Vector; + + /// Friend class + template + friend class VectorRef; + + /// Friend class + template + friend class VectorRef; + + template + void AppendVariadic(Ts&&... args) { + ((new (&impl_.slice.data[impl_.slice.len++]) T(std::forward(args))), ...); + } + + /// Expands the capacity of the vector + void Grow() { Reserve(std::max(impl_.slice.cap, static_cast(1)) * 2); } + + /// Moves 'other' to this vector, if possible, otherwise performs a copy. + void MoveOrCopy(VectorRef&& other) { + if (other.can_move_) { + // Just steal the slice. + ClearAndFree(); + impl_.slice = other.slice_; + other.slice_ = {}; + } else { + Copy(other.slice_); + } + } + + /// Copies all the elements from `other` to this vector, replacing the content of this vector. + /// @param other the slice to copy + template + void Copy(const tint::Slice& other) { + if (impl_.slice.cap < other.len) { + ClearAndFree(); + impl_.Allocate(other.len); + } else { + Clear(); + } + + impl_.slice.len = other.len; + for (size_t i = 0; i < impl_.slice.len; i++) { + new (&impl_.slice.data[i]) T{other.data[i]}; + } + } + + /// Moves all the elements from `other` to this vector, replacing the content of this vector. + /// @param other the vector to move + template + void Move(Vector&& other) { + auto& other_slice = other.impl_.slice; + if constexpr (std::is_same_v) { + if (other.impl_.CanMove()) { + // Just steal the slice. + ClearAndFree(); + impl_.slice = other_slice; + other_slice = {}; + return; + } + } + + // Can't steal the slice, so we have to move the elements instead. + + // Ensure we have capacity for all the elements + if (impl_.slice.cap < other_slice.len) { + ClearAndFree(); + impl_.Allocate(other_slice.len); + } else { + Clear(); + } + + // Move each of the elements. + impl_.slice.len = other_slice.len; + for (size_t i = 0; i < impl_.slice.len; i++) { + new (&impl_.slice.data[i]) T{std::move(other_slice.data[i])}; + } + + // Clear other + other.Clear(); + } + + /// Clears the vector, then frees the slice data. + void ClearAndFree() { + Clear(); + impl_.Free(impl_.slice.data); + } + + /// True if this vector uses a small array for small object optimization. + constexpr static bool HasSmallArray = N > 0; + + /// A structure that has the same size and alignment as T. + using TStorage = AlignedStorage; + + /// The internal structure for the vector with a small array. + struct ImplWithSmallArray { + TStorage small_arr[N]; + tint::Slice slice = {&small_arr[0].Get(), 0, N}; + + /// Allocates a new vector of `T` either from #small_arr, or from the heap, then assigns the + /// pointer it to #slice.data, and updates #slice.cap. + void Allocate(size_t new_cap) { + if (new_cap < N) { + slice.data = &small_arr[0].Get(); + slice.cap = N; + } else { + slice.data = Bitcast(new TStorage[new_cap]); + slice.cap = new_cap; + } + } + + /// Frees `data`, if isn't a pointer to #small_arr + void Free(T* data) const { + if (data != &small_arr[0].Get()) { + delete[] Bitcast(data); + } + } + + /// Indicates whether the slice structure can be std::move()d. + /// @returns true if #slice.data does not point to #small_arr + bool CanMove() const { return slice.data != &small_arr[0].Get(); } + }; + + /// The internal structure for the vector without a small array. + struct ImplWithoutSmallArray { + tint::Slice slice = Empty; + + /// Allocates a new vector of `T` and assigns it to #slice.data, and updates #slice.cap. + void Allocate(size_t new_cap) { + slice.data = Bitcast(new TStorage[new_cap]); + slice.cap = new_cap; + } + + /// Frees `data`. + void Free(T* data) const { delete[] Bitcast(data); } + + /// Indicates whether the slice structure can be std::move()d. + /// @returns true + bool CanMove() const { return true; } + }; + + /// Either a ImplWithSmallArray or ImplWithoutSmallArray based on N. + std::conditional_t impl_; + + /// The current number of iterators referring to this vector + mutable std::atomic iterator_count_ = 0; +}; + +namespace detail { + +/// Helper for determining the Vector element type (`T`) from the vector's constuctor arguments +/// @tparam IS_CASTABLE true if the types of `Ts` derive from CastableBase +/// @tparam Ts the vector constructor argument types to infer the vector element type from. +template +struct VectorCommonType; + +/// VectorCommonType specialization for non-castable types. +template +struct VectorCommonType { + /// The common T type to use for the vector + using type = std::common_type_t; +}; + +/// VectorCommonType specialization for castable types. +template +struct VectorCommonType { + /// The common Castable type (excluding pointer) + using common_ty = CastableCommonBase...>; + /// The common T type to use for the vector + using type = std::conditional_t<(std::is_const_v> || ...), + const common_ty*, + common_ty*>; +}; + +} // namespace detail + +/// Helper for determining the Vector element type (`T`) from the vector's constuctor arguments +template +using VectorCommonType = + typename tint::detail::VectorCommonType...>, Ts...>::type; + +/// Deduction guide for Vector +template +Vector(Ts...) -> Vector, sizeof...(Ts)>; + +/// VectorRef is a weak reference to a Vector, used to pass vectors as parameters, avoiding copies +/// between the caller and the callee, or as an non-static sized accessor on a vector. VectorRef can +/// accept a Vector of any 'N' value, decoupling the caller's vector internal size from the callee's +/// vector size. A VectorRef tracks the usage of moves either side of the call. If at the call site, +/// a Vector argument is moved to a VectorRef parameter, and within the callee, the VectorRef +/// parameter is moved to a Vector, then the Vector heap allocation will be moved. For example: +/// +/// ``` +/// void func_a() { +/// Vector vec; +/// // logic to populate 'vec'. +/// func_b(std::move(vec)); // Constructs a VectorRef tracking the move here. +/// } +/// +/// void func_b(VectorRef vec_ref) { +/// // A move was made when calling func_b, so the vector can be moved instead of copied. +/// Vector vec(std::move(vec_ref)); +/// } +/// ``` +/// +/// Aside from this move pattern, a VectorRef provides an immutable reference to the Vector. +template +class VectorRef { + /// @returns an empty slice. + static tint::Slice& EmptySlice() { + static tint::Slice empty; + return empty; + } + + public: + /// Type of `T`. + using value_type = T; + + /// Constructor - empty reference + VectorRef() : slice_(EmptySlice()) {} + + /// Constructor + VectorRef(EmptyType) : slice_(EmptySlice()) {} // NOLINT(runtime/explicit) + + /// Constructor from a Slice + /// @param slice the slice + VectorRef(tint::Slice& slice) // NOLINT(runtime/explicit) + : slice_(slice) {} + + /// Constructor from a Vector + /// @param vector the vector to create a reference of + template + VectorRef(Vector& vector) // NOLINT(runtime/explicit) + : slice_(vector.impl_.slice) {} + + /// Constructor from a const Vector + /// @param vector the vector to create a reference of + template + VectorRef(const Vector& vector) // NOLINT(runtime/explicit) + : slice_(const_cast&>(vector.impl_.slice)) {} + + /// Constructor from a moved Vector + /// @param vector the vector being moved + template + VectorRef(Vector&& vector) // NOLINT(runtime/explicit) + : slice_(vector.impl_.slice), can_move_(vector.impl_.CanMove()) {} + + /// Copy constructor + /// @param other the vector reference + VectorRef(const VectorRef& other) : slice_(other.slice_) {} + + /// Move constructor + /// @param other the vector reference + VectorRef(VectorRef&& other) = default; + + /// Copy constructor with covariance / const conversion + /// @param other the other vector reference + template >> + VectorRef(const VectorRef& other) // NOLINT(runtime/explicit) + : slice_(other.slice_.template Reinterpret()) {} + + /// Move constructor with covariance / const conversion + /// @param other the vector reference + template >> + VectorRef(VectorRef&& other) // NOLINT(runtime/explicit) + : slice_(other.slice_.template Reinterpret()), can_move_(other.can_move_) {} + + /// Constructor from a Vector with covariance / const conversion + /// @param vector the vector to create a reference of + /// @see CanReinterpretSlice for rules about conversion + template >> + VectorRef(const Vector& vector) // NOLINT(runtime/explicit) + : slice_(const_cast&>(vector.impl_.slice).template Reinterpret()) {} + + /// Constructor from a moved Vector with covariance / const conversion + /// @param vector the vector to create a reference of + /// @see CanReinterpretSlice for rules about conversion + template >> + VectorRef(Vector&& vector) // NOLINT(runtime/explicit) + : slice_(vector.impl_.slice.template Reinterpret()), can_move_(vector.impl_.CanMove()) {} + + /// Index operator + /// @param i the element index. Must be less than `len`. + /// @returns a reference to the i'th element. + const T& operator[](size_t i) const { return slice_[i]; } + + /// @return the number of elements in the vector + size_t Length() const { return slice_.len; } + + /// @return the number of elements that the vector could hold before a heap allocation needs to + /// be made + size_t Capacity() const { return slice_.cap; } + + /// @return a reinterpretation of this VectorRef as elements of type U. + /// @note this is doing a reinterpret_cast of elements. It is up to the caller to ensure that + /// this is a safe operation. + template + VectorRef ReinterpretCast() const { + return {slice_.template Reinterpret()}; + } + + /// @returns the internal slice of the vector + tint::Slice Slice() { return slice_; } + + /// @returns true if the vector is empty. + bool IsEmpty() const { return slice_.len == 0; } + + /// @returns a reference to the first element in the vector + const T& Front() const { return slice_.Front(); } + + /// @returns a reference to the last element in the vector + const T& Back() const { return slice_.Back(); } + + /// @returns a pointer to the first element in the vector + const T* begin() const { return slice_.begin(); } + + /// @returns a pointer to one past the last element in the vector + const T* end() const { return slice_.end(); } + + /// @returns a reverse iterator starting with the last element in the vector + auto rbegin() const { return slice_.rbegin(); } + + /// @returns the end for a reverse iterator + auto rend() const { return slice_.rend(); } + + /// @returns a hash code of the Vector + tint::HashCode HashCode() const { + auto hash = Hash(Length()); + for (auto& el : *this) { + hash = HashCombine(hash, el); + } + return hash; + } + + /// @returns true if the predicate function returns true for any of the elements of the vector + /// @param pred a function-like with the signature `bool(T)` + template + bool Any(PREDICATE&& pred) const { + return std::any_of(begin(), end(), std::forward(pred)); + } + + /// @returns true if the predicate function returns true for all the elements of the vector + /// @param pred a function-like with the signature `bool(T)` + template + bool All(PREDICATE&& pred) const { + return std::all_of(begin(), end(), std::forward(pred)); + } + + private: + /// Friend class + template + friend class Vector; + + /// Friend class + template + friend class VectorRef; + + /// Friend class + template + friend class VectorRef; + + /// The slice of the vector being referenced. + tint::Slice& slice_; + /// Whether the slice data is passed by r-value reference, and can be moved. + bool can_move_ = false; +}; + +/// Helper for converting a Vector to a std::vector. +/// @param vector the input vector +/// @return the converted vector +/// @note This helper exists to help code migration. Avoid if possible. +template +std::vector ToStdVector(const Vector& vector) { + std::vector out; + out.reserve(vector.Length()); + for (auto& el : vector) { + out.emplace_back(el); + } + return out; +} + +/// Helper for constructing a Vector from a Slice. Only the size must be supplied as the type is +/// deduced. +/// @param slice the input slice +/// @return the converted vector +/// @note This helper is useful because Vectors require a size parameter, but because it is the +/// second template parameter to a Vector, both the type and size parameters must be explicitly +/// declared. Furthermore, Slices are often of const pointer/reference type, but a Vector cannot be +/// of const pointer/reference type, again requiring the caller to be explicit. This helper makes it +/// possible to only specify the size. +template +auto ToVector(const tint::Slice& slice) { + // If Slice is of type 'T* const', make it 'T*' (or 'T& const', make it 'T&') as Vectors cannot + // be of const pointer/reference type. + using U = std::conditional_t || std::is_reference_v, + std::remove_const_t, T>; + return Vector{slice}; +} + +/// Helper for converting a std::vector to a Vector. +/// @param vector the input vector +/// @return the converted vector +/// @note This helper exists to help code migration. Avoid if possible. +template +Vector ToVector(const std::vector& vector) { + Vector out; + out.Reserve(vector.size()); + for (auto& el : vector) { + out.Push(el); + } + return out; +} + +/// Prints the vector @p vec to @p o +/// @param o the stream to write to +/// @param vec the vector +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, const Vector& vec) { + o << "["; + bool first = true; + for (auto& el : vec) { + if (!first) { + o << ", "; + } + first = false; + o << el; + } + o << "]"; + return o; +} + +/// Prints the vector @p vec to @p o +/// @param o the stream to write to +/// @param vec the vector reference +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& o, VectorRef vec) { + o << "["; + bool first = true; + for (auto& el : vec) { + if (!first) { + o << ", "; + } + first = false; + o << el; + } + o << "]"; + return o; +} + +namespace detail { + +/// IsVectorLike::value is true if T is a Vector or VectorRef. +template +struct IsVectorLike { + /// Non-specialized form of IsVectorLike defaults to false + static constexpr bool value = false; +}; + +/// IsVectorLike specialization for Vector +template +struct IsVectorLike> { + /// True for the IsVectorLike specialization of Vector + static constexpr bool value = true; +}; + +/// IsVectorLike specialization for VectorRef +template +struct IsVectorLike> { + /// True for the IsVectorLike specialization of VectorRef + static constexpr bool value = true; +}; +} // namespace detail + +/// True if T is a Vector or VectorRef +template +static constexpr bool IsVectorLike = tint::detail::IsVectorLike::value; + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_CONTAINERS_VECTOR_H_ diff --git a/3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.cc b/3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.cc new file mode 100644 index 000000000..b0825e079 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.cc @@ -0,0 +1,86 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/diagnostic/diagnostic.h" + +#include + +#include "src/tint/utils/diagnostic/formatter.h" +#include "src/tint/utils/text/styled_text.h" + +namespace tint::diag { + +namespace { +size_t CountErrors(VectorRef diags) { + size_t count = 0; + for (auto& diag : diags) { + if (diag.severity >= Severity::Error) { + count++; + } + } + return count; +} +} // namespace + +Diagnostic::Diagnostic() = default; +Diagnostic::Diagnostic(const Diagnostic&) = default; +Diagnostic::~Diagnostic() = default; +Diagnostic& Diagnostic::operator=(const Diagnostic&) = default; + +List::List() = default; +List::List(std::initializer_list list) + : entries_(list), error_count_(CountErrors(entries_)) {} +List::List(VectorRef list) + : entries_(std::move(list)), error_count_(CountErrors(entries_)) {} + +List::List(const List& rhs) = default; + +List::List(List&& rhs) = default; + +List::~List() = default; + +List& List::operator=(const List& rhs) = default; + +List& List::operator=(List&& rhs) = default; + +std::string List::Str() const { + diag::Formatter::Style style; + style.print_newline_at_end = false; + return Formatter{style}.Format(*this).Plain(); +} + +Failure::Failure() = default; + +Failure::Failure(std::string_view err) { + reason.AddError(Source{}) << err; +} + +Failure::Failure(diag::Diagnostic diagnostic) : reason(diag::List{std::move(diagnostic)}) {} + +Failure::Failure(diag::List diagnostics) : reason(std::move(diagnostics)) {} + +} // namespace tint::diag diff --git a/3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.h b/3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.h new file mode 100644 index 000000000..cee59c224 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/diagnostic/diagnostic.h @@ -0,0 +1,270 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_DIAGNOSTIC_DIAGNOSTIC_H_ +#define SRC_TINT_UTILS_DIAGNOSTIC_DIAGNOSTIC_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/diagnostic/source.h" +#include "src/tint/utils/result.h" +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/styled_text.h" + +namespace tint::diag { + +/// Severity is an enumerator of diagnostic severities. +enum class Severity : uint8_t { Note, Warning, Error }; + +/// @return true iff `a` is more than, or of equal severity to `b` +inline bool operator>=(Severity a, Severity b) { + return static_cast(a) >= static_cast(b); +} + +/// Diagnostic holds all the information for a single compiler diagnostic +/// message. +class Diagnostic { + public: + /// Constructor + Diagnostic(); + /// Copy constructor + Diagnostic(const Diagnostic&); + /// Destructor + ~Diagnostic(); + + /// Copy assignment operator + /// @return this diagnostic + Diagnostic& operator=(const Diagnostic&); + + /// Appends @p msg to the diagnostic's message + template + Diagnostic& operator<<(T&& msg) { + message << std::forward(msg); + return *this; + } + + /// severity is the severity of the diagnostic message. + Severity severity = Severity::Error; + /// source is the location of the diagnostic. + Source source; + /// message is the text associated with the diagnostic. + StyledText message; + /// A shared pointer to a Source::File. Only used if the diagnostic Source + /// points to a file that was created specifically for this diagnostic + /// (usually an ICE). + std::shared_ptr owned_file = nullptr; +}; + +/// List is a container of Diagnostic messages. +class List { + public: + /// The iterator types for this List + using iterator = VectorIterator; + using const_iterator = VectorIterator; + + /// Constructs the list with no elements. + List(); + + /// Constructor. Copies the diagnostics from @p list into this list. + /// @param list the list of diagnostics to copy into this list. + List(std::initializer_list list); + + /// Constructor. Copies the diagnostics from @p list into this list. + /// @param list the list of diagnostics to copy into this list. + explicit List(VectorRef list); + + /// Copy constructor. Copies the diagnostics from @p list into this list. + /// @param list the list of diagnostics to copy into this list. + List(const List& list); + + /// Move constructor. Moves the diagnostics from @p list into this list. + /// @param list the list of diagnostics to move into this list. + List(List&& list); + + /// Destructor + ~List(); + + /// Assignment operator. Copies the diagnostics from @p list into this list. + /// @param list the list to copy into this list. + /// @return this list. + List& operator=(const List& list); + + /// Assignment move operator. Moves the diagnostics from @p list into this list. + /// @param list the list to move into this list. + /// @return this list. + List& operator=(List&& list); + + /// Adds a diagnostic to the end of this list. + /// @param diag the diagnostic to append to this list. + /// @returns a reference to the new diagnostic. + /// @note The returned reference must not be used after the list is mutated again. + diag::Diagnostic& Add(const Diagnostic& diag) { + if (diag.severity >= Severity::Error) { + error_count_++; + } + entries_.Push(diag); + return entries_.Back(); + } + + /// Adds a diagnostic to the end of this list. + /// @param diag the diagnostic to append to this list. + /// @returns a reference to the new diagnostic. + /// @note The returned reference must not be used after the list is mutated again. + diag::Diagnostic& Add(Diagnostic&& diag) { + if (diag.severity >= Severity::Error) { + error_count_++; + } + entries_.Push(std::move(diag)); + return entries_.Back(); + } + + /// Adds a list of diagnostics to the end of this list. + /// @param list the diagnostic to append to this list. + void Add(const List& list) { + for (auto diag : list) { + Add(std::move(diag)); + } + } + + /// Adds the note message with the given Source to the end of this list. + /// @param source the source of the note diagnostic + /// @returns a reference to the new diagnostic. + /// @note The returned reference must not be used after the list is mutated again. + diag::Diagnostic& AddNote(const Source& source) { + diag::Diagnostic note{}; + note.severity = diag::Severity::Note; + note.source = source; + return Add(std::move(note)); + } + + /// Adds the warning message with the given Source to the end of this list. + /// @param source the source of the warning diagnostic + /// @returns a reference to the new diagnostic. + /// @note The returned reference must not be used after the list is mutated again. + diag::Diagnostic& AddWarning(const Source& source) { + diag::Diagnostic warning{}; + warning.severity = diag::Severity::Warning; + warning.source = source; + return Add(std::move(warning)); + } + + /// Adds the error message with the given Source to the end of this list. + /// @param source the source of the error diagnostic + /// @returns a reference to the new diagnostic. + /// @note The returned reference must not be used after the list is mutated again. + diag::Diagnostic& AddError(const Source& source) { + diag::Diagnostic error{}; + error.severity = diag::Severity::Error; + error.source = source; + return Add(std::move(error)); + } + + /// @returns true iff the diagnostic list contains errors diagnostics (or of + /// higher severity). + bool ContainsErrors() const { return error_count_ > 0; } + /// @returns the number of error diagnostics (or of higher severity). + size_t NumErrors() const { return error_count_; } + /// @returns the number of entries in the list. + size_t Count() const { return entries_.Length(); } + /// @returns true if the diagnostics list is empty + bool IsEmpty() const { return entries_.IsEmpty(); } + + /// @returns a formatted string of all the diagnostics in this list. + std::string Str() const; + + //////////////////////////////////////////////////////////////////////////// + /// STL-interface support + //////////////////////////////////////////////////////////////////////////// + /// @returns true if the diagnostics list is empty + bool empty() const { return entries_.IsEmpty(); } + /// @returns the number of entries in the list. + size_t size() const { return entries_.Length(); } + /// @returns the first diagnostic in the list. + const_iterator begin() const { return entries_.begin(); } + /// @returns the last diagnostic in the list. + const_iterator end() const { return entries_.end(); } + /// @returns the first diagnostic in the list. + iterator begin() { return entries_.begin(); } + /// @returns the last diagnostic in the list. + iterator end() { return entries_.end(); } + + private: + Vector entries_; + size_t error_count_ = 0; +}; + +/// The default Result error type. +struct Failure { + /// Constructor with no diagnostics + Failure(); + + /// Constructor with a single diagnostic + /// @param err the single error diagnostic + explicit Failure(std::string_view err); + + /// Constructor with a single diagnostic + /// @param diagnostic the failure diagnostic + explicit Failure(diag::Diagnostic diagnostic); + + /// Constructor with a list of diagnostics + /// @param diagnostics the failure diagnostics + explicit Failure(diag::List diagnostics); + + /// The diagnostics explaining the failure reason + diag::List reason; +}; + +template +using Result = ::tint::Result; + +/// Write the Failure to the given stream +/// @param out the output stream +/// @param failure the Failure +/// @returns the output stream +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Failure& failure) { + return out << failure.reason.Str(); +} + +/// Write the diagnostic list to the given stream +/// @param out the output stream +/// @param list the list to emit +/// @returns the output stream +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const List& list) { + return out << list.Str(); +} + +} // namespace tint::diag + +#endif // SRC_TINT_UTILS_DIAGNOSTIC_DIAGNOSTIC_H_ diff --git a/3rdparty/dawn/src/tint/utils/diagnostic/formatter.cc b/3rdparty/dawn/src/tint/utils/diagnostic/formatter.cc new file mode 100644 index 000000000..5b5c57419 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/diagnostic/formatter.cc @@ -0,0 +1,208 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/diagnostic/formatter.h" + +#include +#include +#include +#include + +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/styled_text_printer.h" +#include "src/tint/utils/text/text_style.h" + +namespace tint::diag { +namespace { + +const char* ToString(Severity severity) { + switch (severity) { + case Severity::Note: + return "note"; + case Severity::Warning: + return "warning"; + case Severity::Error: + return "error"; + } + return ""; +} + +std::string ToString(const Source::Location& location) { + StringStream ss; + if (location.line > 0) { + ss << location.line; + if (location.column > 0) { + ss << ":" << location.column; + } + } + return ss.str(); +} + +} // namespace + +Formatter::Formatter() {} +Formatter::Formatter(const Style& style) : style_(style) {} + +StyledText Formatter::Format(const List& list) const { + StyledText text; + + bool first = true; + for (auto diag : list) { + if (!first) { + text << "\n"; + } + Format(diag, text); + first = false; + } + + if (style_.print_newline_at_end) { + text << "\n"; + } + + return text; +} + +void Formatter::Format(const Diagnostic& diag, StyledText& text) const { + auto const& src = diag.source; + auto const& rng = src.range; + + text << style::Plain; + TINT_DEFER(text << style::Plain); + + struct TextAndStyle { + std::string text; + TextStyle style = {}; + }; + Vector prefix; + + if (style_.print_file && src.file != nullptr) { + if (rng.begin.line > 0) { + prefix.Push(TextAndStyle{src.file->path + ":" + ToString(rng.begin)}); + } else { + prefix.Push(TextAndStyle{src.file->path}); + } + } else if (rng.begin.line > 0) { + prefix.Push(TextAndStyle{ToString(rng.begin)}); + } + + if (style_.print_severity) { + TextStyle style; + switch (diag.severity) { + case Severity::Note: + break; + case Severity::Warning: + style = style::Warning + style::Bold; + break; + case Severity::Error: + style = style::Error + style::Bold; + break; + } + prefix.Push(TextAndStyle{ToString(diag.severity), style}); + } + + for (size_t i = 0; i < prefix.Length(); i++) { + if (i > 0) { + text << " "; + } + text << prefix[i].style << prefix[i].text; + } + + if (!prefix.IsEmpty()) { + text << style::Plain(": "); + } + text << style::Bold << diag.message; + + if (style_.print_line && src.file && rng.begin.line > 0) { + text << style::Plain("\n"); + + for (size_t line_num = rng.begin.line; + (line_num <= rng.end.line) && (line_num <= src.file->content.lines.size()); + line_num++) { + auto& line = src.file->content.lines[line_num - 1]; + auto line_len = line.size(); + + bool is_ascii = true; + for (auto c : line) { + if (c == '\t') { + text.Repeat(' ', style_.tab_width); + } else { + text << c; + } + if (c & 0x80) { + is_ascii = false; + } + } + + text << style::Plain("\n"); + + // If the line contains non-ascii characters, then we cannot assume that + // a single utf8 code unit represents a single glyph, so don't attempt to + // draw squiggles. + if (!is_ascii) { + continue; + } + + text << style::Squiggle; + + // Count the number of glyphs in the line span. + // start and end use 1-based indexing. + auto num_glyphs = [&](size_t start, size_t end) { + size_t count = 0; + start = (start > 0) ? (start - 1) : 0; + end = (end > 0) ? (end - 1) : 0; + for (size_t i = start; (i < end) && (i < line_len); i++) { + count += (line[i] == '\t') ? style_.tab_width : 1; + } + return count; + }; + + if (line_num == rng.begin.line && line_num == rng.end.line) { + // Single line + text.Repeat(' ', num_glyphs(1, rng.begin.column)); + text.Repeat('^', std::max(num_glyphs(rng.begin.column, rng.end.column), 1)); + } else if (line_num == rng.begin.line) { + // Start of multi-line + text.Repeat(' ', num_glyphs(1, rng.begin.column)); + text.Repeat('^', num_glyphs(rng.begin.column, line_len + 1)); + } else if (line_num == rng.end.line) { + // End of multi-line + text.Repeat('^', num_glyphs(1, rng.end.column)); + } else { + // Middle of multi-line + text.Repeat('^', num_glyphs(1, line_len + 1)); + } + text << style::Plain("\n"); + } + } +} + +Formatter::~Formatter() = default; + +} // namespace tint::diag diff --git a/3rdparty/dawn/src/tint/utils/diagnostic/formatter.h b/3rdparty/dawn/src/tint/utils/diagnostic/formatter.h new file mode 100644 index 000000000..b744ff654 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/diagnostic/formatter.h @@ -0,0 +1,84 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_DIAGNOSTIC_FORMATTER_H_ +#define SRC_TINT_UTILS_DIAGNOSTIC_FORMATTER_H_ + +#include + +// Forward declaration +namespace tint { +class StyledTextPrinter; +class StyledText; +} // namespace tint +namespace tint::diag { +class Diagnostic; +class List; +} // namespace tint::diag + +namespace tint::diag { +/// Formatter are used to print a list of diagnostics messages. +class Formatter { + public: + /// Style controls the formatter's output style. + struct Style { + /// include the file path for each diagnostic + bool print_file = true; + /// include the severity for each diagnostic + bool print_severity = true; + /// include the source line(s) for the diagnostic + bool print_line = true; + /// print a newline at the end of a diagnostic list + bool print_newline_at_end = true; + /// width of a tab character + size_t tab_width = 2u; + }; + + /// Constructor for the formatter using a default style. + Formatter(); + + /// Constructor for the formatter using the custom style. + /// @param style the style used for the formatter. + explicit Formatter(const Style& style); + + ~Formatter(); + + /// @return the list of diagnostics `list` formatted to a string. + /// @param list the list of diagnostic messages to format + StyledText Format(const List& list) const; + + private: + struct State; + + void Format(const Diagnostic& diag, StyledText& text) const; + + const Style style_; +}; + +} // namespace tint::diag + +#endif // SRC_TINT_UTILS_DIAGNOSTIC_FORMATTER_H_ diff --git a/3rdparty/dawn/src/tint/utils/diagnostic/source.cc b/3rdparty/dawn/src/tint/utils/diagnostic/source.cc new file mode 100644 index 000000000..8b036e850 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/diagnostic/source.cc @@ -0,0 +1,216 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/diagnostic/source.h" + +#include +#include +#include + +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/unicode.h" + +namespace tint { +namespace { + +bool ParseLineBreak(std::string_view str, size_t i, bool* is_line_break, size_t* line_break_size) { + // See https://www.w3.org/TR/WGSL/#blankspace + + auto* utf8 = reinterpret_cast(&str[i]); + auto [cp, n] = tint::utf8::Decode(utf8, str.size() - i); + + if (n == 0) { + return false; + } + + static const auto kLF = tint::CodePoint(0x000A); // line feed + static const auto kVTab = tint::CodePoint(0x000B); // vertical tab + static const auto kFF = tint::CodePoint(0x000C); // form feed + static const auto kNL = tint::CodePoint(0x0085); // next line + static const auto kCR = tint::CodePoint(0x000D); // carriage return + static const auto kLS = tint::CodePoint(0x2028); // line separator + static const auto kPS = tint::CodePoint(0x2029); // parargraph separator + + if (cp == kLF || cp == kVTab || cp == kFF || cp == kNL || cp == kPS || cp == kLS) { + *is_line_break = true; + *line_break_size = n; + return true; + } + + // Handle CRLF as one line break, and CR alone as one line break + if (cp == kCR) { + *is_line_break = true; + *line_break_size = n; + + if (auto next_i = i + n; next_i < str.size()) { + auto* next_utf8 = reinterpret_cast(&str[next_i]); + auto [next_cp, next_n] = tint::utf8::Decode(next_utf8, str.size() - next_i); + + if (next_n == 0) { + return false; + } + + if (next_cp == kLF) { + // CRLF as one break + *line_break_size = n + next_n; + } + } + + return true; + } + + *is_line_break = false; + return true; +} + +std::vector SplitLines(std::string_view str) { + std::vector lines; + + size_t lineStart = 0; + for (size_t i = 0; i < str.size();) { + bool is_line_break{}; + size_t line_break_size{}; + // We don't handle decode errors from ParseLineBreak. Instead, we rely on + // the Lexer to do so. + ParseLineBreak(str, i, &is_line_break, &line_break_size); + if (is_line_break) { + lines.push_back(str.substr(lineStart, i - lineStart)); + i += line_break_size; + lineStart = i; + } else { + ++i; + } + } + if (lineStart < str.size()) { + lines.push_back(str.substr(lineStart)); + } + + return lines; +} + +std::vector CopyRelativeStringViews(const std::vector& src_list, + const std::string_view& src_view, + const std::string_view& dst_view) { + std::vector out(src_list.size()); + for (size_t i = 0; i < src_list.size(); i++) { + if (src_list[i].empty()) { + continue; + } + auto offset = static_cast(&src_list[i].front() - &src_view.front()); + auto count = src_list[i].length(); + out[i] = dst_view.substr(offset, count); + } + return out; +} + +} // namespace + +Source::FileContent::FileContent(std::string_view body) : data(body), lines(SplitLines(data)) {} + +Source::FileContent::FileContent(const FileContent& rhs) + : data(rhs.data), lines(CopyRelativeStringViews(rhs.lines, rhs.data, data)) {} + +Source::FileContent::~FileContent() = default; + +Source::File::~File() = default; + +std::string ToString(const Source& source) { + StringStream out; + + auto rng = source.range; + + if (source.file) { + out << source.file->path << ":"; + } + if (rng.begin.line) { + out << rng.begin.line << ":"; + if (rng.begin.column) { + out << rng.begin.column; + } + + if (source.file) { + out << "\n\n"; + + auto repeat = [&](char c, size_t n) { + while (n--) { + out << c; + } + }; + + for (size_t line = rng.begin.line; line <= rng.end.line; line++) { + if (line < source.file->content.lines.size() + 1) { + auto len = source.file->content.lines[line - 1].size(); + + out << source.file->content.lines[line - 1] << "\n"; + + if (line == rng.begin.line && line == rng.end.line) { + // Single line + repeat(' ', rng.begin.column - 1); + repeat('^', std::max(rng.end.column - rng.begin.column, 1)); + } else if (line == rng.begin.line) { + // Start of multi-line + repeat(' ', rng.begin.column - 1); + repeat('^', len - (rng.begin.column - 1)); + } else if (line == rng.end.line) { + // End of multi-line + repeat('^', rng.end.column - 1); + } else { + // Middle of multi-line + repeat('^', len); + } + + out << "\n"; + } + } + } + } + return out.str(); +} + +size_t Source::Range::Length(const FileContent& content) const { + TINT_ASSERT(begin <= end); + TINT_ASSERT(begin.column > 0); + TINT_ASSERT(begin.line > 0); + TINT_ASSERT(end.line <= 1 + content.lines.size()); + TINT_ASSERT(end.column <= 1 + content.lines[end.line - 1].size()); + + if (end.line == begin.line) { + return end.column - begin.column; + } + + size_t len = (content.lines[begin.line - 1].size() + 1 - begin.column) + // first line + (end.column - 1) + // last line + end.line - begin.line; // newlines + + for (size_t line = begin.line + 1; line < end.line; line++) { + len += content.lines[line - 1].size(); // whole-lines + } + return len; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/diagnostic/source.h b/3rdparty/dawn/src/tint/utils/diagnostic/source.h new file mode 100644 index 000000000..4747dddd2 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/diagnostic/source.h @@ -0,0 +1,283 @@ + +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_DIAGNOSTIC_SOURCE_H_ +#define SRC_TINT_UTILS_DIAGNOSTIC_SOURCE_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/rtti/traits.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint { + +/// Source describes a range of characters within a source file. +class Source { + public: + /// FileContent describes the content of a source file encoded using UTF-8. + class FileContent { + public: + /// Constructs the FileContent with the given file content. + /// @param data the file contents + explicit FileContent(std::string_view data); + + /// Copy constructor + /// @param rhs the FileContent to copy + FileContent(const FileContent& rhs); + + /// Destructor + ~FileContent(); + + /// The original un-split file content + const std::string data; + /// #data split by lines + const std::vector lines; + }; + + /// File describes a source file, including path and content. + class File { + public: + /// Constructs the File with the given file path and content. + /// @param p the path for this file + /// @param c the file contents + inline File(const std::string& p, std::string_view c) : path(p), content(c) {} + + /// Copy constructor + File(const File&) = default; + + /// Move constructor + File(File&&) = default; + + /// Destructor + ~File(); + + /// file path + const std::string path; + /// file content + const FileContent content; + }; + + /// Location holds a 1-based line and column index. + class Location { + public: + /// the 1-based line number. 0 represents no line information. + uint32_t line = 0; + /// the 1-based column number in utf8-code units (bytes). + /// 0 represents no column information. + uint32_t column = 0; + + /// Returns true if `this` location is lexicographically less than `rhs` + /// @param rhs location to compare against + /// @returns true if `this` < `rhs` + inline bool operator<(const Source::Location& rhs) const { + return std::tie(line, column) < std::tie(rhs.line, rhs.column); + } + + /// Returns true if `this` location is lexicographically less than or equal to `rhs` + /// @param rhs location to compare against + /// @returns true if `this` <= `rhs` + inline bool operator<=(const Source::Location& rhs) const { + return std::tie(line, column) <= std::tie(rhs.line, rhs.column); + } + + /// Returns true if `this` location is lexicographically greater than `rhs` + /// @param rhs location to compare against + /// @returns true if `this` > `rhs` + inline bool operator>(const Source::Location& rhs) const { + return std::tie(line, column) > std::tie(rhs.line, rhs.column); + } + + /// Returns true if `this` location is lexicographically greater than or equal to `rhs` + /// @param rhs location to compare against + /// @returns true if `this` >= `rhs` + inline bool operator>=(const Source::Location& rhs) const { + return std::tie(line, column) >= std::tie(rhs.line, rhs.column); + } + + /// Returns true of `this` location is equal to `rhs` + /// @param rhs location to compare against + /// @returns true if `this` == `rhs` + inline bool operator==(const Location& rhs) const { + return line == rhs.line && column == rhs.column; + } + + /// Returns true of `this` location is not equal to `rhs` + /// @param rhs location to compare against + /// @returns true if `this` != `rhs` + inline bool operator!=(const Location& rhs) const { return !(*this == rhs); } + }; + + /// Range holds a Location interval described by [begin, end). + class Range { + public: + /// Constructs a zero initialized Range. + inline Range() = default; + + /// Constructs a zero-length Range starting at `loc` + /// @param loc the start and end location for the range + inline constexpr explicit Range(const Location& loc) : begin(loc), end(loc) {} + + /// Constructs the Range beginning at `b` and ending at `e` + /// @param b the range start location + /// @param e the range end location + inline constexpr Range(const Location& b, const Location& e) : begin(b), end(e) {} + + /// Return a column-shifted Range + /// @param n the number of UTF-8 codepoint to shift by + /// @returns a Range with a #begin and #end column shifted by `n` + inline Range operator+(uint32_t n) const { + return Range{{begin.line, begin.column + n}, {end.line, end.column + n}}; + } + + /// Returns true of `this` range is not equal to `rhs` + /// @param rhs range to compare against + /// @returns true if `this` != `rhs` + inline bool operator==(const Range& rhs) const { + return begin == rhs.begin && end == rhs.end; + } + + /// Returns true of `this` range is equal to `rhs` + /// @param rhs range to compare against + /// @returns true if `this` == `rhs` + inline bool operator!=(const Range& rhs) const { return !(*this == rhs); } + + /// @param content the file content that this range belongs to + /// @returns the length of the range in UTF-8 codepoints, treating all line-break sequences + /// as a single code-point. + /// @see https://www.w3.org/TR/WGSL/#blankspace-and-line-breaks for the definition of a line + /// break. + size_t Length(const FileContent& content) const; + + /// The location of the first UTF-8 codepoint in the range. + Location begin; + /// The location of one-past the last UTF-8 codepoint in the range. + Location end; + }; + + /// Constructs the Source with an zero initialized Range and null File. + inline Source() : range() {} + + /// Constructs the Source with the Range `rng` and a null File + /// @param rng the source range + inline explicit Source(const Range& rng) : range(rng) {} + + /// Constructs the Source with the Range `loc` and a null File + /// @param loc the start and end location for the source range + inline explicit Source(const Location& loc) : range(Range(loc)) {} + + /// Constructs the Source with the Range `rng` and File `file` + /// @param rng the source range + /// @param f the source file + inline Source(const Range& rng, File const* f) : range(rng), file(f) {} + + /// @returns a Source that points to the begin range of this Source. + inline Source Begin() const { return Source(Range{range.begin}, file); } + + /// @returns a Source that points to the end range of this Source. + inline Source End() const { return Source(Range{range.end}, file); } + + /// Return a column-shifted Source + /// @param n the number of characters to shift by + /// @returns a Source with the range's columns shifted by `n` + inline Source operator+(uint32_t n) const { return Source(range + n, file); } + + /// Returns true of `this` Source is lexicographically less than `rhs` + /// @param rhs source to compare against + /// @returns true if `this` < `rhs` + inline bool operator<(const Source& rhs) { + if (file != rhs.file) { + return false; + } + return range.begin < rhs.range.begin; + } + + /// Helper function that returns the range union of two source locations. The + /// `start` and `end` locations are assumed to refer to the same source file. + /// @param start the start source of the range + /// @param end the end source of the range + /// @returns the combined source + inline static Source Combine(const Source& start, const Source& end) { + return Source(Source::Range(start.range.begin, end.range.end), start.file); + } + + /// range is the span of text this source refers to in #file + Range range; + /// file is the optional source content this source refers to + const File* file = nullptr; +}; + +/// @param source the input Source +/// @returns a string that describes given source location +std::string ToString(const Source& source); + +/// Writes the Source::Location to the stream. +/// @param out the stream to write to +/// @param loc the location to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Source::Location& loc) { + return out << loc.line << ":" << loc.column; +} + +/// Writes the Source::Range to the stream. +/// @param out the stream to write to +/// @param range the range to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Source::Range& range) { + return out << "[" << range.begin << ", " << range.end << "]"; +} + +/// Writes the Source to the stream. +/// @param out the stream to write to +/// @param source the source to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Source& source) { + return out << ToString(source); +} + +/// Writes the Source::FileContent to the stream. +/// @param out the stream to write to +/// @param content the file content to write +/// @returns out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Source::FileContent& content) { + return out << content.data; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_DIAGNOSTIC_SOURCE_H_ diff --git a/3rdparty/dawn/src/tint/utils/ice/debugger.cc b/3rdparty/dawn/src/tint/utils/ice/debugger.cc new file mode 100644 index 000000000..73fd28c55 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/ice/debugger.cc @@ -0,0 +1,75 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/ice/debugger.h" + +#ifdef TINT_ENABLE_BREAK_IN_DEBUGGER + +#ifdef _MSC_VER +#include +#elif defined(__linux__) +#include +#include +#include +#endif + +#ifdef _MSC_VER +#define TINT_DEBUGGER_BREAK_DEFINED +void tint::debugger::Break() { + if (::IsDebuggerPresent()) { + ::DebugBreak(); + } +} + +#elif defined(__linux__) + +#define TINT_DEBUGGER_BREAK_DEFINED +void tint::debugger::Break() { + // A process is being traced (debugged) if "/proc/self/status" contains a + // line with "TracerPid: ...". + bool is_traced = false; + std::ifstream fin("/proc/self/status"); + std::string line; + while (!is_traced && std::getline(fin, line)) { + const char kPrefix[] = "TracerPid:\t"; + static constexpr int kPrefixLen = sizeof(kPrefix) - 1; + if (line.length() > kPrefixLen && line.compare(0, kPrefixLen, kPrefix) == 0) { + is_traced = line[kPrefixLen] != '0'; + } + } + + if (is_traced) { + raise(SIGTRAP); + } +} +#endif // platform + +#endif // TINT_ENABLE_BREAK_IN_DEBUGGER + +#ifndef TINT_DEBUGGER_BREAK_DEFINED +void tint::debugger::Break() {} +#endif diff --git a/3rdparty/dawn/src/tint/utils/ice/debugger.h b/3rdparty/dawn/src/tint/utils/ice/debugger.h new file mode 100644 index 000000000..55708fd33 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/ice/debugger.h @@ -0,0 +1,40 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_ICE_DEBUGGER_H_ +#define SRC_TINT_UTILS_ICE_DEBUGGER_H_ + +namespace tint::debugger { + +/// If debugger is attached and the `TINT_ENABLE_BREAK_IN_DEBUGGER` preprocessor +/// macro is defined for `debugger.cc`, calling `Break()` will cause the +/// debugger to break at the call site. +void Break(); + +} // namespace tint::debugger + +#endif // SRC_TINT_UTILS_ICE_DEBUGGER_H_ diff --git a/3rdparty/dawn/src/tint/utils/ice/ice.cc b/3rdparty/dawn/src/tint/utils/ice/ice.cc new file mode 100644 index 000000000..6649ca3bc --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/ice/ice.cc @@ -0,0 +1,81 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/ice/ice.h" + +#include +#include +#include + +#include "src/tint/utils/ice/debugger.h" +#include "src/tint/utils/macros/compiler.h" + +namespace tint { + +InternalCompilerError::InternalCompilerError(const char* file, + size_t line, + InternalCompilerErrorCallback callback) + : file_(file), line_(line), callback_info_(callback) {} + +TINT_BEGIN_DISABLE_WARNING(DESTRUCTOR_NEVER_RETURNS); +InternalCompilerError::~InternalCompilerError() { + std::ostringstream err; + err << Error(); + err << R"( + +******************************************************************** +* The tint shader compiler has encountered an unexpected error. * +* * +* Please help us fix this issue by submitting a bug report at * +* crbug.com/tint with the source program that triggered the bug. * +******************************************************************** +)"; + + // When consuming the ICE, log the error message and never return. + // Default to stderr unless an ICE callback is provided. + if (callback_info_ && callback_info_->callback) { + callback_info_->callback(err.str(), callback_info_->userdata); + } else { + std::cerr << err.str(); + } + + debugger::Break(); + +#if defined(_MSC_VER) && !defined(__clang__) + abort(); +#else + __builtin_trap(); +#endif +} +TINT_END_DISABLE_WARNING(DESTRUCTOR_NEVER_RETURNS); + +std::string InternalCompilerError::Error() const { + return std::string(File()) + ":" + std::to_string(Line()) + + " internal compiler error: " + Message(); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/ice/ice.h b/3rdparty/dawn/src/tint/utils/ice/ice.h new file mode 100644 index 000000000..a6fb44df1 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/ice/ice.h @@ -0,0 +1,128 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_ICE_ICE_H_ +#define SRC_TINT_UTILS_ICE_ICE_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/macros/compiler.h" + +namespace tint { + +/// An instance of InternalCompilerErrorCallbackInfo can be used to set up a callback so that the +/// user of Tint can capture an ICE message before crashing. +struct InternalCompilerErrorCallbackInfo { + void (*callback)(std::string err, void* userdata) = nullptr; + void* userdata = nullptr; +}; +using InternalCompilerErrorCallback = std::optional; + +/// InternalCompilerError is a helper for reporting internal compiler errors. +/// Construct the InternalCompilerError with the source location of the ICE fault and append any +/// error details with the `<<` operator. When the InternalCompilerError is destructed, the +/// concatenated error message is passed to the provided ICE callback, or printed to stderr. +class InternalCompilerError { + public: + /// Constructor + /// @param file the file containing the ICE + /// @param line the line containing the ICE + /// @param callback an optional callback to call with the error message + InternalCompilerError(const char* file, + size_t line, + InternalCompilerErrorCallback callback = std::nullopt); + + /// Destructor. + /// Adds the internal compiler error message to the diagnostics list, calls the + /// InternalCompilerErrorReporter if one is set, then terminates the process. + [[noreturn]] ~InternalCompilerError(); + + /// Appends `arg` to the ICE message. + /// @param arg the argument to append to the ICE message + /// @returns this object so calls can be chained + template + InternalCompilerError& operator<<(T&& arg) { + msg_ << std::forward(arg); + return *this; + } + + /// @returns the file that triggered the ICE + const char* File() const { return file_; } + + /// @returns the line that triggered the ICE + size_t Line() const { return line_; } + + /// @returns the ICE message + std::string Message() const { return msg_.str(); } + + /// @returns the ICE file, line and message + std::string Error() const; + + /// This operator overload exists so that we can use an InternalCompilerError object on the + /// right-hand side of a short-circuiting operator, which is how the TINT_ASSERT macro works. + operator bool() const { return false; } + + private: + InternalCompilerError(const InternalCompilerError&) = delete; + InternalCompilerError(InternalCompilerError&&) = delete; + + char const* const file_; + const size_t line_; + std::stringstream msg_; + const InternalCompilerErrorCallback callback_info_; +}; + +} // namespace tint + +/// TINT_ICE() is a macro to produce an Internal Compiler Error. The ICE message contains the +/// callsite's file and line. Use the `<<` operator to append an error message to the ICE. An +/// optional callback can be provided so that the user of Tint can capture the ICE before crashing. +#define TINT_ICE(...) tint::InternalCompilerError(__FILE__, __LINE__ __VA_OPT__(, __VA_ARGS__)) + +/// TINT_UNREACHABLE() is a macro produce an Internal Compiler Error when an expectedly unreachable +/// statement is reached. The ICE message contains the callsite's file and line. Use the `<<` +/// operator to append an error message to the ICE. An optional callback can be provided so that the +/// user of Tint can capture the ICE before crashing. +#define TINT_UNREACHABLE(...) TINT_ICE(__VA_ARGS__) << "TINT_UNREACHABLE " + +/// TINT_UNIMPLEMENTED() is a macro to produce an Internal Compiler Error when an unimplemented +/// codepath is executed. The ICE message contains the callsite's file and line. Use the `<<` +/// operator to append an error message to the ICE. An optional callback can be provided so that the +/// user of Tint can capture the ICE before crashing. +#define TINT_UNIMPLEMENTED(...) TINT_ICE(__VA_ARGS__) << "TINT_UNIMPLEMENTED " + +/// TINT_ASSERT() is a macro for checking the expression is true, triggering a TINT_ICE if it is +/// not. The ICE message contains the callsite's file and line. Use the `<<` operator to append an +/// error message to the ICE. An optional callback can be provided so that the user of Tint can +/// capture the ICE before crashing. +#define TINT_ASSERT(condition, ...) \ + DAWN_LIKELY((condition)) || TINT_ICE(__VA_ARGS__) << "TINT_ASSERT(" #condition ") " + +#endif // SRC_TINT_UTILS_ICE_ICE_H_ diff --git a/3rdparty/dawn/src/tint/utils/internal_limits.h b/3rdparty/dawn/src/tint/utils/internal_limits.h new file mode 100644 index 000000000..005d21cdd --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/internal_limits.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_INTERNAL_LIMITS_H_ +#define SRC_TINT_UTILS_INTERNAL_LIMITS_H_ + +#include +#include + +// Contains constants for internal limits used within Tint. These limits are not specified in the +// WGSL spec, but are practical heuristics to limit certain operations that are known to cause +// memory or runtime issues, i.e. creation of arrays with 100k elements that cause IR binary +// decoding to take pathologically long times to run. + +namespace tint::internal_limits { + +// Limits the number of elements appearing in the constructor for an array +constexpr size_t kMaxArrayConstructorElements = 32767; + +// Limits the number of elements in an array type +constexpr int64_t kMaxArrayElementCount = 65536; + +// The max subgroup size supported. Used in validation. +constexpr int64_t kMaxSubgroupSize = 128; + +// A quad (fragment) is composed of four invocations. +constexpr int64_t kQuadSize = 4; + +// A @size attribute maximum size +constexpr int64_t kMaxStructMemberPadding = 10 * 1024 * 1024; + +} // namespace tint::internal_limits + +#endif // SRC_TINT_UTILS_INTERNAL_LIMITS_H_ diff --git a/3rdparty/dawn/src/tint/utils/macros/compiler.h b/3rdparty/dawn/src/tint/utils/macros/compiler.h new file mode 100644 index 000000000..79d0509b7 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/compiler.h @@ -0,0 +1,307 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/macros/concat.h" +#include "src/utils/compiler.h" + +#ifndef SRC_TINT_UTILS_MACROS_COMPILER_H_ +#define SRC_TINT_UTILS_MACROS_COMPILER_H_ + +#define TINT_REQUIRE_SEMICOLON static_assert(true) + +#if defined(_MSC_VER) && !defined(__clang__) +//////////////////////////////////////////////////////////////////////////////// +// MSVC +//////////////////////////////////////////////////////////////////////////////// +#define TINT_BUILD_IS_MSVC 1 +#define TINT_DISABLE_WARNING_CONSTANT_OVERFLOW __pragma(warning(disable : 4756)) +#define TINT_DISABLE_WARNING_DEPRECATED __pragma(warning(disable : 4996)) +#define TINT_DISABLE_WARNING_DESTRUCTOR_NEVER_RETURNS __pragma(warning(disable : 4722)) +#define TINT_DISABLE_WARNING_EXTRA_SEMICOLON /* currently no-op */ +#define TINT_DISABLE_WARNING_FLOAT_EQUAL /* currently no-op */ +#define TINT_DISABLE_WARNING_MAYBE_UNINITIALIZED __pragma(warning(disable : 4701)) +#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE /* currently no-op */ +#define TINT_DISABLE_WARNING_NEWLINE_EOF /* currently no-op */ +#define TINT_DISABLE_WARNING_OLD_STYLE_CAST /* currently no-op */ +#define TINT_DISABLE_WARNING_PEDANTIC /* currently no-op */ +#define TINT_DISABLE_WARNING_REDUNDANT_PARENS /* currently no-op */ +#define TINT_DISABLE_WARNING_RESERVED_IDENTIFIER /* currently no-op */ +#define TINT_DISABLE_WARNING_RESERVED_MACRO_IDENTIFIER /* currently no-op */ +#define TINT_DISABLE_WARNING_SHADOW_FIELD_IN_CONSTRUCTOR /* currently no-op */ +#define TINT_DISABLE_WARNING_SIGN_CONVERSION /* currently no-op */ +#define TINT_DISABLE_WARNING_UNDEFINED_REINTERPRET_CAST /* currently no-op */ +#define TINT_DISABLE_WARNING_UNREACHABLE_CODE __pragma(warning(disable : 4702)) +#define TINT_DISABLE_WARNING_UNSAFE_BUFFER_USAGE /* currently no-op */ +#define TINT_DISABLE_WARNING_UNUSED_PARAMETER __pragma(warning(disable : 4100)) +#define TINT_DISABLE_WARNING_UNSUED_VARIABLE __pragma(warning(disable : 4189)) +#define TINT_DISABLE_WARNING_UNUSED_VALUE /* currently no-op */ +#define TINT_DISABLE_WARNING_WEAK_VTABLES /* currently no-op */ +#define TINT_DISABLE_WARNING_ZERO_AS_NULLPTR /* currently no-op */ + +#define TINT_BEGIN_DISABLE_OPTIMIZATIONS() __pragma(optimize("", off)) TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_OPTIMIZATIONS() __pragma(optimize("", on)) TINT_REQUIRE_SEMICOLON + +#define TINT_BEGIN_DISABLE_ALL_WARNINGS() __pragma(warning(push, 0)) TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_ALL_WARNINGS() __pragma(warning(pop)) TINT_REQUIRE_SEMICOLON + +// clang-format off +#define TINT_BEGIN_DISABLE_WARNING(name) \ + __pragma(warning(push)) \ + TINT_CONCAT(TINT_DISABLE_WARNING_, name) \ + TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_WARNING(name) \ + __pragma(warning(pop)) \ + TINT_REQUIRE_SEMICOLON + +#define TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS() \ + __pragma(warning(push)) \ + TINT_DISABLE_WARNING_UNUSED_PARAMETER \ + TINT_DISABLE_WARNING_UNSUED_VARIABLE \ + TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_PROTOBUF_WARNINGS() \ + __pragma(warning(pop)) \ + TINT_REQUIRE_SEMICOLON +// clang-format on + +#elif defined(__clang__) +//////////////////////////////////////////////////////////////////////////////// +// Clang +//////////////////////////////////////////////////////////////////////////////// +#define TINT_BUILD_IS_CLANG 1 +#define TINT_DISABLE_WARNING_ALL _Pragma("clang diagnostic ignored \"-Wall\"") +#define TINT_DISABLE_WARNING_CONSTANT_OVERFLOW /* currently no-op */ +#define TINT_DISABLE_WARNING_DEPRECATED /* currently no-op */ +#define TINT_DISABLE_WARNING_DESTRUCTOR_NEVER_RETURNS /* currently no-op */ +#define TINT_DISABLE_WARNING_COVERED_SWITCH_DEFAULT \ + _Pragma("clang diagnostic ignored \"-Wcovered-switch-default\"") +#define TINT_DISABLE_WARNING_DEPRECATED_REDUNDANT_CONSTEXPR_STATIC_DEF \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-redundant-constexpr-static-def\"") +#define TINT_DISABLE_WARNING_DOUBLE_PROMOTION \ + _Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") +#define TINT_DISABLE_WARNING_EVERYTHING _Pragma("clang diagnostic ignored \"-Weverything\"") +#define TINT_DISABLE_WARNING_EXTRA _Pragma("clang diagnostic ignored \"-Wextra\"") +#define TINT_DISABLE_WARNING_EXTRA_SEMICOLON \ + _Pragma("clang diagnostic ignored \"-Wextra-semi-stmt\"") +#define TINT_DISABLE_WARNING_FLOAT_EQUAL _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") +#define TINT_DISABLE_WARNING_MAYBE_UNINITIALIZED \ + _Pragma("clang diagnostic ignored \"-Wconditional-uninitialized\"") +#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE \ + _Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"") \ + _Pragma("clang diagnostic ignored \"-Winconsistent-missing-destructor-override\"") +#define TINT_DISABLE_WARNING_NEWLINE_EOF _Pragma("clang diagnostic ignored \"-Wnewline-eof\"") +#define TINT_DISABLE_WARNING_OLD_STYLE_CAST _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") +#define TINT_DISABLE_WARNING_PEDANTIC /* currently no-op */ +#define TINT_DISABLE_WARNING_REDUNDANT_PARENS \ + _Pragma("clang diagnostic ignored \"-Wredundant-parens\"") +#define TINT_DISABLE_WARNING_RESERVED_IDENTIFIER \ + _Pragma("clang diagnostic ignored \"-Wreserved-identifier\"") +#define TINT_DISABLE_WARNING_RESERVED_MACRO_IDENTIFIER \ + _Pragma("clang diagnostic ignored \"-Wreserved-macro-identifier\"") \ + _Pragma("clang diagnostic ignored \"-Wreserved-id-macro\"") +#define TINT_DISABLE_WARNING_SHADOW_FIELD_IN_CONSTRUCTOR \ + _Pragma("clang diagnostic ignored \"-Wshadow-field-in-constructor\"") +#define TINT_DISABLE_WARNING_SIGN_CONVERSION \ + _Pragma("clang diagnostic ignored \"-Wsign-conversion\"") +#define TINT_DISABLE_WARNING_THREAD_SAFETY_NEGATIVE \ + _Pragma("clang diagnostic ignored \"-Wthread-safety-negative\"") +#define TINT_DISABLE_WARNING_UNDEFINED_REINTERPRET_CAST \ + _Pragma("clang diagnostic ignored \"-Wundefined-reinterpret-cast\"") +#define TINT_DISABLE_WARNING_UNREACHABLE_CODE /* currently no-op */ +#define TINT_DISABLE_WARNING_UNSAFE_BUFFER_USAGE \ + _Pragma("clang diagnostic ignored \"-Wunsafe-buffer-usage\"") +#define TINT_DISABLE_WARNING_UNUSED_PARAMETER \ + _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") +#define TINT_DISABLE_WARNING_UNUSED_VALUE _Pragma("clang diagnostic ignored \"-Wunused-value\"") +#define TINT_DISABLE_WARNING_WEAK_VTABLES _Pragma("clang diagnostic ignored \"-Wweak-vtables\"") +#define TINT_DISABLE_WARNING_ZERO_AS_NULLPTR \ + _Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"") + +// clang-format off +#define TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS() \ + _Pragma("clang diagnostic push") \ + TINT_DISABLE_WARNING_ALL \ + TINT_DISABLE_WARNING_EXTRA \ + TINT_DISABLE_WARNING_EVERYTHING \ + TINT_DISABLE_WARNING_UNSAFE_BUFFER_USAGE \ + TINT_REQUIRE_SEMICOLON + +#define TINT_END_DISABLE_PROTOBUF_WARNINGS() \ + _Pragma("clang diagnostic pop") \ + TINT_REQUIRE_SEMICOLON + +#define TINT_BEGIN_DISABLE_OPTIMIZATIONS() /* currently no-op */ TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_OPTIMIZATIONS() /* currently no-op */ TINT_REQUIRE_SEMICOLON + +#define TINT_BEGIN_DISABLE_ALL_WARNINGS() \ + _Pragma("clang diagnostic push") \ + TINT_DISABLE_WARNING_EVERYTHING \ + TINT_DISABLE_WARNING_UNSAFE_BUFFER_USAGE \ + TINT_REQUIRE_SEMICOLON + +#define TINT_END_DISABLE_ALL_WARNINGS() \ + _Pragma("clang diagnostic pop") \ + TINT_REQUIRE_SEMICOLON + +#define TINT_BEGIN_DISABLE_WARNING(name) \ + _Pragma("clang diagnostic push") \ + TINT_CONCAT(TINT_DISABLE_WARNING_, name) \ + TINT_REQUIRE_SEMICOLON + +#define TINT_END_DISABLE_WARNING(name) \ + _Pragma("clang diagnostic pop") \ + TINT_REQUIRE_SEMICOLON +// clang-format on + +#elif defined(__GNUC__) +//////////////////////////////////////////////////////////////////////////////// +// GCC +//////////////////////////////////////////////////////////////////////////////// +#define TINT_BUILD_IS_GCC 1 +#define TINT_DISABLE_WARNING_CONSTANT_OVERFLOW /* currently no-op */ +#define TINT_DISABLE_WARNING_DEPRECATED /* currently no-op */ +#define TINT_DISABLE_WARNING_DESTRUCTOR_NEVER_RETURNS /* currently no-op */ +#define TINT_DISABLE_WARNING_EXTRA_SEMICOLON /* currently no-op */ +#define TINT_DISABLE_WARNING_FLOAT_EQUAL /* currently no-op */ +#define TINT_DISABLE_WARNING_MAYBE_UNINITIALIZED \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE /* currently no-op */ +#define TINT_DISABLE_WARNING_NEWLINE_EOF /* currently no-op */ +#define TINT_DISABLE_WARNING_OLD_STYLE_CAST /* currently no-op */ +#define TINT_DISABLE_WARNING_PEDANTIC _Pragma("GCC diagnostic ignored \"-Wpedantic\"") +#define TINT_DISABLE_WARNING_REDUNDANT_PARENS /* currently no-op */ +#define TINT_DISABLE_WARNING_RESERVED_IDENTIFIER /* currently no-op */ +#define TINT_DISABLE_WARNING_RESERVED_MACRO_IDENTIFIER /* currently no-op */ +#define TINT_DISABLE_WARNING_SHADOW_FIELD_IN_CONSTRUCTOR /* currently no-op */ +#define TINT_DISABLE_WARNING_SIGN_CONVERSION /* currently no-op */ +#define TINT_DISABLE_WARNING_UNDEFINED_REINTERPRET_CAST /* currently no-op */ +#define TINT_DISABLE_WARNING_UNREACHABLE_CODE /* currently no-op */ +#define TINT_DISABLE_WARNING_UNSAFE_BUFFER_USAGE /* currently no-op */ +#define TINT_DISABLE_WARNING_UNUSED_PARAMETER \ + _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") +#define TINT_DISABLE_WARNING_UNUSED_VALUE _Pragma("GCC diagnostic ignored \"-Wunused-value\"") +#define TINT_DISABLE_WARNING_WEAK_VTABLES /* currently no-op */ +#define TINT_DISABLE_WARNING_ZERO_AS_NULLPTR /* currently no-op */ + +// clang-format off +#define TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS() \ + _Pragma("GCC diagnostic push") \ + TINT_DISABLE_WARNING_UNUSED_PARAMETER \ + TINT_DISABLE_WARNING_PEDANTIC \ + TINT_REQUIRE_SEMICOLON + +#define TINT_END_DISABLE_PROTOBUF_WARNINGS() \ + _Pragma("GCC diagnostic pop") \ + TINT_REQUIRE_SEMICOLON +// clang-format on + +#define TINT_BEGIN_DISABLE_OPTIMIZATIONS() /* currently no-op */ TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_OPTIMIZATIONS() /* currently no-op */ TINT_REQUIRE_SEMICOLON + +// clang-format off +#define TINT_BEGIN_DISABLE_ALL_WARNINGS() \ + _Pragma("GCC diagnostic push") \ + TINT_DISABLE_WARNING_CONSTANT_OVERFLOW \ + TINT_DISABLE_WARNING_MAYBE_UNINITIALIZED \ + TINT_DISABLE_WARNING_NEWLINE_EOF \ + TINT_DISABLE_WARNING_OLD_STYLE_CAST \ + TINT_DISABLE_WARNING_PEDANTIC \ + TINT_DISABLE_WARNING_SIGN_CONVERSION \ + TINT_DISABLE_WARNING_UNREACHABLE_CODE \ + TINT_DISABLE_WARNING_WEAK_VTABLES \ + TINT_DISABLE_WARNING_FLOAT_EQUAL \ + TINT_DISABLE_WARNING_DEPRECATED \ + TINT_DISABLE_WARNING_REDUNDANT_PARENS \ + TINT_DISABLE_WARNING_RESERVED_IDENTIFIER \ + TINT_DISABLE_WARNING_RESERVED_MACRO_IDENTIFIER \ + TINT_DISABLE_WARNING_UNUSED_VALUE \ + TINT_DISABLE_WARNING_UNUSED_PARAMETER \ + TINT_DISABLE_WARNING_SHADOW_FIELD_IN_CONSTRUCTOR \ + TINT_DISABLE_WARNING_EXTRA_SEMICOLON \ + TINT_DISABLE_WARNING_ZERO_AS_NULLPTR \ + TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE \ + TINT_DISABLE_WARNING_UNSAFE_BUFFER_USAGE \ + TINT_REQUIRE_SEMICOLON +// clang-format on + +#define TINT_END_DISABLE_ALL_WARNINGS() _Pragma("GCC diagnostic pop") TINT_REQUIRE_SEMICOLON + +// clang-format off +#define TINT_BEGIN_DISABLE_WARNING(name) \ + _Pragma("GCC diagnostic push") \ + TINT_CONCAT(TINT_DISABLE_WARNING_, name) \ + TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_WARNING(name) \ + _Pragma("GCC diagnostic pop") \ + TINT_REQUIRE_SEMICOLON +// clang-format on + +#else +//////////////////////////////////////////////////////////////////////////////// +// Other +//////////////////////////////////////////////////////////////////////////////// +#define TINT_BEGIN_DISABLE_OPTIMIZATIONS() TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_OPTIMIZATIONS() TINT_REQUIRE_SEMICOLON +#define TINT_BEGIN_DISABLE_ALL_WARNINGS() TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_ALL_WARNINGS TINT_REQUIRE_SEMICOLON +#define TINT_BEGIN_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON +#define TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS() TINT_REQUIRE_SEMICOLON +#define TINT_END_DISABLE_PROTOBUF_WARNINGS() TINT_REQUIRE_SEMICOLON + +#endif + +#ifndef TINT_BUILD_IS_MSVC +#define TINT_BUILD_IS_MSVC 0 +#endif + +#ifndef TINT_BUILD_IS_CLANG +#define TINT_BUILD_IS_CLANG 0 +#endif + +#ifndef TINT_BUILD_IS_GCC +#define TINT_BUILD_IS_GCC 0 +#endif + +#if TINT_BUILD_IS_MSVC +#define TINT_MSVC_ONLY(x) x +#else +#define TINT_MSVC_ONLY(x) +#endif + +#if TINT_BUILD_IS_CLANG +#define TINT_CLANG_ONLY(x) x +#else +#define TINT_CLANG_ONLY(x) +#endif + +#if TINT_BUILD_IS_GCC +#define TINT_GCC_ONLY(x) x +#else +#define TINT_GCC_ONLY(x) +#endif + +#endif // SRC_TINT_UTILS_MACROS_COMPILER_H_ diff --git a/3rdparty/dawn/src/tint/utils/macros/concat.h b/3rdparty/dawn/src/tint/utils/macros/concat.h new file mode 100644 index 000000000..458ba1a2a --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/concat.h @@ -0,0 +1,35 @@ + +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MACROS_CONCAT_H_ +#define SRC_TINT_UTILS_MACROS_CONCAT_H_ + +#define TINT_CONCAT_2(a, b) a##b +#define TINT_CONCAT(a, b) TINT_CONCAT_2(a, b) + +#endif // SRC_TINT_UTILS_MACROS_CONCAT_H_ diff --git a/3rdparty/dawn/src/tint/utils/macros/defer.h b/3rdparty/dawn/src/tint/utils/macros/defer.h new file mode 100644 index 000000000..6a7d44be8 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/defer.h @@ -0,0 +1,73 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MACROS_DEFER_H_ +#define SRC_TINT_UTILS_MACROS_DEFER_H_ + +#include + +#include "src/tint/utils/macros/concat.h" + +namespace tint { + +/// Defer executes a function or function like object when it is destructed. +template +class Defer { + public: + /// Constructor + /// @param f the function to call when the Defer is destructed + explicit Defer(F&& f) : f_(std::move(f)) {} + + /// Move constructor + Defer(Defer&&) = default; + + /// Destructor + /// Calls the deferred function + ~Defer() { f_(); } + + private: + Defer(const Defer&) = delete; + Defer& operator=(const Defer&) = delete; + + F f_; +}; + +/// Constructor +/// @param f the function to call when the Defer is destructed +/// @return the defer object +template +inline Defer MakeDefer(F&& f) { + return Defer(std::forward(f)); +} + +} // namespace tint + +/// TINT_DEFER(S) executes the statement(s) `S` when exiting the current lexical +/// scope. +#define TINT_DEFER(S) auto TINT_CONCAT(tint_defer_, __COUNTER__) = ::tint::MakeDefer([&] { S; }) + +#endif // SRC_TINT_UTILS_MACROS_DEFER_H_ diff --git a/3rdparty/dawn/src/tint/utils/macros/foreach.h b/3rdparty/dawn/src/tint/utils/macros/foreach.h new file mode 100644 index 000000000..acb044249 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/foreach.h @@ -0,0 +1,521 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MACROS_FOREACH_H_ +#define SRC_TINT_UTILS_MACROS_FOREACH_H_ + +// Macro magic to perform macro variadic dispatch. +// See: +// https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/count-arguments +// Note, this doesn't attempt to use the ##__VA_ARGS__ trick to handle 0 + +// Helper macro to force expanding __VA_ARGS__ to satisfy MSVC compiler. +#define TINT_MSVC_EXPAND_BUG(X) X + +/// TINT_COUNT_ARGUMENTS_NTH_ARG is used by TINT_COUNT_ARGUMENTS to get the number of arguments in a +/// variadic macro call. +#define TINT_COUNT_ARGUMENTS_NTH_ARG( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, \ + _59, _60, _61, _62, _63, _64, N, ...) \ + N + +/// TINT_COUNT_ARGUMENTS evaluates to the number of arguments passed to the macro +#define TINT_COUNT_ARGUMENTS(...) \ + TINT_MSVC_EXPAND_BUG(TINT_COUNT_ARGUMENTS_NTH_ARG( \ + __VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, \ + 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, \ + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) + +// Correctness checks. +static_assert(1 == TINT_COUNT_ARGUMENTS(a), "TINT_COUNT_ARGUMENTS broken"); +static_assert(2 == TINT_COUNT_ARGUMENTS(a, b), "TINT_COUNT_ARGUMENTS broken"); +static_assert(3 == TINT_COUNT_ARGUMENTS(a, b, c), "TINT_COUNT_ARGUMENTS broken"); +static_assert(64 == TINT_COUNT_ARGUMENTS(a, + b, + c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m, + n, + o, + p, + q, + r, + s, + t, + u, + v, + w, + x, + y, + z, + a2, + b2, + c2, + d2, + e2, + f2, + g2, + h2, + i2, + j2, + k2, + l2, + m2, + n2, + o2, + p2, + q2, + r2, + s2, + t2, + u2, + v2, + w2, + x2, + y2, + z2, + a3, + b3, + c3, + d3, + e3, + f3, + g3, + h3, + i3, + j3, + k3, + l3), + "TINT_COUNT_ARGUMENTS broken"); + +/// TINT_FOREACH calls CB with each of the variadic arguments. +#define TINT_FOREACH(CB, ...) \ + TINT_MSVC_EXPAND_BUG( \ + TINT_CONCAT(TINT_FOREACH_, TINT_COUNT_ARGUMENTS(__VA_ARGS__))(CB, __VA_ARGS__)) + +#define TINT_FOREACH_1(CB, _1) CB(_1) +#define TINT_FOREACH_2(CB, _1, _2) \ + TINT_FOREACH_1(CB, _1) \ + CB(_2) +#define TINT_FOREACH_3(CB, _1, _2, _3) \ + TINT_FOREACH_2(CB, _1, _2) \ + CB(_3) +#define TINT_FOREACH_4(CB, _1, _2, _3, _4) \ + TINT_FOREACH_3(CB, _1, _2, _3) \ + CB(_4) +#define TINT_FOREACH_5(CB, _1, _2, _3, _4, _5) \ + TINT_FOREACH_4(CB, _1, _2, _3, _4) \ + CB(_5) +#define TINT_FOREACH_6(CB, _1, _2, _3, _4, _5, _6) \ + TINT_FOREACH_5(CB, _1, _2, _3, _4, _5) \ + CB(_6) +#define TINT_FOREACH_7(CB, _1, _2, _3, _4, _5, _6, _7) \ + TINT_FOREACH_6(CB, _1, _2, _3, _4, _5, _6) \ + CB(_7) +#define TINT_FOREACH_8(CB, _1, _2, _3, _4, _5, _6, _7, _8) \ + TINT_FOREACH_7(CB, _1, _2, _3, _4, _5, _6, _7) \ + CB(_8) +#define TINT_FOREACH_9(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ + TINT_FOREACH_8(CB, _1, _2, _3, _4, _5, _6, _7, _8) \ + CB(_9) +#define TINT_FOREACH_10(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ + TINT_FOREACH_9(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ + CB(_10) +#define TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ + TINT_FOREACH_10(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ + CB(_11) +#define TINT_FOREACH_12(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ + TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ + CB(_12) +#define TINT_FOREACH_13(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ + TINT_FOREACH_12(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ + CB(_13) +#define TINT_FOREACH_14(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ + TINT_FOREACH_13(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ + CB(_14) +#define TINT_FOREACH_15(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ + TINT_FOREACH_14(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ + CB(_15) +#define TINT_FOREACH_16(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ + TINT_FOREACH_15(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ + CB(_16) +#define TINT_FOREACH_17(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17) \ + TINT_FOREACH_16(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ + CB(_17) +#define TINT_FOREACH_18(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18) \ + TINT_FOREACH_17(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17) \ + CB(_18) +#define TINT_FOREACH_19(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19) \ + TINT_FOREACH_18(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18) \ + CB(_19) +#define TINT_FOREACH_20(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20) \ + TINT_FOREACH_19(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19) \ + CB(_20) +#define TINT_FOREACH_21(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21) \ + TINT_FOREACH_20(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20) \ + CB(_21) +#define TINT_FOREACH_22(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22) \ + TINT_FOREACH_21(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21) \ + CB(_22) +#define TINT_FOREACH_23(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23) \ + TINT_FOREACH_22(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22) \ + CB(_23) +#define TINT_FOREACH_24(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24) \ + TINT_FOREACH_23(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23) \ + CB(_24) +#define TINT_FOREACH_25(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25) \ + TINT_FOREACH_24(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24) \ + CB(_25) +#define TINT_FOREACH_26(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26) \ + TINT_FOREACH_25(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25) \ + CB(_26) +#define TINT_FOREACH_27(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27) \ + TINT_FOREACH_26(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26) \ + CB(_27) +#define TINT_FOREACH_28(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28) \ + TINT_FOREACH_27(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27) \ + CB(_28) +#define TINT_FOREACH_29(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29) \ + TINT_FOREACH_28(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28) \ + CB(_29) +#define TINT_FOREACH_30(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30) \ + TINT_FOREACH_29(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29) \ + CB(_30) +#define TINT_FOREACH_31(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31) \ + TINT_FOREACH_30(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30) \ + CB(_31) +#define TINT_FOREACH_32(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32) \ + TINT_FOREACH_31(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31) \ + CB(_32) +#define TINT_FOREACH_33(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33) \ + TINT_FOREACH_32(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32) \ + CB(_33) +#define TINT_FOREACH_34(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34) \ + TINT_FOREACH_33(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33) \ + CB(_34) +#define TINT_FOREACH_35(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35) \ + TINT_FOREACH_34(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34) \ + CB(_35) +#define TINT_FOREACH_36(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36) \ + TINT_FOREACH_35(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35) \ + CB(_36) +#define TINT_FOREACH_37(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37) \ + TINT_FOREACH_36(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36) \ + CB(_37) +#define TINT_FOREACH_38(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38) \ + TINT_FOREACH_37(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37) \ + CB(_38) +#define TINT_FOREACH_39(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39) \ + TINT_FOREACH_38(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38) \ + CB(_39) +#define TINT_FOREACH_40(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40) \ + TINT_FOREACH_39(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39) \ + CB(_40) +#define TINT_FOREACH_41(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41) \ + TINT_FOREACH_40(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40) \ + CB(_41) +#define TINT_FOREACH_42(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42) \ + TINT_FOREACH_41(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41) \ + CB(_42) +#define TINT_FOREACH_43(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43) \ + TINT_FOREACH_42(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42) \ + CB(_43) +#define TINT_FOREACH_44(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44) \ + TINT_FOREACH_43(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43) \ + CB(_44) +#define TINT_FOREACH_45(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45) \ + TINT_FOREACH_44(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44) \ + CB(_45) +#define TINT_FOREACH_46(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46) \ + TINT_FOREACH_45(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45) \ + CB(_46) +#define TINT_FOREACH_47(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47) \ + TINT_FOREACH_46(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46) \ + CB(_47) +#define TINT_FOREACH_48(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48) \ + TINT_FOREACH_47(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47) \ + CB(_48) +#define TINT_FOREACH_49(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49) \ + TINT_FOREACH_48(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48) \ + CB(_49) +#define TINT_FOREACH_50(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50) \ + TINT_FOREACH_49(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49) \ + CB(_50) +#define TINT_FOREACH_51(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51) \ + TINT_FOREACH_50(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50) \ + CB(_51) +#define TINT_FOREACH_52(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52) \ + TINT_FOREACH_51(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51) \ + CB(_52) +#define TINT_FOREACH_53(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53) \ + TINT_FOREACH_52(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52) \ + CB(_53) +#define TINT_FOREACH_54(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54) \ + TINT_FOREACH_53(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53) \ + CB(_54) +#define TINT_FOREACH_55(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55) \ + TINT_FOREACH_54(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54) \ + CB(_55) +#define TINT_FOREACH_56(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56) \ + TINT_FOREACH_55(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55) \ + CB(_56) +#define TINT_FOREACH_57(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57) \ + TINT_FOREACH_56(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56) \ + CB(_57) +#define TINT_FOREACH_58(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58) \ + TINT_FOREACH_57(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57) \ + CB(_58) +#define TINT_FOREACH_59(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59) \ + TINT_FOREACH_58(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58) \ + CB(_59) +#define TINT_FOREACH_60(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60) \ + TINT_FOREACH_59(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59) \ + CB(_60) +#define TINT_FOREACH_61(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61) \ + TINT_FOREACH_60(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60) \ + CB(_61) +#define TINT_FOREACH_62(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, \ + _62) \ + TINT_FOREACH_61(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61) \ + CB(_62) +#define TINT_FOREACH_63(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, \ + _62, _63) \ + TINT_FOREACH_62(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, \ + _62) \ + CB(_63) +#define TINT_FOREACH_64(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, \ + _62, _63, _64) \ + TINT_FOREACH_63(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \ + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \ + _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, \ + _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, \ + _62, _63) \ + CB(_64) + +#endif // SRC_TINT_UTILS_MACROS_FOREACH_H_ diff --git a/3rdparty/dawn/src/tint/utils/macros/macros.cc b/3rdparty/dawn/src/tint/utils/macros/macros.cc new file mode 100644 index 000000000..3259c3d8e --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/macros.cc @@ -0,0 +1,33 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +// A placeholder symbol used to emit a symbol for this lib target. +int tint_utils_macros_symbol = 1; diff --git a/3rdparty/dawn/src/tint/utils/macros/scoped_assignment.h b/3rdparty/dawn/src/tint/utils/macros/scoped_assignment.h new file mode 100644 index 000000000..680803a48 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/scoped_assignment.h @@ -0,0 +1,74 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MACROS_SCOPED_ASSIGNMENT_H_ +#define SRC_TINT_UTILS_MACROS_SCOPED_ASSIGNMENT_H_ + +#include + +#include "src/tint/utils/macros/concat.h" + +namespace tint { + +/// Helper class that temporarily assigns a value to a variable for the lifetime +/// of the ScopedAssignment object. Once the ScopedAssignment is destructed, the +/// original value is restored. +template +class ScopedAssignment { + public: + /// Constructor + /// @param var the variable to temporarily assign a new value to + /// @param val the value to assign to `ref` for the lifetime of this + /// ScopedAssignment. + ScopedAssignment(T& var, T val) : ref_(var) { + old_value_ = var; + var = val; + } + + /// Destructor + /// Restores the original value of the variable. + ~ScopedAssignment() { ref_ = old_value_; } + + private: + ScopedAssignment(const ScopedAssignment&) = delete; + ScopedAssignment& operator=(const ScopedAssignment&) = delete; + + T& ref_; + T old_value_; +}; + +} // namespace tint + +/// TINT_SCOPED_ASSIGNMENT(var, val) assigns `val` to `var`, and automatically +/// restores the original value of `var` when exiting the current lexical scope. +#define TINT_SCOPED_ASSIGNMENT(var, val) \ + ::tint::ScopedAssignment> TINT_CONCAT( \ + tint_scoped_assignment_, __COUNTER__) { \ + var, val \ + } + +#endif // SRC_TINT_UTILS_MACROS_SCOPED_ASSIGNMENT_H_ diff --git a/3rdparty/dawn/src/tint/utils/macros/static_init.h b/3rdparty/dawn/src/tint/utils/macros/static_init.h new file mode 100644 index 000000000..1b01a9046 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/macros/static_init.h @@ -0,0 +1,44 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MACROS_STATIC_INIT_H_ +#define SRC_TINT_UTILS_MACROS_STATIC_INIT_H_ + +#include "src/tint/utils/macros/concat.h" + +/// A helper macro that executes STATEMENT the first time the macro comes into scope - typically +/// used at global scope to call a function before main() is run. +/// For example: `TINT_STATIC_INIT(CallAtStartup(1,2,3));` +/// @note: This must not be used at global scope in production code, as this violates the Chromium +/// rules around static initializers. Attempting to do this will result in a compilation error. +#define TINT_STATIC_INIT(STATEMENT) \ + [[maybe_unused]] static const bool TINT_CONCAT(tint_static_init_, __COUNTER__) = [] { \ + STATEMENT; \ + return true; \ + }() + +#endif // SRC_TINT_UTILS_MACROS_STATIC_INIT_H_ diff --git a/3rdparty/dawn/src/tint/utils/math/crc32.h b/3rdparty/dawn/src/tint/utils/math/crc32.h new file mode 100644 index 000000000..c407bd165 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/math/crc32.h @@ -0,0 +1,143 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MATH_CRC32_H_ +#define SRC_TINT_UTILS_MATH_CRC32_H_ + +#include +#include + +#include "src/tint/utils/macros/compiler.h" + +// This implementation of CRC32 uses C idioms that trigger '-Wunsafe-buffer-usage', but by +// inspecting the code one can see that they are not actually unsafe or an acceptable compromise in +// the design. +// +// First, all of the accesses to kCRC32LUT are considered unsafe, since it is a C-style array and +// thus does not do any meaningful bounds checking. Looking at the accesses below, they are all of +// the form `kCRC32LUT[static_cast(crc) ^ static_cast(*p)]`, i.e. the XOR of two +// u8s, which will always be a u8. kCRC32LUT has 256 entries, so this access will always be in +// bounds. +// +// The other issue that triggers warnings is the use of pointer arithmetic, since with raw pointers +// there is no bounds checking, though this is a standard C API idiom. Specifically for the +// constexpr function it is explicitly stated that the input is a '\0' terminated string, and the +// code is checking for the '\0' value. So assuming well-formed inputs this code is safe. Similarly +// for the inline function, the API explicitly calls for the size of the data buffer, which is +// assumed to be valid. Both of these functions also assume the user isn't passing in null +// pointers. +// +// This second issue could be mitigated via a combination of API changes, so only containers that +// have bounds checking are allowed. Though that would only be moving the problem off to whatever +// code is responsible for converting from the unsafe data formats. +// +// There is other checking that could be done to quite these warning, but all suffer from the fact +// that they fundamentally will be more costly to implement than the existing code. +// Performance in this code is a very important, since it is heavily utilized code as part of the +// Castable infrastructure in the code base, so any performance loss here would likely be +// noticeable. +// +// Other drop-in solutions are not really fit for purpose since they don't have the same design +// considerations. This implementation can be evaluated as a constexpr, which means that uses can +// potentially be evaluated at compile-time, thus mitigating the cost of doing the calculations in +// production. +// +// The simplicity of the implementation also means that one can visually inspect it and be +// reasonably confident in its safety. Additionally, this code is heavily used in the Tint code +// base which is tested via fuzzers and sanitizers, so has had significant indirect testing. +// +// A replacement implementing would need to be comparable in performance, be usable in constexpr, +// and have our confidence in its safety. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +namespace tint { + +/// CRC32 immutable lookup table data. +constexpr uint32_t kCRC32LUT[] = { + 0, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +/// @param s the null-terminated string +/// @returns the CRC32 of the string @p s. +/// @note this function can be used to calculate the CRC32 of a string literal +/// at compile time. +/// @see https://en.wikipedia.org/wiki/Cyclic_redundancy_check#CRC-32_algorithm +constexpr uint32_t CRC32(const char* s) { + uint32_t crc = 0xffffffff; + for (auto* p = s; *p != '\0'; ++p) { + crc = (crc >> 8) ^ kCRC32LUT[static_cast(crc) ^ static_cast(*p)]; + } + return crc ^ 0xffffffff; +} + +/// @param ptr a pointer to the start of the data +/// @param size the number of bytes of the data +/// @returns the CRC32 of the data at @p ptr of size @p size. +inline uint32_t CRC32(const void* ptr, size_t size) { + auto* p = static_cast(ptr); + uint32_t crc = 0xffffffff; + while (size--) { + crc = (crc >> 8) ^ kCRC32LUT[static_cast(crc) ^ *p++]; + } + return crc ^ 0xffffffff; +} + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_MATH_CRC32_H_ diff --git a/3rdparty/dawn/src/tint/utils/math/hash.h b/3rdparty/dawn/src/tint/utils/math/hash.h new file mode 100644 index 000000000..d5cd9c688 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/math/hash.h @@ -0,0 +1,339 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MATH_HASH_H_ +#define SRC_TINT_UTILS_MATH_HASH_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/utils/math/crc32.h" + +namespace tint { + +namespace detail { + +template +struct HasHashCodeMember : std::false_type {}; + +template +struct HasHashCodeMember< + T, + std::enable_if_t>> : std::true_type { +}; + +} // namespace detail + +/// The type of a hash code +using HashCode = uint32_t; + +/// Forward declarations (see below) +template +HashCode Hash(const ARGS&... values); + +template +HashCode HashCombine(HashCode hash, const ARGS&... values); + +/// A STL-compatible hasher that does a more thorough job than most implementations of std::hash. +/// Hasher has been optimized for a better quality hash at the expense of increased computation +/// costs. +/// Hasher is specialized for various core Tint data types. The default implementation will use a +/// `HashCode HashCode()` method on the `T` type, and will fallback to `std::hash` if +/// `T::HashCode` is missing. +template +struct Hasher { + /// @param value the value to hash + /// @returns a hash of the value + HashCode operator()(const T& value) const { + if constexpr (detail::HasHashCodeMember::value) { + auto hash = value.HashCode(); + static_assert(std::is_same_v, + "T::HashCode() must return HashCode"); + return hash; + } else { + return static_cast(std::hash()(value)); + } + } +}; + +/// Hasher specialization for pointers +template +struct Hasher { + /// @param ptr the pointer to hash + /// @returns a hash of the pointer + HashCode operator()(T* ptr) const { + auto hash = reinterpret_cast(ptr); +#ifdef TINT_HASH_SEED + hash ^= static_cast(TINT_HASH_SEED); +#endif + if constexpr (sizeof(hash) > 4) { + return static_cast(hash >> 4 | hash >> 32); + } else { + return static_cast(hash >> 4); + } + } +}; + +/// Hasher specialization for std::vector +template +struct Hasher> { + /// @param vector the vector to hash + /// @returns a hash of the vector + HashCode operator()(const std::vector& vector) const { + auto hash = Hash(vector.size()); + for (auto& el : vector) { + hash = HashCombine(hash, el); + } + return hash; + } +}; + +/// Hasher specialization for std::tuple +template +struct Hasher> { + /// @param tuple the tuple to hash + /// @returns a hash of the tuple + HashCode operator()(const std::tuple& tuple) const { + return std::apply(Hash, tuple); + } +}; + +/// Hasher specialization for std::pair +template +struct Hasher> { + /// @param tuple the tuple to hash + /// @returns a hash of the tuple + HashCode operator()(const std::pair& tuple) const { + return std::apply(Hash, tuple); + } +}; + +/// Hasher specialization for std::optional +template +struct Hasher> { + /// @param optional the std::optional to hash + /// @returns a hash of the std::optional + HashCode operator()(const std::optional& optional) const { + auto hash = Hash(optional.has_value()); + if (optional.has_value()) { + hash = HashCombine(hash, optional.value()); + } + return hash; + } +}; + +/// Hasher specialization for std::variant +template +struct Hasher> { + /// @param variant the variant to hash + /// @returns a hash of the tuple + HashCode operator()(const std::variant& variant) const { + return std::visit([](auto&& val) { return Hash(val); }, variant); + } +}; + +/// Hasher specialization for std::string, which also supports hashing of const char* and +/// std::string_view without first constructing a std::string. +template <> +struct Hasher { + /// @param str the string to hash + /// @returns a hash of the string + HashCode operator()(const std::string& str) const { + return static_cast(std::hash()(std::string_view(str))); + } + + /// @param str the string to hash + /// @returns a hash of the string + HashCode operator()(const char* str) const { + return static_cast(std::hash()(std::string_view(str))); + } + + /// @param str the string to hash + /// @returns a hash of the string + HashCode operator()(const std::string_view& str) const { + return static_cast(std::hash()(str)); + } +}; + +/// Hasher specialization for std::unordered_map +template +struct Hasher> { + /// @param map the std::unordered_map to hash + /// @returns a hash of the map + HashCode operator()(const std::unordered_map& map) const { + auto hash = Hash(map.size()); + for (const auto& [key, value] : map) { + // Use an XOR to ensure that the non-deterministic ordering of the map still produces + // the same hash value for the same entries. + hash ^= Hash(key, value); + } + return hash; + } +}; + +/// Hasher specialization for std::unordered_set +template +struct Hasher> { + /// @param set the std::unordered_set to hash + /// @returns a hash of the set + HashCode operator()(const std::unordered_set& set) const { + auto hash = Hash(set.size()); + for (const auto& key : set) { + // Use an XOR to ensure that the non-deterministic ordering of the map still produces + // the same hash value for the same entries. + hash ^= Hash(key); + } + return hash; + } +}; + +/// @param args the arguments to hash +/// @returns a hash of the variadic list of arguments. +/// The returned hash is dependent on the order of the arguments. +template +HashCode Hash(const ARGS&... args) { + if constexpr (sizeof...(ARGS) == 0) { + return 0; + } else if constexpr (sizeof...(ARGS) == 1) { + using T = std::tuple_element_t<0, std::tuple>; + return Hasher()(args...); + } else { + HashCode hash = 102931; // seed with an arbitrary prime + return HashCombine(hash, args...); + } +} + +/// @param hash the hash value to combine with +/// @param values the values to hash +/// @returns a hash of the variadic list of arguments. +/// The returned hash is dependent on the order of the arguments. +template +HashCode HashCombine(HashCode hash, const ARGS&... values) { +#ifdef TINT_HASH_SEED + constexpr uint32_t offset = 0x7f4a7c16 ^ static_cast(TINT_HASH_SEED); +#else + constexpr uint32_t offset = 0x7f4a7c16; +#endif + + ((hash ^= Hash(values) + (offset ^ (hash >> 2))), ...); + return hash; +} + +/// A STL-compatible equal_to implementation that specializes for types. +template +struct EqualTo { + /// @param lhs the left hand side value + /// @param rhs the right hand side value + /// @returns true if the two values are equal + constexpr bool operator()(const T& lhs, const T& rhs) const { + return std::equal_to()(lhs, rhs); + } +}; + +/// A specialization for EqualTo for std::string, which supports additional comparision with +/// std::string_view and const char*. +template <> +struct EqualTo { + /// @param lhs the left hand side value + /// @param rhs the right hand side value + /// @returns true if the two values are equal + bool operator()(const std::string& lhs, const std::string& rhs) const { return lhs == rhs; } + + /// @param lhs the left hand side value + /// @param rhs the right hand side value + /// @returns true if the two values are equal + bool operator()(const std::string& lhs, const char* rhs) const { return lhs == rhs; } + + /// @param lhs the left hand side value + /// @param rhs the right hand side value + /// @returns true if the two values are equal + bool operator()(const std::string& lhs, std::string_view rhs) const { return lhs == rhs; } + + /// @param lhs the left hand side value + /// @param rhs the right hand side value + /// @returns true if the two values are equal + bool operator()(const char* lhs, const std::string& rhs) const { return lhs == rhs; } + + /// @param lhs the left hand side value + /// @param rhs the right hand side value + /// @returns true if the two values are equal + bool operator()(std::string_view lhs, const std::string& rhs) const { return lhs == rhs; } +}; + +/// Wrapper for a hashable type enabling the wrapped value to be used as a key +/// for an unordered_map or unordered_set. +template +struct UnorderedKeyWrapper { + /// The wrapped value + T value; + /// The hash of value + HashCode hash; + + /// Constructor + /// @param v the value to wrap + explicit UnorderedKeyWrapper(const T& v) : value(v), hash(Hash(v)) {} + + /// Move constructor + /// @param v the value to wrap + explicit UnorderedKeyWrapper(T&& v) : value(std::move(v)), hash(Hash(value)) {} + + /// @returns true if this wrapper comes before other + /// @param other the RHS of the operator + bool operator<(const UnorderedKeyWrapper& other) const { return hash < other.hash; } + + /// @returns true if this wrapped value is equal to the other wrapped value + /// @param other the RHS of the operator + bool operator==(const UnorderedKeyWrapper& other) const { return value == other.value; } +}; + +} // namespace tint + +namespace std { + +/// Custom std::hash specialization for tint::UnorderedKeyWrapper +template +class hash> { + public: + /// @param w the UnorderedKeyWrapper + /// @return the hash value + inline std::size_t operator()(const tint::UnorderedKeyWrapper& w) const { return w.hash; } +}; + +} // namespace std + +#endif // SRC_TINT_UTILS_MATH_HASH_H_ diff --git a/3rdparty/dawn/src/tint/utils/math/math.cc b/3rdparty/dawn/src/tint/utils/math/math.cc new file mode 100644 index 000000000..b490eef03 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/math/math.cc @@ -0,0 +1,35 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/math/math.h" + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +// A placeholder symbol used to emit a symbol for this lib target. +int tint_utils_math_symbol = 1; diff --git a/3rdparty/dawn/src/tint/utils/math/math.h b/3rdparty/dawn/src/tint/utils/math/math.h new file mode 100644 index 000000000..8b5783aaf --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/math/math.h @@ -0,0 +1,116 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MATH_MATH_H_ +#define SRC_TINT_UTILS_MATH_MATH_H_ + +#include + +#include +#include + +namespace tint { + +/// @param alignment the next multiple to round `value` to +/// @param value the value to round to the next multiple of `alignment` +/// @return `value` rounded to the next multiple of `alignment`, or `value` if `alignment` is 0 +/// @note `alignment` must be positive. +template +inline constexpr T RoundUp(T alignment, T value) { + return alignment != 0 ? ((value + alignment - 1) / alignment) * alignment : value; +} + +/// @param value the value to check whether it is a power-of-two +/// @returns true if `value` is a power-of-two +/// @note `value` must be positive if `T` is signed +template +inline constexpr bool IsPowerOfTwo(T value) { + return (value & (value - 1)) == 0; +} + +/// @param value the input value +/// @returns the base-2 logarithm of @p value +inline constexpr uint32_t Log2(uint64_t value) { +#if defined(__clang__) || defined(__GNUC__) + return 63 - static_cast(__builtin_clzll(value)); +#elif defined(_MSC_VER) && !defined(__clang__) && __cplusplus >= 202002L && defined(__x86_64__) // MSVC and C++20+ + // note: std::is_constant_evaluated() added in C++20 + // required here as _BitScanReverse64 is not constexpr + if (!std::is_constant_evaluated()) { + // NOLINTNEXTLINE(runtime/int) + if constexpr (sizeof(unsigned long) == 8) { // 64-bit + // NOLINTNEXTLINE(runtime/int) + unsigned long first_bit_index = 0; + _tzcnt_u64(&first_bit_index, value); + return first_bit_index; + } else { // 32-bit + // NOLINTNEXTLINE(runtime/int) + unsigned long first_bit_index = 0; + if (_BitScanReverse(&first_bit_index, value >> 32)) { + return first_bit_index + 32; + } + _BitScanReverse(&first_bit_index, value & 0xffffffff); + return first_bit_index; + } + } +#endif + + // Non intrinsic (slow) path. Supports constexpr evaluation. + for (uint64_t clz = 0; clz < 64; clz++) { + uint64_t bit = 63 - clz; + if (value & (static_cast(1u) << bit)) { + return static_cast(bit); + } + } + return 64; +} + +/// @param value the input value +/// @returns the next power of two number greater or equal to @p value +inline constexpr uint64_t NextPowerOfTwo(uint64_t value) { + if (value <= 1) { + return 1; + } else { + return static_cast(1) << (Log2(value - 1) + 1); + } +} + +/// @param value the input value +/// @returns the largest power of two that `value` is a multiple of +template +inline std::enable_if_t::value, T> MaxAlignOf(T value) { + T pot = 1; + while (value && ((value & 1u) == 0)) { + pot <<= 1; + value >>= 1; + } + return pot; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_MATH_MATH_H_ diff --git a/3rdparty/dawn/src/tint/utils/memory/aligned_storage.h b/3rdparty/dawn/src/tint/utils/memory/aligned_storage.h new file mode 100644 index 000000000..7c533bb2f --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/memory/aligned_storage.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MEMORY_ALIGNED_STORAGE_H_ +#define SRC_TINT_UTILS_MEMORY_ALIGNED_STORAGE_H_ + +#include + +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/memory/bitcast.h" + +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +namespace tint { + +/// A structure that has the same size and alignment as Entry. +/// Replacement for std::aligned_storage as this is broken on earlier versions of MSVC. +template +struct alignas(alignof(T)) AlignedStorage { + /// Byte array of length sizeof(T) + std::byte data[sizeof(T)]; + + /// @returns a pointer to aligned storage, reinterpreted as T& + T& Get() { return *Bitcast(&data[0]); } + + /// @returns a pointer to aligned storage, reinterpreted as T& + const T& Get() const { return *Bitcast(&data[0]); } +}; + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_MEMORY_ALIGNED_STORAGE_H_ diff --git a/3rdparty/dawn/src/tint/utils/memory/bitcast.h b/3rdparty/dawn/src/tint/utils/memory/bitcast.h new file mode 100644 index 000000000..9b0fa57f7 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/memory/bitcast.h @@ -0,0 +1,71 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#ifndef SRC_TINT_UTILS_MEMORY_BITCAST_H_ +#define SRC_TINT_UTILS_MEMORY_BITCAST_H_ + +#include +#include +#include + +namespace tint { + +/// Bitcast performs a cast of `from` to the `TO` type using a memcpy. +/// This unsafe cast avoids triggering Clang's Control Flow Integrity checks. +/// See: crbug.com/dawn/1406 +/// See: https://clang.llvm.org/docs/ControlFlowIntegrity.html#bad-cast-checking +/// @param from the value to cast +/// @tparam TO the value to cast to +/// @returns the cast value +template +inline TO Bitcast(FROM&& from) { + static_assert(sizeof(FROM) == sizeof(TO)); + // gcc warns in cases where either TO or FROM are classes, even if they are trivially + // copyable, with for example: + // + // error: ‘void* memcpy(void*, const void*, size_t)’ copying an object of + // non-trivial type ‘struct tint::Number’ from an array of ‘float’ + // [-Werror=class-memaccess] + // + // We avoid this by asserting that both types are indeed trivially copyable, and casting both + // args to std::byte*. + static_assert(std::is_trivially_copyable_v>); + static_assert(std::is_trivially_copyable_v>); + TO to; + memcpy(reinterpret_cast(&to), reinterpret_cast(&from), + sizeof(TO)); + return to; +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_MEMORY_BITCAST_H_ diff --git a/3rdparty/dawn/src/tint/utils/memory/block_allocator.h b/3rdparty/dawn/src/tint/utils/memory/block_allocator.h new file mode 100644 index 000000000..2d682be5c --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/memory/block_allocator.h @@ -0,0 +1,330 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MEMORY_BLOCK_ALLOCATOR_H_ +#define SRC_TINT_UTILS_MEMORY_BLOCK_ALLOCATOR_H_ + +#include +#include +#include + +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/memory/bitcast.h" + +// This file implements a custom allocator & iterator using C-style data access. It is not +// unexpected that -Wunsafe-buffer-usage triggers in this code, since the type of dynamic access +// being used cannot be guaranteed to be safe via static analysis. Attempting to change this code in +// simple ways to quiet these errors either a) negatively affects the performance by introducing +// unneeded copes, or b) uses typing shenanigans to work around the warning that other +// linters/analyses are unhappy with. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +namespace tint { + +/// A container and allocator of objects of (or deriving from) the template type `T`. +/// Objects are allocated by calling Create(), and are owned by the BlockAllocator. +/// When the BlockAllocator is destructed, all constructed objects are automatically destructed and +/// freed. +/// +/// Objects held by the BlockAllocator can be iterated over using a View. +template +class BlockAllocator { + /// Pointers is a chunk of T* pointers, forming a linked list. + /// The list of Pointers are used to maintain the list of allocated objects. + /// Pointers are allocated out of the block memory. + struct Pointers { + static constexpr size_t kMax = 32; + std::array ptrs; + Pointers* next; + Pointers* prev; + size_t count; + }; + + /// Block is linked list of memory blocks. + /// Blocks are allocated out of heap memory. + /// + /// Note: We're not using std::aligned_storage here as this warns / errors on MSVC. + struct alignas(BLOCK_ALIGNMENT) Block { + uint8_t data[BLOCK_SIZE]; + Block* next = nullptr; + }; + + // Forward declaration + template + class TView; + + /// An iterator for the objects owned by the BlockAllocator. + template + class TIterator { + using PointerTy = std::conditional_t; + + public: + /// Equality operator + /// @param other the iterator to compare this iterator to + /// @returns true if this iterator is equal to other + bool operator==(const TIterator& other) const { + return ptrs == other.ptrs && idx == other.idx; + } + + /// Inequality operator + /// @param other the iterator to compare this iterator to + /// @returns true if this iterator is not equal to other + bool operator!=(const TIterator& other) const { return !(*this == other); } + + /// Progress the iterator forward one element + /// @returns this iterator + TIterator& operator++() { + if (ptrs != nullptr) { + ++idx; + if (idx >= ptrs->count) { + idx = 0; + ptrs = ptrs->next; + } + } + return *this; + } + + /// Progress the iterator backwards one element + /// @returns this iterator + TIterator& operator--() { + if (ptrs != nullptr) { + if (idx == 0) { + ptrs = ptrs->prev; + idx = ptrs->count - 1; + } + --idx; + } + return *this; + } + + /// @returns the pointer to the object at the current iterator position + PointerTy operator*() const { return ptrs->ptrs[idx]; } + + private: + friend TView; // Keep internal iterator impl private. + explicit TIterator(const Pointers* p, size_t i) : ptrs(p), idx(i) {} + + /// The current Pointers + const Pointers* ptrs = nullptr; + /// The current index within #ptrs + size_t idx = 0; + }; + + /// View provides begin() and end() methods for looping over the objects owned by the + /// BlockAllocator. + template + class TView { + public: + /// The iterator type + using iterator = TIterator; + /// The const iterator type + using const_iterator = TIterator; + + /// @returns an iterator to the beginning of the view + iterator begin() const { return iterator{allocator_->data.pointers.root, 0}; } + + /// @returns an iterator to the end of the view + iterator end() const { return iterator{nullptr, 0}; } + + private: + friend BlockAllocator; // For BlockAllocator::operator View() + explicit TView(BlockAllocator const* allocator) : allocator_(allocator) {} + BlockAllocator const* const allocator_; + }; + + public: + /// A forward-iterator type over the objects of the BlockAllocator + using Iterator = TIterator; + + /// An immutable forward-iterator type over the objects of the BlockAllocator + using ConstIterator = TIterator; + + /// View provides begin() and end() methods for looping over the objects owned by the + /// BlockAllocator. + using View = TView; + + /// ConstView provides begin() and end() methods for looping over the objects owned by the + /// BlockAllocator. + using ConstView = TView; + + /// Constructor + BlockAllocator() = default; + + /// Move constructor + /// @param rhs the BlockAllocator to move + BlockAllocator(BlockAllocator&& rhs) { std::swap(data, rhs.data); } + + /// Move assignment operator + /// @param rhs the BlockAllocator to move + /// @return this BlockAllocator + BlockAllocator& operator=(BlockAllocator&& rhs) { + if (this != &rhs) { + Reset(); + std::swap(data, rhs.data); + } + return *this; + } + + /// Destructor + ~BlockAllocator() { Reset(); } + + /// @return a View of all objects owned by this BlockAllocator + View Objects() { return View(this); } + + /// @return a ConstView of all objects owned by this BlockAllocator + ConstView Objects() const { return ConstView(this); } + + /// Creates a new `TYPE` owned by the BlockAllocator. + /// When the BlockAllocator is destructed the object will be destructed and freed. + /// @param args the arguments to pass to the constructor + /// @returns the pointer to the constructed object + template + TYPE* Create(ARGS&&... args) { + static_assert(std::is_same::value || std::is_base_of::value, + "TYPE does not derive from T"); + static_assert(std::is_same::value || std::has_virtual_destructor::value, + "TYPE requires a virtual destructor when calling Create() for a type " + "that is not T"); + + auto* ptr = Allocate(); + new (ptr) TYPE(std::forward(args)...); + AddObjectPointer(ptr); + data.count++; + + return ptr; + } + + /// Frees all allocations from the allocator. + void Reset() { + for (auto ptr : Objects()) { + ptr->~T(); + } + auto* block = data.block.root; + while (block != nullptr) { + auto* next = block->next; + delete block; + block = next; + } + data = {}; + } + + /// @returns the total number of allocated objects. + size_t Count() const { return data.count; } + + private: + BlockAllocator(const BlockAllocator&) = delete; + BlockAllocator& operator=(const BlockAllocator&) = delete; + + /// Allocates an instance of TYPE from the current block, or from a newly allocated block if the + /// current block is full. + template + TYPE* Allocate() { + static_assert(sizeof(TYPE) <= BLOCK_SIZE, + "Cannot construct TYPE with size greater than BLOCK_SIZE"); + static_assert(alignof(TYPE) <= BLOCK_ALIGNMENT, "alignof(TYPE) is greater than ALIGNMENT"); + + auto& block = data.block; + + block.current_offset = tint::RoundUp(alignof(TYPE), block.current_offset); + if (block.current_offset + sizeof(TYPE) > BLOCK_SIZE) { + // Allocate a new block from the heap + auto* prev_block = block.current; + block.current = new Block; + if (!block.current) { + return nullptr; // out of memory + } + block.current->next = nullptr; + block.current_offset = 0; + if (prev_block) { + prev_block->next = block.current; + } else { + block.root = block.current; + } + } + + auto* base = &block.current->data[0]; + auto* ptr = tint::Bitcast(base + block.current_offset); + block.current_offset += sizeof(TYPE); + return ptr; + } + + /// Adds `ptr` to the linked list of objects owned by this BlockAllocator. + /// Once added, `ptr` will be tracked for destruction when the BlockAllocator is destructed. + void AddObjectPointer(T* ptr) { + auto& pointers = data.pointers; + + if (!pointers.current || pointers.current->count == Pointers::kMax) { + auto* prev_pointers = pointers.current; + pointers.current = Allocate(); + if (!pointers.current) { + return; // out of memory + } + pointers.current->next = nullptr; + pointers.current->prev = prev_pointers; + pointers.current->count = 0; + + if (prev_pointers) { + prev_pointers->next = pointers.current; + } else { + pointers.root = pointers.current; + } + } + + pointers.current->ptrs[pointers.current->count++] = ptr; + } + + struct { + struct { + /// The root block of the block linked list + Block* root = nullptr; + /// The current (end) block of the blocked linked list. + /// New allocations come from this block + Block* current = nullptr; + /// The byte offset in #current for the next allocation. + /// Initialized with BLOCK_SIZE so that the first allocation triggers a block + /// allocation. + size_t current_offset = BLOCK_SIZE; + } block; + + struct { + /// The root Pointers structure of the pointers linked list + Pointers* root = nullptr; + /// The current (end) Pointers structure of the pointers linked list. + /// AddObjectPointer() adds to this structure. + Pointers* current = nullptr; + } pointers; + + size_t count = 0; + } data; +}; + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_MEMORY_BLOCK_ALLOCATOR_H_ diff --git a/3rdparty/dawn/src/tint/utils/memory/bump_allocator.h b/3rdparty/dawn/src/tint/utils/memory/bump_allocator.h new file mode 100644 index 000000000..1e12484ca --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/memory/bump_allocator.h @@ -0,0 +1,158 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_MEMORY_BUMP_ALLOCATOR_H_ +#define SRC_TINT_UTILS_MEMORY_BUMP_ALLOCATOR_H_ + +#include +#include +#include +#include +#include +#include + +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/memory/bitcast.h" + +// This file implements a custom allocator & iterator using C-style data access. It is not +// unexpected that -Wunsafe-buffer-usage triggers in this code, since the type of dynamic access +// being used cannot be guaranteed to be safe via static analysis. Attempting to change this code in +// simple ways to quiet these errors either a) negatively affects the performance by introducing +// unneeded copes, or b) uses typing shenanigans to work around the warning that other +// linters/analyses are unhappy with. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +namespace tint { + +/// A allocator for chunks of memory. The memory is owned by the BumpAllocator. When the +/// BumpAllocator is freed all of the allocated memory is freed. +class BumpAllocator { + /// BlockHeader is linked list of memory blocks. + /// Blocks are allocated out of heap memory. + struct BlockHeader { + BlockHeader* next; + }; + + public: + /// The default size for a block's data. Allocations can be greater than this, but smaller + /// allocations will use this size. + static constexpr size_t kDefaultBlockDataSize = 64 * 1024; + + /// Constructor + BumpAllocator() = default; + + /// Move constructor + /// @param rhs the BumpAllocator to move + BumpAllocator(BumpAllocator&& rhs) { std::swap(data, rhs.data); } + + /// Move assignment operator + /// @param rhs the BumpAllocator to move + /// @return this BumpAllocator + BumpAllocator& operator=(BumpAllocator&& rhs) { + if (this != &rhs) { + Reset(); + std::swap(data, rhs.data); + } + return *this; + } + + /// Destructor + ~BumpAllocator() { Reset(); } + + /// Allocates @p size_in_bytes from the current block, or from a newly allocated block if the + /// current block is full. + /// @param size_in_bytes the number of bytes to allocate + /// @returns the pointer to the allocated memory or `nullptr` if the memory can not be allocated + std::byte* Allocate(size_t size_in_bytes) { + if (DAWN_UNLIKELY(data.current_offset + size_in_bytes < size_in_bytes)) { + return nullptr; // integer overflow + } + if (data.current_offset + size_in_bytes > data.current_data_size) { + // Allocate a new block from the heap + auto* prev_block = data.current; + size_t data_size = std::max(size_in_bytes, kDefaultBlockDataSize); + data.current = Bitcast(new (std::nothrow) + std::byte[sizeof(BlockHeader) + data_size]); + if (DAWN_UNLIKELY(!data.current)) { + return nullptr; // out of memory + } + data.current->next = nullptr; + data.current_data_size = data_size; + data.current_offset = 0; + if (prev_block) { + prev_block->next = data.current; + } else { + data.root = data.current; + } + } + + auto* base = Bitcast(data.current) + sizeof(BlockHeader); + auto* ptr = base + data.current_offset; + data.current_offset += size_in_bytes; + data.count++; + return ptr; + } + + /// Frees all allocations from the allocator. + void Reset() { + auto* block = data.root; + while (block != nullptr) { + auto* next = block->next; + delete[] Bitcast(block); + block = next; + } + data = {}; + } + + /// @returns the total number of allocations + size_t Count() const { return data.count; } + + private: + BumpAllocator(const BumpAllocator&) = delete; + BumpAllocator& operator=(const BumpAllocator&) = delete; + + struct { + /// The root block of the block linked list + BlockHeader* root = nullptr; + /// The current (end) block of the blocked linked list. + /// New allocations come from this block + BlockHeader* current = nullptr; + /// The byte offset in #current for the next allocation. + size_t current_offset = 0; + /// The size of the #current, excluding the header size + size_t current_data_size = 0; + /// Total number of allocations + size_t count = 0; + } data; +}; + +} // namespace tint + +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +#endif // SRC_TINT_UTILS_MEMORY_BUMP_ALLOCATOR_H_ diff --git a/3rdparty/dawn/src/tint/utils/memory/memory.cc b/3rdparty/dawn/src/tint/utils/memory/memory.cc new file mode 100644 index 000000000..5b07e5ea5 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/memory/memory.cc @@ -0,0 +1,33 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +// A placeholder symbol used to emit a symbol for this lib target. +int tint_utils_memory_symbol = 1; diff --git a/3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.cc b/3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.cc new file mode 100644 index 000000000..88f3fa936 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.cc @@ -0,0 +1,21506 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: src/tint/utils/protos/ir/ir.proto +// Protobuf C++ Version: 6.32.0 + +#include "src/tint/utils/protos/ir/ir.pb.h" + +#include +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +namespace tint { +namespace core { +namespace ir { +namespace binary { +namespace pb { + +inline constexpr WorkgroupSize::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + x_{0u}, + y_{0u}, + z_{0u} {} + +template +PROTOBUF_CONSTEXPR WorkgroupSize::WorkgroupSize(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(WorkgroupSize_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct WorkgroupSizeDefaultTypeInternal { + PROTOBUF_CONSTEXPR WorkgroupSizeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~WorkgroupSizeDefaultTypeInternal() {} + union { + WorkgroupSize _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 WorkgroupSizeDefaultTypeInternal _WorkgroupSize_default_instance_; + +inline constexpr TypeVector::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + width_{0u}, + element_type_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeVector::TypeVector(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeVector_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeVectorDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeVectorDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeVectorDefaultTypeInternal() {} + union { + TypeVector _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeVectorDefaultTypeInternal _TypeVector_default_instance_; + +inline constexpr TypeTexelBuffer::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + texel_format_{static_cast< ::tint::core::ir::binary::pb::TexelFormat >(0)}, + access_{static_cast< ::tint::core::ir::binary::pb::AccessControl >(0)} {} + +template +PROTOBUF_CONSTEXPR TypeTexelBuffer::TypeTexelBuffer(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeTexelBuffer_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeTexelBufferDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeTexelBufferDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeTexelBufferDefaultTypeInternal() {} + union { + TypeTexelBuffer _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeTexelBufferDefaultTypeInternal _TypeTexelBuffer_default_instance_; + +inline constexpr TypeSubgroupMatrix::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + sub_type_{0u}, + rows_{0u}, + columns_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeSubgroupMatrix::TypeSubgroupMatrix(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeSubgroupMatrix_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeSubgroupMatrixDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeSubgroupMatrixDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeSubgroupMatrixDefaultTypeInternal() {} + union { + TypeSubgroupMatrix _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeSubgroupMatrixDefaultTypeInternal _TypeSubgroupMatrix_default_instance_; + +inline constexpr TypeStorageTexture::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + dimension_{static_cast< ::tint::core::ir::binary::pb::TextureDimension >(0)}, + texel_format_{static_cast< ::tint::core::ir::binary::pb::TexelFormat >(0)}, + access_{static_cast< ::tint::core::ir::binary::pb::AccessControl >(0)} {} + +template +PROTOBUF_CONSTEXPR TypeStorageTexture::TypeStorageTexture(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeStorageTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeStorageTextureDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeStorageTextureDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeStorageTextureDefaultTypeInternal() {} + union { + TypeStorageTexture _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeStorageTextureDefaultTypeInternal _TypeStorageTexture_default_instance_; + +inline constexpr TypeSampler::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + kind_{static_cast< ::tint::core::ir::binary::pb::SamplerKind >(0)} {} + +template +PROTOBUF_CONSTEXPR TypeSampler::TypeSampler(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeSampler_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeSamplerDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeSamplerDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeSamplerDefaultTypeInternal() {} + union { + TypeSampler _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeSamplerDefaultTypeInternal _TypeSampler_default_instance_; + +inline constexpr TypeSampledTexture::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + dimension_{static_cast< ::tint::core::ir::binary::pb::TextureDimension >(0)}, + sub_type_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeSampledTexture::TypeSampledTexture(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeSampledTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeSampledTextureDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeSampledTextureDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeSampledTextureDefaultTypeInternal() {} + union { + TypeSampledTexture _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeSampledTextureDefaultTypeInternal _TypeSampledTexture_default_instance_; +template +PROTOBUF_CONSTEXPR TypeResourceBinding::TypeResourceBinding(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(TypeResourceBinding_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct TypeResourceBindingDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeResourceBindingDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeResourceBindingDefaultTypeInternal() {} + union { + TypeResourceBinding _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeResourceBindingDefaultTypeInternal _TypeResourceBinding_default_instance_; + +inline constexpr TypePointer::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + address_space_{static_cast< ::tint::core::ir::binary::pb::AddressSpace >(0)}, + store_type_{0u}, + access_{static_cast< ::tint::core::ir::binary::pb::AccessControl >(0)} {} + +template +PROTOBUF_CONSTEXPR TypePointer::TypePointer(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypePointer_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypePointerDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypePointerDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypePointerDefaultTypeInternal() {} + union { + TypePointer _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypePointerDefaultTypeInternal _TypePointer_default_instance_; + +inline constexpr TypeMultisampledTexture::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + dimension_{static_cast< ::tint::core::ir::binary::pb::TextureDimension >(0)}, + sub_type_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeMultisampledTexture::TypeMultisampledTexture(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeMultisampledTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeMultisampledTextureDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeMultisampledTextureDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeMultisampledTextureDefaultTypeInternal() {} + union { + TypeMultisampledTexture _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeMultisampledTextureDefaultTypeInternal _TypeMultisampledTexture_default_instance_; + +inline constexpr TypeMatrix::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + num_columns_{0u}, + num_rows_{0u}, + element_type_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeMatrix::TypeMatrix(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeMatrix_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeMatrixDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeMatrixDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeMatrixDefaultTypeInternal() {} + union { + TypeMatrix _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeMatrixDefaultTypeInternal _TypeMatrix_default_instance_; + +inline constexpr TypeInputAttachment::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + sub_type_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeInputAttachment::TypeInputAttachment(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeInputAttachment_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeInputAttachmentDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeInputAttachmentDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeInputAttachmentDefaultTypeInternal() {} + union { + TypeInputAttachment _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeInputAttachmentDefaultTypeInternal _TypeInputAttachment_default_instance_; +template +PROTOBUF_CONSTEXPR TypeExternalTexture::TypeExternalTexture(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(TypeExternalTexture_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct TypeExternalTextureDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeExternalTextureDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeExternalTextureDefaultTypeInternal() {} + union { + TypeExternalTexture _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeExternalTextureDefaultTypeInternal _TypeExternalTexture_default_instance_; + +inline constexpr TypeDepthTexture::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + dimension_{static_cast< ::tint::core::ir::binary::pb::TextureDimension >(0)} {} + +template +PROTOBUF_CONSTEXPR TypeDepthTexture::TypeDepthTexture(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeDepthTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeDepthTextureDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeDepthTextureDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeDepthTextureDefaultTypeInternal() {} + union { + TypeDepthTexture _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeDepthTextureDefaultTypeInternal _TypeDepthTexture_default_instance_; + +inline constexpr TypeDepthMultisampledTexture::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + dimension_{static_cast< ::tint::core::ir::binary::pb::TextureDimension >(0)} {} + +template +PROTOBUF_CONSTEXPR TypeDepthMultisampledTexture::TypeDepthMultisampledTexture(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeDepthMultisampledTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeDepthMultisampledTextureDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeDepthMultisampledTextureDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeDepthMultisampledTextureDefaultTypeInternal() {} + union { + TypeDepthMultisampledTexture _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeDepthMultisampledTextureDefaultTypeInternal _TypeDepthMultisampledTexture_default_instance_; + +inline constexpr TypeBuffer::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + count_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeBuffer::TypeBuffer(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeBuffer_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeBufferDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeBufferDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeBufferDefaultTypeInternal() {} + union { + TypeBuffer _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeBufferDefaultTypeInternal _TypeBuffer_default_instance_; + +inline constexpr TypeBindingArray::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + element_{0u}, + count_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeBindingArray::TypeBindingArray(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeBindingArray_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeBindingArrayDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeBindingArrayDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeBindingArrayDefaultTypeInternal() {} + union { + TypeBindingArray _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeBindingArrayDefaultTypeInternal _TypeBindingArray_default_instance_; + +inline constexpr TypeAtomic::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + type_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeAtomic::TypeAtomic(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeAtomic_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeAtomicDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeAtomicDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeAtomicDefaultTypeInternal() {} + union { + TypeAtomic _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeAtomicDefaultTypeInternal _TypeAtomic_default_instance_; + +inline constexpr TypeArray::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + element_{0u}, + count_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeArray::TypeArray(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeArray_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeArrayDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeArrayDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeArrayDefaultTypeInternal() {} + union { + TypeArray _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeArrayDefaultTypeInternal _TypeArray_default_instance_; + +inline constexpr SwitchCase::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + selectors_{}, + _selectors_cached_byte_size_{0}, + block_{0u}, + is_default_{false} {} + +template +PROTOBUF_CONSTEXPR SwitchCase::SwitchCase(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(SwitchCase_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct SwitchCaseDefaultTypeInternal { + PROTOBUF_CONSTEXPR SwitchCaseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~SwitchCaseDefaultTypeInternal() {} + union { + SwitchCase _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SwitchCaseDefaultTypeInternal _SwitchCase_default_instance_; + +inline constexpr Interpolation::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + type_{static_cast< ::tint::core::ir::binary::pb::InterpolationType >(0)}, + sampling_{static_cast< ::tint::core::ir::binary::pb::InterpolationSampling >(0)} {} + +template +PROTOBUF_CONSTEXPR Interpolation::Interpolation(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Interpolation_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InterpolationDefaultTypeInternal { + PROTOBUF_CONSTEXPR InterpolationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InterpolationDefaultTypeInternal() {} + union { + Interpolation _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InterpolationDefaultTypeInternal _Interpolation_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionUserCall::InstructionUserCall(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionUserCall_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionUserCallDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionUserCallDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionUserCallDefaultTypeInternal() {} + union { + InstructionUserCall _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionUserCallDefaultTypeInternal _InstructionUserCall_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionUnreachable::InstructionUnreachable(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionUnreachable_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionUnreachableDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionUnreachableDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionUnreachableDefaultTypeInternal() {} + union { + InstructionUnreachable _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionUnreachableDefaultTypeInternal _InstructionUnreachable_default_instance_; + +inline constexpr InstructionUnary::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + op_{static_cast< ::tint::core::ir::binary::pb::UnaryOp >(0)} {} + +template +PROTOBUF_CONSTEXPR InstructionUnary::InstructionUnary(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionUnary_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionUnaryDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionUnaryDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionUnaryDefaultTypeInternal() {} + union { + InstructionUnary _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionUnaryDefaultTypeInternal _InstructionUnary_default_instance_; + +inline constexpr InstructionSwizzle::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : indices_{}, + _indices_cached_byte_size_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR InstructionSwizzle::InstructionSwizzle(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionSwizzle_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionSwizzleDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionSwizzleDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionSwizzleDefaultTypeInternal() {} + union { + InstructionSwizzle _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionSwizzleDefaultTypeInternal _InstructionSwizzle_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionStoreVectorElement::InstructionStoreVectorElement(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionStoreVectorElement_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionStoreVectorElementDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionStoreVectorElementDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionStoreVectorElementDefaultTypeInternal() {} + union { + InstructionStoreVectorElement _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionStoreVectorElementDefaultTypeInternal _InstructionStoreVectorElement_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionStore::InstructionStore(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionStore_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionStoreDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionStoreDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionStoreDefaultTypeInternal() {} + union { + InstructionStore _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionStoreDefaultTypeInternal _InstructionStore_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionReturn::InstructionReturn(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionReturn_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionReturnDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionReturnDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionReturnDefaultTypeInternal() {} + union { + InstructionReturn _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionReturnDefaultTypeInternal _InstructionReturn_default_instance_; + +inline constexpr InstructionResult::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + type_{0u} {} + +template +PROTOBUF_CONSTEXPR InstructionResult::InstructionResult(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionResult_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionResultDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionResultDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionResultDefaultTypeInternal() {} + union { + InstructionResult _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionResultDefaultTypeInternal _InstructionResult_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionNextIteration::InstructionNextIteration(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionNextIteration_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionNextIterationDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionNextIterationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionNextIterationDefaultTypeInternal() {} + union { + InstructionNextIteration _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionNextIterationDefaultTypeInternal _InstructionNextIteration_default_instance_; + +inline constexpr InstructionLoop::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + initializer_{0u}, + body_{0u}, + continuing_{0u} {} + +template +PROTOBUF_CONSTEXPR InstructionLoop::InstructionLoop(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionLoop_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionLoopDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionLoopDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionLoopDefaultTypeInternal() {} + union { + InstructionLoop _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionLoopDefaultTypeInternal _InstructionLoop_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionLoadVectorElement::InstructionLoadVectorElement(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionLoadVectorElement_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionLoadVectorElementDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionLoadVectorElementDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionLoadVectorElementDefaultTypeInternal() {} + union { + InstructionLoadVectorElement _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionLoadVectorElementDefaultTypeInternal _InstructionLoadVectorElement_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionLoad::InstructionLoad(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionLoad_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionLoadDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionLoadDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionLoadDefaultTypeInternal() {} + union { + InstructionLoad _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionLoadDefaultTypeInternal _InstructionLoad_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionLet::InstructionLet(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionLet_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionLetDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionLetDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionLetDefaultTypeInternal() {} + union { + InstructionLet _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionLetDefaultTypeInternal _InstructionLet_default_instance_; + +inline constexpr InstructionIf::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + true__{0u}, + false__{0u} {} + +template +PROTOBUF_CONSTEXPR InstructionIf::InstructionIf(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionIf_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionIfDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionIfDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionIfDefaultTypeInternal() {} + union { + InstructionIf _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionIfDefaultTypeInternal _InstructionIf_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionExitSwitch::InstructionExitSwitch(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionExitSwitch_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionExitSwitchDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionExitSwitchDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionExitSwitchDefaultTypeInternal() {} + union { + InstructionExitSwitch _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionExitSwitchDefaultTypeInternal _InstructionExitSwitch_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionExitLoop::InstructionExitLoop(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionExitLoop_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionExitLoopDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionExitLoopDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionExitLoopDefaultTypeInternal() {} + union { + InstructionExitLoop _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionExitLoopDefaultTypeInternal _InstructionExitLoop_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionExitIf::InstructionExitIf(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionExitIf_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionExitIfDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionExitIfDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionExitIfDefaultTypeInternal() {} + union { + InstructionExitIf _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionExitIfDefaultTypeInternal _InstructionExitIf_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionDiscard::InstructionDiscard(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionDiscard_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionDiscardDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionDiscardDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionDiscardDefaultTypeInternal() {} + union { + InstructionDiscard _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionDiscardDefaultTypeInternal _InstructionDiscard_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionConvert::InstructionConvert(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionConvert_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionConvertDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionConvertDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionConvertDefaultTypeInternal() {} + union { + InstructionConvert _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionConvertDefaultTypeInternal _InstructionConvert_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionContinue::InstructionContinue(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionContinue_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionContinueDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionContinueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionContinueDefaultTypeInternal() {} + union { + InstructionContinue _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionContinueDefaultTypeInternal _InstructionContinue_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionConstruct::InstructionConstruct(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionConstruct_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionConstructDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionConstructDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionConstructDefaultTypeInternal() {} + union { + InstructionConstruct _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionConstructDefaultTypeInternal _InstructionConstruct_default_instance_; + +inline constexpr InstructionBuiltinCall::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + explicit_template_params_{}, + _explicit_template_params_cached_byte_size_{0}, + builtin_{static_cast< ::tint::core::ir::binary::pb::BuiltinFn >(0)} {} + +template +PROTOBUF_CONSTEXPR InstructionBuiltinCall::InstructionBuiltinCall(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionBuiltinCall_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionBuiltinCallDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionBuiltinCallDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionBuiltinCallDefaultTypeInternal() {} + union { + InstructionBuiltinCall _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionBuiltinCallDefaultTypeInternal _InstructionBuiltinCall_default_instance_; + +inline constexpr InstructionBreakIf::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + num_next_iter_values_{0u} {} + +template +PROTOBUF_CONSTEXPR InstructionBreakIf::InstructionBreakIf(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionBreakIf_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionBreakIfDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionBreakIfDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionBreakIfDefaultTypeInternal() {} + union { + InstructionBreakIf _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionBreakIfDefaultTypeInternal _InstructionBreakIf_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionBitcast::InstructionBitcast(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionBitcast_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionBitcastDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionBitcastDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionBitcastDefaultTypeInternal() {} + union { + InstructionBitcast _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionBitcastDefaultTypeInternal _InstructionBitcast_default_instance_; + +inline constexpr InstructionBinary::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + op_{static_cast< ::tint::core::ir::binary::pb::BinaryOp >(0)} {} + +template +PROTOBUF_CONSTEXPR InstructionBinary::InstructionBinary(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionBinary_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionBinaryDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionBinaryDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionBinaryDefaultTypeInternal() {} + union { + InstructionBinary _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionBinaryDefaultTypeInternal _InstructionBinary_default_instance_; +template +PROTOBUF_CONSTEXPR InstructionAccess::InstructionAccess(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(InstructionAccess_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE +struct InstructionAccessDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionAccessDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionAccessDefaultTypeInternal() {} + union { + InstructionAccess _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionAccessDefaultTypeInternal _InstructionAccess_default_instance_; + +inline constexpr ConstantValueSplat::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + type_{0u}, + elements_{0u}, + count_{0u} {} + +template +PROTOBUF_CONSTEXPR ConstantValueSplat::ConstantValueSplat(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ConstantValueSplat_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct ConstantValueSplatDefaultTypeInternal { + PROTOBUF_CONSTEXPR ConstantValueSplatDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ConstantValueSplatDefaultTypeInternal() {} + union { + ConstantValueSplat _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ConstantValueSplatDefaultTypeInternal _ConstantValueSplat_default_instance_; + +inline constexpr ConstantValueScalar::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +template +PROTOBUF_CONSTEXPR ConstantValueScalar::ConstantValueScalar(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ConstantValueScalar_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct ConstantValueScalarDefaultTypeInternal { + PROTOBUF_CONSTEXPR ConstantValueScalarDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ConstantValueScalarDefaultTypeInternal() {} + union { + ConstantValueScalar _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ConstantValueScalarDefaultTypeInternal _ConstantValueScalar_default_instance_; + +inline constexpr ConstantValueComposite::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + elements_{}, + _elements_cached_byte_size_{0}, + type_{0u} {} + +template +PROTOBUF_CONSTEXPR ConstantValueComposite::ConstantValueComposite(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ConstantValueComposite_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct ConstantValueCompositeDefaultTypeInternal { + PROTOBUF_CONSTEXPR ConstantValueCompositeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ConstantValueCompositeDefaultTypeInternal() {} + union { + ConstantValueComposite _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ConstantValueCompositeDefaultTypeInternal _ConstantValueComposite_default_instance_; + +inline constexpr BlockParameter::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + type_{0u} {} + +template +PROTOBUF_CONSTEXPR BlockParameter::BlockParameter(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(BlockParameter_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct BlockParameterDefaultTypeInternal { + PROTOBUF_CONSTEXPR BlockParameterDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~BlockParameterDefaultTypeInternal() {} + union { + BlockParameter _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BlockParameterDefaultTypeInternal _BlockParameter_default_instance_; + +inline constexpr BindingPoint::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + group_{0u}, + binding_{0u} {} + +template +PROTOBUF_CONSTEXPR BindingPoint::BindingPoint(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(BindingPoint_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct BindingPointDefaultTypeInternal { + PROTOBUF_CONSTEXPR BindingPointDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~BindingPointDefaultTypeInternal() {} + union { + BindingPoint _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BindingPointDefaultTypeInternal _BindingPoint_default_instance_; + +inline constexpr InstructionVar::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + binding_point_{nullptr}, + input_attachment_index_{0u} {} + +template +PROTOBUF_CONSTEXPR InstructionVar::InstructionVar(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionVar_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionVarDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionVarDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionVarDefaultTypeInternal() {} + union { + InstructionVar _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionVarDefaultTypeInternal _InstructionVar_default_instance_; + +inline constexpr InstructionSwitch::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : cases_{}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR InstructionSwitch::InstructionSwitch(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(InstructionSwitch_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionSwitchDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionSwitchDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionSwitchDefaultTypeInternal() {} + union { + InstructionSwitch _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionSwitchDefaultTypeInternal _InstructionSwitch_default_instance_; + +inline constexpr Function::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + parameters_{}, + _parameters_cached_byte_size_{0}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + workgroup_size_{nullptr}, + return_interpolation_{nullptr}, + return_type_{0u}, + block_{0u}, + pipeline_stage_{static_cast< ::tint::core::ir::binary::pb::PipelineStage >(0)}, + return_location_{0u}, + return_builtin_{static_cast< ::tint::core::ir::binary::pb::BuiltinValue >(0)}, + return_invariant_{false}, + subgroup_size_{0u} {} + +template +PROTOBUF_CONSTEXPR Function::Function(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Function_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct FunctionDefaultTypeInternal { + PROTOBUF_CONSTEXPR FunctionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~FunctionDefaultTypeInternal() {} + union { + Function _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FunctionDefaultTypeInternal _Function_default_instance_; + +inline constexpr ConstantValue::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +template +PROTOBUF_CONSTEXPR ConstantValue::ConstantValue(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ConstantValue_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct ConstantValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR ConstantValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ConstantValueDefaultTypeInternal() {} + union { + ConstantValue _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ConstantValueDefaultTypeInternal _ConstantValue_default_instance_; + +inline constexpr AttributesStructMember::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + interpolation_{nullptr}, + location_{0u}, + blend_src_{0u}, + color_{0u}, + builtin_{static_cast< ::tint::core::ir::binary::pb::BuiltinValue >(0)}, + invariant_{false} {} + +template +PROTOBUF_CONSTEXPR AttributesStructMember::AttributesStructMember(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(AttributesStructMember_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct AttributesStructMemberDefaultTypeInternal { + PROTOBUF_CONSTEXPR AttributesStructMemberDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~AttributesStructMemberDefaultTypeInternal() {} + union { + AttributesStructMember _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 AttributesStructMemberDefaultTypeInternal _AttributesStructMember_default_instance_; + +inline constexpr AttributesFunctionParameter::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + interpolation_{nullptr}, + binding_point_{nullptr}, + builtin_{static_cast< ::tint::core::ir::binary::pb::BuiltinValue >(0)}, + location_{0u}, + color_{0u}, + invariant_{false} {} + +template +PROTOBUF_CONSTEXPR AttributesFunctionParameter::AttributesFunctionParameter(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(AttributesFunctionParameter_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct AttributesFunctionParameterDefaultTypeInternal { + PROTOBUF_CONSTEXPR AttributesFunctionParameterDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~AttributesFunctionParameterDefaultTypeInternal() {} + union { + AttributesFunctionParameter _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 AttributesFunctionParameterDefaultTypeInternal _AttributesFunctionParameter_default_instance_; + +inline constexpr TypeStructMember::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + attributes_{nullptr}, + type_{0u}, + size_{0u}, + align_{0u} {} + +template +PROTOBUF_CONSTEXPR TypeStructMember::TypeStructMember(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeStructMember_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeStructMemberDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeStructMemberDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeStructMemberDefaultTypeInternal() {} + union { + TypeStructMember _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeStructMemberDefaultTypeInternal _TypeStructMember_default_instance_; + +inline constexpr Instruction::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : operands_{}, + _operands_cached_byte_size_{0}, + results_{}, + _results_cached_byte_size_{0}, + kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +template +PROTOBUF_CONSTEXPR Instruction::Instruction(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Instruction_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct InstructionDefaultTypeInternal { + PROTOBUF_CONSTEXPR InstructionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~InstructionDefaultTypeInternal() {} + union { + Instruction _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 InstructionDefaultTypeInternal _Instruction_default_instance_; + +inline constexpr FunctionParameter::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + attributes_{nullptr}, + type_{0u} {} + +template +PROTOBUF_CONSTEXPR FunctionParameter::FunctionParameter(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FunctionParameter_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct FunctionParameterDefaultTypeInternal { + PROTOBUF_CONSTEXPR FunctionParameterDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~FunctionParameterDefaultTypeInternal() {} + union { + FunctionParameter _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FunctionParameterDefaultTypeInternal _FunctionParameter_default_instance_; + +inline constexpr Value::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +template +PROTOBUF_CONSTEXPR Value::Value(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Value_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct ValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ValueDefaultTypeInternal() {} + union { + Value _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ValueDefaultTypeInternal _Value_default_instance_; + +inline constexpr TypeStruct::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + member_{}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()) {} + +template +PROTOBUF_CONSTEXPR TypeStruct::TypeStruct(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(TypeStruct_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeStructDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeStructDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeStructDefaultTypeInternal() {} + union { + TypeStruct _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeStructDefaultTypeInternal _TypeStruct_default_instance_; + +inline constexpr Block::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + parameters_{}, + _parameters_cached_byte_size_{0}, + instructions_{}, + is_multi_in_{false} {} + +template +PROTOBUF_CONSTEXPR Block::Block(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Block_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct BlockDefaultTypeInternal { + PROTOBUF_CONSTEXPR BlockDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~BlockDefaultTypeInternal() {} + union { + Block _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BlockDefaultTypeInternal _Block_default_instance_; + +inline constexpr Type::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +template +PROTOBUF_CONSTEXPR Type::Type(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Type_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct TypeDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeDefaultTypeInternal() {} + union { + Type _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeDefaultTypeInternal _Type_default_instance_; + +inline constexpr Module::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + types_{}, + values_{}, + constant_values_{}, + functions_{}, + blocks_{}, + root_block_{0u} {} + +template +PROTOBUF_CONSTEXPR Module::Module(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Module_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} +struct ModuleDefaultTypeInternal { + PROTOBUF_CONSTEXPR ModuleDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ModuleDefaultTypeInternal() {} + union { + Module _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT_WITH_PTR + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ModuleDefaultTypeInternal _Module_default_instance_; +} // namespace pb +} // namespace binary +} // namespace ir +} // namespace core +} // namespace tint +static const ::_pb::EnumDescriptor* PROTOBUF_NONNULL + file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[14]; +static constexpr const ::_pb::ServiceDescriptor *PROTOBUF_NONNULL *PROTOBUF_NULLABLE + file_level_service_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto = nullptr; +const ::uint32_t + TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_.types_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_.values_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_.constant_values_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_.functions_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_.blocks_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Module, _impl_.root_block_), + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + 0, + 0x004, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_._oneof_case_[0]), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_.kind_), + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeVector, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeVector, _impl_.width_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeVector, _impl_.element_type_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMatrix, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMatrix, _impl_.num_columns_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMatrix, _impl_.num_rows_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMatrix, _impl_.element_type_), + 0, + 1, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeArray, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeArray, _impl_.element_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeArray, _impl_.count_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeBindingArray, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeBindingArray, _impl_.element_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeBindingArray, _impl_.count_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypePointer, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypePointer, _impl_.address_space_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypePointer, _impl_.store_type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypePointer, _impl_.access_), + 0, + 1, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStruct, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStruct, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStruct, _impl_.member_), + 0, + ~0u, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStructMember, _impl_._has_bits_), + 8, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStructMember, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStructMember, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStructMember, _impl_.size_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStructMember, _impl_.align_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStructMember, _impl_.attributes_), + 0, + 2, + 3, + 4, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeAtomic, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeAtomic, _impl_.type_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeDepthTexture, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeDepthTexture, _impl_.dimension_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSampledTexture, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSampledTexture, _impl_.dimension_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSampledTexture, _impl_.sub_type_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMultisampledTexture, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMultisampledTexture, _impl_.dimension_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeMultisampledTexture, _impl_.sub_type_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeDepthMultisampledTexture, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeDepthMultisampledTexture, _impl_.dimension_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStorageTexture, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStorageTexture, _impl_.dimension_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStorageTexture, _impl_.texel_format_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeStorageTexture, _impl_.access_), + 0, + 1, + 2, + 0x000, // bitmap + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSampler, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSampler, _impl_.kind_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeInputAttachment, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeInputAttachment, _impl_.sub_type_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSubgroupMatrix, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSubgroupMatrix, _impl_.sub_type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSubgroupMatrix, _impl_.rows_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeSubgroupMatrix, _impl_.columns_), + 0, + 1, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeBuffer, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeBuffer, _impl_.count_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeTexelBuffer, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeTexelBuffer, _impl_.texel_format_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::TypeTexelBuffer, _impl_.access_), + 0, + 1, + 0x004, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_._oneof_case_[0]), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_.kind_), + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionResult, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionResult, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionResult, _impl_.name_), + 1, + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::FunctionParameter, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::FunctionParameter, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::FunctionParameter, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::FunctionParameter, _impl_.attributes_), + 2, + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::BlockParameter, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::BlockParameter, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::BlockParameter, _impl_.name_), + 1, + 0, + 0x004, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValue, _impl_._oneof_case_[0]), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValue, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValue, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValue, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValue, _impl_.kind_), + 0x004, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_._oneof_case_[0]), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_.kind_), + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueComposite, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueComposite, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueComposite, _impl_.elements_), + 0, + ~0u, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueSplat, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueSplat, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueSplat, _impl_.elements_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueSplat, _impl_.count_), + 0, + 1, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_._has_bits_), + 14, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.return_type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.block_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.pipeline_stage_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.workgroup_size_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.parameters_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.return_location_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.return_interpolation_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.return_builtin_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.return_invariant_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Function, _impl_.subgroup_size_), + 3, + 4, + 0, + 5, + 1, + ~0u, + 6, + 2, + 7, + 8, + 9, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::WorkgroupSize, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::WorkgroupSize, _impl_.x_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::WorkgroupSize, _impl_.y_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::WorkgroupSize, _impl_.z_), + 0, + 1, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Block, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Block, _impl_.parameters_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Block, _impl_.instructions_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Block, _impl_.is_multi_in_), + ~0u, + ~0u, + 0, + 0x004, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_._oneof_case_[0]), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.operands_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.results_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_.kind_), + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionUnary, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionUnary, _impl_.op_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBinary, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBinary, _impl_.op_), + 0, + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionVar, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionVar, _impl_.binding_point_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionVar, _impl_.input_attachment_index_), + 0, + 1, + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBuiltinCall, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBuiltinCall, _impl_.builtin_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBuiltinCall, _impl_.explicit_template_params_), + 0, + ~0u, + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionSwizzle, _impl_.indices_), + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionIf, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionIf, _impl_.true__), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionIf, _impl_.false__), + 0, + 1, + 0x000, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionSwitch, _impl_.cases_), + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionLoop, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionLoop, _impl_.initializer_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionLoop, _impl_.body_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionLoop, _impl_.continuing_), + 0, + 1, + 2, + 0x000, // bitmap + 0x000, // bitmap + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::SwitchCase, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::SwitchCase, _impl_.block_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::SwitchCase, _impl_.selectors_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::SwitchCase, _impl_.is_default_), + 0, + ~0u, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::BindingPoint, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::BindingPoint, _impl_.group_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::BindingPoint, _impl_.binding_), + 0, + 1, + 0x000, // bitmap + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBreakIf, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::InstructionBreakIf, _impl_.num_next_iter_values_), + 0, + 0x000, // bitmap + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_.blend_src_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_.color_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_.builtin_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_.interpolation_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesStructMember, _impl_.invariant_), + 1, + 2, + 3, + 4, + 0, + 5, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_.builtin_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_.color_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_.interpolation_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_.binding_point_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::AttributesFunctionParameter, _impl_.invariant_), + 2, + 3, + 4, + 0, + 1, + 5, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Interpolation, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Interpolation, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Interpolation, _impl_.sampling_), + 0, + 1, +}; + +static const ::_pbi::MigrationSchema + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + {0, sizeof(::tint::core::ir::binary::pb::Module)}, + {15, sizeof(::tint::core::ir::binary::pb::Type)}, + {40, sizeof(::tint::core::ir::binary::pb::TypeVector)}, + {47, sizeof(::tint::core::ir::binary::pb::TypeMatrix)}, + {56, sizeof(::tint::core::ir::binary::pb::TypeArray)}, + {63, sizeof(::tint::core::ir::binary::pb::TypeBindingArray)}, + {70, sizeof(::tint::core::ir::binary::pb::TypePointer)}, + {79, sizeof(::tint::core::ir::binary::pb::TypeStruct)}, + {86, sizeof(::tint::core::ir::binary::pb::TypeStructMember)}, + {99, sizeof(::tint::core::ir::binary::pb::TypeAtomic)}, + {104, sizeof(::tint::core::ir::binary::pb::TypeDepthTexture)}, + {109, sizeof(::tint::core::ir::binary::pb::TypeSampledTexture)}, + {116, sizeof(::tint::core::ir::binary::pb::TypeMultisampledTexture)}, + {123, sizeof(::tint::core::ir::binary::pb::TypeDepthMultisampledTexture)}, + {128, sizeof(::tint::core::ir::binary::pb::TypeStorageTexture)}, + {137, sizeof(::tint::core::ir::binary::pb::TypeResourceBinding)}, + {138, sizeof(::tint::core::ir::binary::pb::TypeExternalTexture)}, + {139, sizeof(::tint::core::ir::binary::pb::TypeSampler)}, + {144, sizeof(::tint::core::ir::binary::pb::TypeInputAttachment)}, + {149, sizeof(::tint::core::ir::binary::pb::TypeSubgroupMatrix)}, + {158, sizeof(::tint::core::ir::binary::pb::TypeBuffer)}, + {163, sizeof(::tint::core::ir::binary::pb::TypeTexelBuffer)}, + {170, sizeof(::tint::core::ir::binary::pb::Value)}, + {178, sizeof(::tint::core::ir::binary::pb::InstructionResult)}, + {185, sizeof(::tint::core::ir::binary::pb::FunctionParameter)}, + {194, sizeof(::tint::core::ir::binary::pb::BlockParameter)}, + {201, sizeof(::tint::core::ir::binary::pb::ConstantValue)}, + {207, sizeof(::tint::core::ir::binary::pb::ConstantValueScalar)}, + {215, sizeof(::tint::core::ir::binary::pb::ConstantValueComposite)}, + {222, sizeof(::tint::core::ir::binary::pb::ConstantValueSplat)}, + {231, sizeof(::tint::core::ir::binary::pb::Function)}, + {256, sizeof(::tint::core::ir::binary::pb::WorkgroupSize)}, + {265, sizeof(::tint::core::ir::binary::pb::Block)}, + {274, sizeof(::tint::core::ir::binary::pb::Instruction)}, + {306, sizeof(::tint::core::ir::binary::pb::InstructionReturn)}, + {307, sizeof(::tint::core::ir::binary::pb::InstructionUnary)}, + {312, sizeof(::tint::core::ir::binary::pb::InstructionBinary)}, + {317, sizeof(::tint::core::ir::binary::pb::InstructionBitcast)}, + {318, sizeof(::tint::core::ir::binary::pb::InstructionConstruct)}, + {319, sizeof(::tint::core::ir::binary::pb::InstructionDiscard)}, + {320, sizeof(::tint::core::ir::binary::pb::InstructionLet)}, + {321, sizeof(::tint::core::ir::binary::pb::InstructionVar)}, + {328, sizeof(::tint::core::ir::binary::pb::InstructionConvert)}, + {329, sizeof(::tint::core::ir::binary::pb::InstructionAccess)}, + {330, sizeof(::tint::core::ir::binary::pb::InstructionUserCall)}, + {331, sizeof(::tint::core::ir::binary::pb::InstructionBuiltinCall)}, + {338, sizeof(::tint::core::ir::binary::pb::InstructionLoad)}, + {339, sizeof(::tint::core::ir::binary::pb::InstructionStore)}, + {340, sizeof(::tint::core::ir::binary::pb::InstructionLoadVectorElement)}, + {341, sizeof(::tint::core::ir::binary::pb::InstructionStoreVectorElement)}, + {342, sizeof(::tint::core::ir::binary::pb::InstructionSwizzle)}, + {344, sizeof(::tint::core::ir::binary::pb::InstructionIf)}, + {351, sizeof(::tint::core::ir::binary::pb::InstructionSwitch)}, + {353, sizeof(::tint::core::ir::binary::pb::InstructionLoop)}, + {362, sizeof(::tint::core::ir::binary::pb::InstructionExitIf)}, + {363, sizeof(::tint::core::ir::binary::pb::InstructionExitSwitch)}, + {364, sizeof(::tint::core::ir::binary::pb::InstructionExitLoop)}, + {365, sizeof(::tint::core::ir::binary::pb::SwitchCase)}, + {374, sizeof(::tint::core::ir::binary::pb::BindingPoint)}, + {381, sizeof(::tint::core::ir::binary::pb::InstructionNextIteration)}, + {382, sizeof(::tint::core::ir::binary::pb::InstructionContinue)}, + {383, sizeof(::tint::core::ir::binary::pb::InstructionBreakIf)}, + {388, sizeof(::tint::core::ir::binary::pb::InstructionUnreachable)}, + {389, sizeof(::tint::core::ir::binary::pb::AttributesStructMember)}, + {404, sizeof(::tint::core::ir::binary::pb::AttributesFunctionParameter)}, + {419, sizeof(::tint::core::ir::binary::pb::Interpolation)}, +}; +static const ::_pb::Message* PROTOBUF_NONNULL const file_default_instances[] = { + &::tint::core::ir::binary::pb::_Module_default_instance_._instance, + &::tint::core::ir::binary::pb::_Type_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeVector_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeMatrix_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeArray_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeBindingArray_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypePointer_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeStruct_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeStructMember_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeAtomic_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeDepthTexture_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeSampledTexture_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeMultisampledTexture_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeDepthMultisampledTexture_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeStorageTexture_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeResourceBinding_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeExternalTexture_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeSampler_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeInputAttachment_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeSubgroupMatrix_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeBuffer_default_instance_._instance, + &::tint::core::ir::binary::pb::_TypeTexelBuffer_default_instance_._instance, + &::tint::core::ir::binary::pb::_Value_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionResult_default_instance_._instance, + &::tint::core::ir::binary::pb::_FunctionParameter_default_instance_._instance, + &::tint::core::ir::binary::pb::_BlockParameter_default_instance_._instance, + &::tint::core::ir::binary::pb::_ConstantValue_default_instance_._instance, + &::tint::core::ir::binary::pb::_ConstantValueScalar_default_instance_._instance, + &::tint::core::ir::binary::pb::_ConstantValueComposite_default_instance_._instance, + &::tint::core::ir::binary::pb::_ConstantValueSplat_default_instance_._instance, + &::tint::core::ir::binary::pb::_Function_default_instance_._instance, + &::tint::core::ir::binary::pb::_WorkgroupSize_default_instance_._instance, + &::tint::core::ir::binary::pb::_Block_default_instance_._instance, + &::tint::core::ir::binary::pb::_Instruction_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionReturn_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionUnary_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionBinary_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionBitcast_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionConstruct_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionDiscard_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionLet_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionVar_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionConvert_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionAccess_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionUserCall_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionBuiltinCall_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionLoad_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionStore_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionLoadVectorElement_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionStoreVectorElement_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionSwizzle_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionIf_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionSwitch_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionLoop_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionExitIf_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionExitSwitch_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionExitLoop_default_instance_._instance, + &::tint::core::ir::binary::pb::_SwitchCase_default_instance_._instance, + &::tint::core::ir::binary::pb::_BindingPoint_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionNextIteration_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionContinue_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionBreakIf_default_instance_._instance, + &::tint::core::ir::binary::pb::_InstructionUnreachable_default_instance_._instance, + &::tint::core::ir::binary::pb::_AttributesStructMember_default_instance_._instance, + &::tint::core::ir::binary::pb::_AttributesFunctionParameter_default_instance_._instance, + &::tint::core::ir::binary::pb::_Interpolation_default_instance_._instance, +}; +const char descriptor_table_protodef_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + "\n!src/tint/utils/protos/ir/ir.proto\022\026tin" + "t.core.ir.binary.pb\"\234\002\n\006Module\022+\n\005types\030" + "\001 \003(\0132\034.tint.core.ir.binary.pb.Type\022-\n\006v" + "alues\030\002 \003(\0132\035.tint.core.ir.binary.pb.Val" + "ue\022>\n\017constant_values\030\003 \003(\0132%.tint.core." + "ir.binary.pb.ConstantValue\0223\n\tfunctions\030" + "\004 \003(\0132 .tint.core.ir.binary.pb.Function\022" + "-\n\006blocks\030\005 \003(\0132\035.tint.core.ir.binary.pb" + ".Block\022\022\n\nroot_block\030\006 \001(\r\"\314\013\n\004Type\0222\n\005b" + "asic\030\001 \001(\0162!.tint.core.ir.binary.pb.Type" + "BasicH\000\0224\n\006vector\030\002 \001(\0132\".tint.core.ir.b" + "inary.pb.TypeVectorH\000\0224\n\006matrix\030\003 \001(\0132\"." + "tint.core.ir.binary.pb.TypeMatrixH\000\0222\n\005a" + "rray\030\004 \001(\0132!.tint.core.ir.binary.pb.Type" + "ArrayH\000\0226\n\007pointer\030\005 \001(\0132#.tint.core.ir." + "binary.pb.TypePointerH\000\0224\n\006struct\030\006 \001(\0132" + "\".tint.core.ir.binary.pb.TypeStructH\000\0224\n" + "\006atomic\030\007 \001(\0132\".tint.core.ir.binary.pb.T" + "ypeAtomicH\000\022A\n\rdepth_texture\030\010 \001(\0132(.tin" + "t.core.ir.binary.pb.TypeDepthTextureH\000\022E" + "\n\017sampled_texture\030\t \001(\0132*.tint.core.ir.b" + "inary.pb.TypeSampledTextureH\000\022O\n\024multisa" + "mpled_texture\030\n \001(\0132/.tint.core.ir.binar" + "y.pb.TypeMultisampledTextureH\000\022Z\n\032depth_" + "multisampled_texture\030\013 \001(\01324.tint.core.i" + "r.binary.pb.TypeDepthMultisampledTexture" + "H\000\022E\n\017storage_texture\030\014 \001(\0132*.tint.core." + "ir.binary.pb.TypeStorageTextureH\000\022G\n\020ext" + "ernal_texture\030\r \001(\0132+.tint.core.ir.binar" + "y.pb.TypeExternalTextureH\000\0226\n\007sampler\030\016 " + "\001(\0132#.tint.core.ir.binary.pb.TypeSampler" + "H\000\022G\n\020input_attachment\030\017 \001(\0132+.tint.core" + ".ir.binary.pb.TypeInputAttachmentH\000\022J\n\024s" + "ubgroup_matrix_left\030\020 \001(\0132*.tint.core.ir" + ".binary.pb.TypeSubgroupMatrixH\000\022K\n\025subgr" + "oup_matrix_right\030\021 \001(\0132*.tint.core.ir.bi" + "nary.pb.TypeSubgroupMatrixH\000\022L\n\026subgroup" + "_matrix_result\030\022 \001(\0132*.tint.core.ir.bina" + "ry.pb.TypeSubgroupMatrixH\000\022C\n\016builtin_st" + "ruct\030\023 \001(\0162).tint.core.ir.binary.pb.Type" + "BuiltinStructH\000\022A\n\rbinding_array\030\024 \001(\0132(" + ".tint.core.ir.binary.pb.TypeBindingArray" + "H\000\022\?\n\014texel_buffer\030\025 \001(\0132\'.tint.core.ir." + "binary.pb.TypeTexelBufferH\000\0224\n\006buffer\030\027 " + "\001(\0132\".tint.core.ir.binary.pb.TypeBufferH" + "\000B\006\n\004kindJ\004\010\026\020\027R\020resource_binding\"1\n\nTyp" + "eVector\022\r\n\005width\030\001 \001(\r\022\024\n\014element_type\030\002" + " \001(\r\"I\n\nTypeMatrix\022\023\n\013num_columns\030\001 \001(\r\022" + "\020\n\010num_rows\030\002 \001(\r\022\024\n\014element_type\030\003 \001(\r\"" + "9\n\tTypeArray\022\017\n\007element\030\001 \001(\r\022\r\n\005count\030\003" + " \001(\rJ\004\010\002\020\003R\006stride\"2\n\020TypeBindingArray\022\017" + "\n\007element\030\001 \001(\r\022\r\n\005count\030\002 \001(\r\"\225\001\n\013TypeP" + "ointer\022;\n\raddress_space\030\001 \001(\0162$.tint.cor" + "e.ir.binary.pb.AddressSpace\022\022\n\nstore_typ" + "e\030\002 \001(\r\0225\n\006access\030\003 \001(\0162%.tint.core.ir.b" + "inary.pb.AccessControl\"T\n\nTypeStruct\022\014\n\004" + "name\030\001 \001(\t\0228\n\006member\030\002 \003(\0132(.tint.core.i" + "r.binary.pb.TypeStructMember\"\243\001\n\020TypeStr" + "uctMember\022\014\n\004name\030\001 \001(\t\022\014\n\004type\030\002 \001(\r\022\014\n" + "\004size\030\003 \001(\r\022\r\n\005align\030\004 \001(\r\022G\n\nattributes" + "\030\005 \001(\0132..tint.core.ir.binary.pb.Attribut" + "esStructMemberH\000\210\001\001B\r\n\013_attributes\"\032\n\nTy" + "peAtomic\022\014\n\004type\030\001 \001(\r\"O\n\020TypeDepthTextu" + "re\022;\n\tdimension\030\001 \001(\0162(.tint.core.ir.bin" + "ary.pb.TextureDimension\"c\n\022TypeSampledTe" + "xture\022;\n\tdimension\030\001 \001(\0162(.tint.core.ir." + "binary.pb.TextureDimension\022\020\n\010sub_type\030\002" + " \001(\r\"h\n\027TypeMultisampledTexture\022;\n\tdimen" + "sion\030\001 \001(\0162(.tint.core.ir.binary.pb.Text" + "ureDimension\022\020\n\010sub_type\030\002 \001(\r\"[\n\034TypeDe" + "pthMultisampledTexture\022;\n\tdimension\030\001 \001(" + "\0162(.tint.core.ir.binary.pb.TextureDimens" + "ion\"\303\001\n\022TypeStorageTexture\022;\n\tdimension\030" + "\001 \001(\0162(.tint.core.ir.binary.pb.TextureDi" + "mension\0229\n\014texel_format\030\002 \001(\0162#.tint.cor" + "e.ir.binary.pb.TexelFormat\0225\n\006access\030\003 \001" + "(\0162%.tint.core.ir.binary.pb.AccessContro" + "l\"\025\n\023TypeResourceBinding\"\025\n\023TypeExternal" + "Texture\"@\n\013TypeSampler\0221\n\004kind\030\001 \001(\0162#.t" + "int.core.ir.binary.pb.SamplerKind\"\'\n\023Typ" + "eInputAttachment\022\020\n\010sub_type\030\001 \001(\r\"E\n\022Ty" + "peSubgroupMatrix\022\020\n\010sub_type\030\001 \001(\r\022\014\n\004ro" + "ws\030\002 \001(\r\022\017\n\007columns\030\003 \001(\r\"\033\n\nTypeBuffer\022" + "\r\n\005count\030\001 \001(\r\"\203\001\n\017TypeTexelBuffer\0229\n\014te" + "xel_format\030\001 \001(\0162#.tint.core.ir.binary.p" + "b.TexelFormat\0225\n\006access\030\002 \001(\0162%.tint.cor" + "e.ir.binary.pb.AccessControl\"\214\002\n\005Value\022\022" + "\n\010function\030\001 \001(\rH\000\022G\n\022instruction_result" + "\030\002 \001(\0132).tint.core.ir.binary.pb.Instruct" + "ionResultH\000\022G\n\022function_parameter\030\003 \001(\0132" + ").tint.core.ir.binary.pb.FunctionParamet" + "erH\000\022A\n\017block_parameter\030\004 \001(\0132&.tint.cor" + "e.ir.binary.pb.BlockParameterH\000\022\022\n\010const" + "ant\030\005 \001(\rH\000B\006\n\004kind\"=\n\021InstructionResult" + "\022\014\n\004type\030\001 \001(\r\022\021\n\004name\030\002 \001(\tH\000\210\001\001B\007\n\005_na" + "me\"\232\001\n\021FunctionParameter\022\014\n\004type\030\001 \001(\r\022\021" + "\n\004name\030\002 \001(\tH\000\210\001\001\022L\n\nattributes\030\003 \001(\01323." + "tint.core.ir.binary.pb.AttributesFunctio" + "nParameterH\001\210\001\001B\007\n\005_nameB\r\n\013_attributes\"" + ":\n\016BlockParameter\022\014\n\004type\030\001 \001(\r\022\021\n\004name\030" + "\002 \001(\tH\000\210\001\001B\007\n\005_name\"\330\001\n\rConstantValue\022=\n" + "\006scalar\030\001 \001(\0132+.tint.core.ir.binary.pb.C" + "onstantValueScalarH\000\022C\n\tcomposite\030\002 \001(\0132" + "..tint.core.ir.binary.pb.ConstantValueCo" + "mpositeH\000\022;\n\005splat\030\003 \001(\0132*.tint.core.ir." + "binary.pb.ConstantValueSplatH\000B\006\n\004kind\"i" + "\n\023ConstantValueScalar\022\016\n\004bool\030\001 \001(\010H\000\022\r\n" + "\003i32\030\002 \001(\005H\000\022\r\n\003u32\030\003 \001(\rH\000\022\r\n\003f32\030\004 \001(\002" + "H\000\022\r\n\003f16\030\005 \001(\002H\000B\006\n\004kind\"8\n\026ConstantVal" + "ueComposite\022\014\n\004type\030\001 \001(\r\022\020\n\010elements\030\002 " + "\003(\r\"C\n\022ConstantValueSplat\022\014\n\004type\030\001 \001(\r\022" + "\020\n\010elements\030\002 \001(\r\022\r\n\005count\030\003 \001(\r\"\277\004\n\010Fun" + "ction\022\023\n\013return_type\030\001 \001(\r\022\r\n\005block\030\002 \001(" + "\r\022\021\n\004name\030\003 \001(\tH\000\210\001\001\022B\n\016pipeline_stage\030\004" + " \001(\0162%.tint.core.ir.binary.pb.PipelineSt" + "ageH\001\210\001\001\022B\n\016workgroup_size\030\005 \001(\0132%.tint." + "core.ir.binary.pb.WorkgroupSizeH\002\210\001\001\022\022\n\n" + "parameters\030\006 \003(\r\022\034\n\017return_location\030\007 \001(" + "\rH\003\210\001\001\022H\n\024return_interpolation\030\010 \001(\0132%.t" + "int.core.ir.binary.pb.InterpolationH\004\210\001\001" + "\022A\n\016return_builtin\030\t \001(\0162$.tint.core.ir." + "binary.pb.BuiltinValueH\005\210\001\001\022\030\n\020return_in" + "variant\030\n \001(\010\022\032\n\rsubgroup_size\030\013 \001(\rH\006\210\001" + "\001B\007\n\005_nameB\021\n\017_pipeline_stageB\021\n\017_workgr" + "oup_sizeB\022\n\020_return_locationB\027\n\025_return_" + "interpolationB\021\n\017_return_builtinB\020\n\016_sub" + "group_size\"0\n\rWorkgroupSize\022\t\n\001x\030\001 \001(\r\022\t" + "\n\001y\030\002 \001(\r\022\t\n\001z\030\003 \001(\r\"k\n\005Block\022\022\n\nparamet" + "ers\030\001 \003(\r\0229\n\014instructions\030\002 \003(\0132#.tint.c" + "ore.ir.binary.pb.Instruction\022\023\n\013is_multi" + "_in\030\003 \001(\010\"\206\016\n\013Instruction\022\020\n\010operands\030\001 " + "\003(\r\022\017\n\007results\030\002 \003(\r\022;\n\006return\030\003 \001(\0132).t" + "int.core.ir.binary.pb.InstructionReturnH" + "\000\0229\n\005unary\030\004 \001(\0132(.tint.core.ir.binary.p" + "b.InstructionUnaryH\000\022;\n\006binary\030\005 \001(\0132).t" + "int.core.ir.binary.pb.InstructionBinaryH" + "\000\022=\n\007discard\030\006 \001(\0132*.tint.core.ir.binary" + ".pb.InstructionDiscardH\000\0225\n\003let\030\007 \001(\0132&." + "tint.core.ir.binary.pb.InstructionLetH\000\022" + "5\n\003var\030\010 \001(\0132&.tint.core.ir.binary.pb.In" + "structionVarH\000\022=\n\007bitcast\030\t \001(\0132*.tint.c" + "ore.ir.binary.pb.InstructionBitcastH\000\022A\n" + "\tconstruct\030\n \001(\0132,.tint.core.ir.binary.p" + "b.InstructionConstructH\000\022=\n\007convert\030\013 \001(" + "\0132*.tint.core.ir.binary.pb.InstructionCo" + "nvertH\000\022;\n\006access\030\014 \001(\0132).tint.core.ir.b" + "inary.pb.InstructionAccessH\000\022@\n\tuser_cal" + "l\030\r \001(\0132+.tint.core.ir.binary.pb.Instruc" + "tionUserCallH\000\022F\n\014builtin_call\030\016 \001(\0132..t" + "int.core.ir.binary.pb.InstructionBuiltin" + "CallH\000\0227\n\004load\030\017 \001(\0132\'.tint.core.ir.bina" + "ry.pb.InstructionLoadH\000\0229\n\005store\030\020 \001(\0132(" + ".tint.core.ir.binary.pb.InstructionStore" + "H\000\022S\n\023load_vector_element\030\021 \001(\01324.tint.c" + "ore.ir.binary.pb.InstructionLoadVectorEl" + "ementH\000\022U\n\024store_vector_element\030\022 \001(\01325." + "tint.core.ir.binary.pb.InstructionStoreV" + "ectorElementH\000\022=\n\007swizzle\030\023 \001(\0132*.tint.c" + "ore.ir.binary.pb.InstructionSwizzleH\000\0223\n" + "\002if\030\024 \001(\0132%.tint.core.ir.binary.pb.Instr" + "uctionIfH\000\022;\n\006switch\030\025 \001(\0132).tint.core.i" + "r.binary.pb.InstructionSwitchH\000\0227\n\004loop\030" + "\026 \001(\0132\'.tint.core.ir.binary.pb.Instructi" + "onLoopH\000\022<\n\007exit_if\030\027 \001(\0132).tint.core.ir" + ".binary.pb.InstructionExitIfH\000\022D\n\013exit_s" + "witch\030\030 \001(\0132-.tint.core.ir.binary.pb.Ins" + "tructionExitSwitchH\000\022@\n\texit_loop\030\031 \001(\0132" + "+.tint.core.ir.binary.pb.InstructionExit" + "LoopH\000\022J\n\016next_iteration\030\032 \001(\01320.tint.co" + "re.ir.binary.pb.InstructionNextIteration" + "H\000\022\?\n\010continue\030\033 \001(\0132+.tint.core.ir.bina" + "ry.pb.InstructionContinueH\000\022>\n\010break_if\030" + "\034 \001(\0132*.tint.core.ir.binary.pb.Instructi" + "onBreakIfH\000\022E\n\013unreachable\030\035 \001(\0132..tint." + "core.ir.binary.pb.InstructionUnreachable" + "H\000B\006\n\004kind\"\023\n\021InstructionReturn\"\?\n\020Instr" + "uctionUnary\022+\n\002op\030\001 \001(\0162\037.tint.core.ir.b" + "inary.pb.UnaryOp\"A\n\021InstructionBinary\022,\n" + "\002op\030\001 \001(\0162 .tint.core.ir.binary.pb.Binar" + "yOp\"\024\n\022InstructionBitcast\"\026\n\024Instruction" + "Construct\"\024\n\022InstructionDiscard\"\020\n\016Instr" + "uctionLet\"\244\001\n\016InstructionVar\022@\n\rbinding_" + "point\030\001 \001(\0132$.tint.core.ir.binary.pb.Bin" + "dingPointH\000\210\001\001\022#\n\026input_attachment_index" + "\030\002 \001(\rH\001\210\001\001B\020\n\016_binding_pointB\031\n\027_input_" + "attachment_index\"\024\n\022InstructionConvert\"\023" + "\n\021InstructionAccess\"\025\n\023InstructionUserCa" + "ll\"n\n\026InstructionBuiltinCall\0222\n\007builtin\030" + "\001 \001(\0162!.tint.core.ir.binary.pb.BuiltinFn" + "\022 \n\030explicit_template_params\030\002 \003(\r\"\021\n\017In" + "structionLoad\"\022\n\020InstructionStore\"\036\n\034Ins" + "tructionLoadVectorElement\"\037\n\035Instruction" + "StoreVectorElement\"%\n\022InstructionSwizzle" + "\022\017\n\007indices\030\001 \003(\r\"I\n\rInstructionIf\022\021\n\004tr" + "ue\030\001 \001(\rH\000\210\001\001\022\022\n\005false\030\002 \001(\rH\001\210\001\001B\007\n\005_tr" + "ueB\010\n\006_false\"F\n\021InstructionSwitch\0221\n\005cas" + "es\030\001 \003(\0132\".tint.core.ir.binary.pb.Switch" + "Case\"\177\n\017InstructionLoop\022\030\n\013initializer\030\001" + " \001(\rH\000\210\001\001\022\021\n\004body\030\002 \001(\rH\001\210\001\001\022\027\n\ncontinui" + "ng\030\003 \001(\rH\002\210\001\001B\016\n\014_initializerB\007\n\005_bodyB\r" + "\n\013_continuing\"\023\n\021InstructionExitIf\"\027\n\025In" + "structionExitSwitch\"\025\n\023InstructionExitLo" + "op\"B\n\nSwitchCase\022\r\n\005block\030\001 \001(\r\022\021\n\tselec" + "tors\030\002 \003(\r\022\022\n\nis_default\030\003 \001(\010\".\n\014Bindin" + "gPoint\022\r\n\005group\030\001 \001(\r\022\017\n\007binding\030\002 \001(\r\"\032" + "\n\030InstructionNextIteration\"\025\n\023Instructio" + "nContinue\"2\n\022InstructionBreakIf\022\034\n\024num_n" + "ext_iter_values\030\001 \001(\r\"\030\n\026InstructionUnre" + "achable\"\260\002\n\026AttributesStructMember\022\025\n\010lo" + "cation\030\001 \001(\rH\000\210\001\001\022\026\n\tblend_src\030\002 \001(\rH\001\210\001" + "\001\022\022\n\005color\030\003 \001(\rH\002\210\001\001\022:\n\007builtin\030\004 \001(\0162$" + ".tint.core.ir.binary.pb.BuiltinValueH\003\210\001" + "\001\022A\n\rinterpolation\030\005 \001(\0132%.tint.core.ir." + "binary.pb.InterpolationH\004\210\001\001\022\021\n\tinvarian" + "t\030\006 \001(\010B\013\n\t_locationB\014\n\n_blend_srcB\010\n\006_c" + "olorB\n\n\010_builtinB\020\n\016_interpolation\"\343\002\n\033A" + "ttributesFunctionParameter\022:\n\007builtin\030\001 " + "\001(\0162$.tint.core.ir.binary.pb.BuiltinValu" + "eH\000\210\001\001\022\025\n\010location\030\002 \001(\rH\001\210\001\001\022\022\n\005color\030\003" + " \001(\rH\002\210\001\001\022A\n\rinterpolation\030\004 \001(\0132%.tint." + "core.ir.binary.pb.InterpolationH\003\210\001\001\022@\n\r" + "binding_point\030\005 \001(\0132$.tint.core.ir.binar" + "y.pb.BindingPointH\004\210\001\001\022\021\n\tinvariant\030\006 \001(" + "\010B\n\n\010_builtinB\013\n\t_locationB\010\n\006_colorB\020\n\016" + "_interpolationB\020\n\016_binding_point\"\233\001\n\rInt" + "erpolation\0227\n\004type\030\001 \001(\0162).tint.core.ir." + "binary.pb.InterpolationType\022D\n\010sampling\030" + "\002 \001(\0162-.tint.core.ir.binary.pb.Interpola" + "tionSamplingH\000\210\001\001B\013\n\t_sampling*S\n\tTypeBa" + "sic\022\010\n\004void\020\000\022\010\n\004bool\020\001\022\007\n\003i32\020\002\022\007\n\003u32\020" + "\003\022\007\n\003f32\020\004\022\007\n\003f16\020\005\022\006\n\002i8\020\006\022\006\n\002u8\020\007*\303\003\n\021" + "TypeBuiltinStruct\022\"\n\036AtomicCompareExchan" + "geResultI32\020\000\022\"\n\036AtomicCompareExchangeRe" + "sultU32\020\001\022\022\n\016FrexpResultF16\020\002\022\022\n\016FrexpRe" + "sultF32\020\003\022\026\n\022FrexpResultVec2F16\020\004\022\026\n\022Fre" + "xpResultVec2F32\020\005\022\026\n\022FrexpResultVec3F16\020" + "\006\022\026\n\022FrexpResultVec3F32\020\007\022\026\n\022FrexpResult" + "Vec4F16\020\010\022\026\n\022FrexpResultVec4F32\020\t\022\021\n\rMod" + "fResultF16\020\n\022\021\n\rModfResultF32\020\013\022\025\n\021ModfR" + "esultVec2F16\020\014\022\025\n\021ModfResultVec2F32\020\r\022\025\n" + "\021ModfResultVec3F16\020\016\022\025\n\021ModfResultVec3F3" + "2\020\017\022\025\n\021ModfResultVec4F16\020\020\022\025\n\021ModfResult" + "Vec4F32\020\021*6\n\rPipelineStage\022\013\n\007Compute\020\000\022" + "\014\n\010Fragment\020\001\022\n\n\006Vertex\020\002*~\n\014AddressSpac" + "e\022\014\n\010function\020\000\022\n\n\006handle\020\001\022\017\n\013pixel_loc" + "al\020\002\022\013\n\007private\020\003\022\r\n\timmediate\020\004\022\013\n\007stor" + "age\020\005\022\013\n\007uniform\020\006\022\r\n\tworkgroup\020\007*4\n\rAcc" + "essControl\022\010\n\004read\020\000\022\t\n\005write\020\001\022\016\n\nread_" + "write\020\002*Q\n\007UnaryOp\022\016\n\ncomplement\020\000\022\014\n\010ne" + "gation\020\001\022\016\n\naddress_of\020\002\022\017\n\013indirection\020" + "\003\022\007\n\003not\020\004*\216\002\n\010BinaryOp\022\010\n\004add_\020\000\022\014\n\010sub" + "tract\020\001\022\014\n\010multiply\020\002\022\n\n\006divide\020\003\022\n\n\006mod" + "ulo\020\004\022\007\n\003and\020\005\022\007\n\003or_\020\006\022\010\n\004xor_\020\007\022\t\n\005equ" + "al\020\010\022\r\n\tnot_equal\020\t\022\r\n\tless_than\020\n\022\020\n\014gr" + "eater_than\020\013\022\023\n\017less_than_equal\020\014\022\026\n\022gre" + "ater_than_equal\020\r\022\016\n\nshift_left\020\016\022\017\n\013shi" + "ft_right\020\017\022\017\n\013logical_and\020\020\022\016\n\nlogical_o" + "r\020\021*V\n\020TextureDimension\022\007\n\003_1d\020\000\022\007\n\003_2d\020" + "\001\022\r\n\t_2d_array\020\002\022\007\n\003_3d\020\003\022\010\n\004cube\020\004\022\016\n\nc" + "ube_array\020\005*\205\005\n\013TexelFormat\022\017\n\013bgra8_uno" + "rm\020\000\022\014\n\010r8_unorm\020\001\022\r\n\tr32_float\020\002\022\014\n\010r32" + "_sint\020\003\022\014\n\010r32_uint\020\004\022\016\n\nrg32_float\020\005\022\r\n" + "\trg32_sint\020\006\022\r\n\trg32_uint\020\007\022\020\n\014rgba16_fl" + "oat\020\010\022\017\n\013rgba16_sint\020\t\022\017\n\013rgba16_uint\020\n\022" + "\020\n\014rgba32_float\020\013\022\017\n\013rgba32_sint\020\014\022\017\n\013rg" + "ba32_uint\020\r\022\016\n\nrgba8_sint\020\016\022\017\n\013rgba8_sno" + "rm\020\017\022\016\n\nrgba8_uint\020\020\022\017\n\013rgba8_unorm\020\021\022\014\n" + "\010r8_snorm\020\022\022\013\n\007r8_uint\020\023\022\013\n\007r8_sint\020\024\022\r\n" + "\trg8_unorm\020\025\022\r\n\trg8_snorm\020\026\022\014\n\010rg8_uint\020" + "\027\022\014\n\010rg8_sint\020\030\022\014\n\010r16_uint\020\031\022\014\n\010r16_sin" + "t\020\032\022\r\n\tr16_float\020\033\022\r\n\trg16_uint\020\034\022\r\n\trg1" + "6_sint\020\035\022\016\n\nrg16_float\020\036\022\020\n\014rgb10a2_uint" + "\020\037\022\021\n\rrgb10a2_unorm\020 \022\022\n\016rg11b10_ufloat\020" + "!\022\r\n\tr16_unorm\020\"\022\r\n\tr16_snorm\020#\022\016\n\nrg16_" + "unorm\020$\022\016\n\nrg16_snorm\020%\022\020\n\014rgba16_unorm\020" + "&\022\020\n\014rgba16_snorm\020\'**\n\013SamplerKind\022\013\n\007sa" + "mpler\020\000\022\016\n\ncomparison\020\001*:\n\021Interpolation" + "Type\022\010\n\004flat\020\000\022\n\n\006linear\020\001\022\017\n\013perspectiv" + "e\020\002*T\n\025InterpolationSampling\022\n\n\006center\020\000" + "\022\014\n\010centroid\020\001\022\n\n\006sample\020\002\022\t\n\005first\020\003\022\n\n" + "\006either\020\004*\262\003\n\014BuiltinValue\022\016\n\npoint_size" + "\020\000\022\016\n\nfrag_depth\020\001\022\020\n\014front_facing\020\002\022\030\n\024" + "global_invocation_id\020\003\022\022\n\016instance_index" + "\020\004\022\027\n\023local_invocation_id\020\005\022\032\n\026local_inv" + "ocation_index\020\006\022\022\n\016num_workgroups\020\007\022\014\n\010p" + "osition\020\010\022\020\n\014sample_index\020\t\022\017\n\013sample_ma" + "sk\020\n\022\032\n\026subgroup_invocation_id\020\013\022\021\n\rsubg" + "roup_size\020\014\022\020\n\014vertex_index\020\r\022\020\n\014workgro" + "up_id\020\016\022\022\n\016clip_distances\020\017\022\021\n\rcull_dist" + "ance\020\020\022\017\n\013subgroup_id\020\021\022\023\n\017primitive_ind" + "ex\020\022\022\025\n\021barycentric_coord\020\023\022\021\n\rnum_subgr" + "oups\020\024*\312\026\n\tBuiltinFn\022\007\n\003abs\020\000\022\010\n\004acos\020\001\022" + "\t\n\005acosh\020\002\022\007\n\003all\020\003\022\007\n\003any\020\004\022\020\n\014array_le" + "ngth\020\005\022\010\n\004asin\020\006\022\t\n\005asinh\020\007\022\010\n\004atan\020\010\022\t\n" + "\005atan2\020\t\022\t\n\005atanh\020\n\022\010\n\004ceil\020\013\022\t\n\005clamp\020\014" + "\022\007\n\003cos\020\r\022\010\n\004cosh\020\016\022\027\n\023count_leading_zer" + "os\020\017\022\022\n\016count_one_bits\020\020\022\030\n\024count_traili" + "ng_zeros\020\021\022\t\n\005cross\020\022\022\013\n\007degrees\020\023\022\017\n\013de" + "terminant\020\024\022\014\n\010distance\020\025\022\007\n\003dot\020\026\022\021\n\rdo" + "t4i8_packed\020\027\022\021\n\rdot4u8_packed\020\030\022\010\n\004dpdx" + "\020\031\022\017\n\013dpdx_coarse\020\032\022\r\n\tdpdx_fine\020\033\022\010\n\004dp" + "dy\020\034\022\017\n\013dpdy_coarse\020\035\022\r\n\tdpdy_fine\020\036\022\007\n\003" + "exp\020\037\022\010\n\004exp2\020 \022\020\n\014extract_bits\020!\022\020\n\014fac" + "e_forward\020\"\022\025\n\021first_leading_bit\020#\022\026\n\022fi" + "rst_trailing_bit\020$\022\t\n\005floor\020%\022\007\n\003fma\020&\022\t" + "\n\005fract\020\'\022\t\n\005frexp\020(\022\n\n\006fwidth\020)\022\021\n\rfwid" + "th_coarse\020*\022\017\n\013fwidth_fine\020+\022\017\n\013insert_b" + "its\020,\022\020\n\014inverse_sqrt\020-\022\t\n\005ldexp\020.\022\n\n\006le" + "ngth\020/\022\007\n\003log\0200\022\010\n\004log2\0201\022\007\n\003max\0202\022\007\n\003mi" + "n\0203\022\007\n\003mix\0204\022\010\n\004modf\0205\022\r\n\tnormalize\0206\022\022\n" + "\016pack2x16_float\0207\022\022\n\016pack2x16_snorm\0208\022\022\n" + "\016pack2x16_unorm\0209\022\021\n\rpack4x8_snorm\020:\022\021\n\r" + "pack4x8_unorm\020;\022\014\n\010pack4xi8\020<\022\014\n\010pack4xu" + "8\020=\022\022\n\016pack4xi8_clamp\020>\022\022\n\016pack4xu8_clam" + "p\020\?\022\007\n\003pow\020@\022\023\n\017quantize_to_f16\020A\022\013\n\007rad" + "ians\020B\022\013\n\007reflect\020C\022\013\n\007refract\020D\022\020\n\014reve" + "rse_bits\020E\022\t\n\005round\020F\022\014\n\010saturate\020G\022\n\n\006s" + "elect\020H\022\010\n\004sign\020I\022\007\n\003sin\020J\022\010\n\004sinh\020K\022\016\n\n" + "smoothstep\020L\022\010\n\004sqrt\020M\022\010\n\004step\020N\022\023\n\017stor" + "age_barrier\020O\022\007\n\003tan\020P\022\010\n\004tanh\020Q\022\r\n\ttran" + "spose\020R\022\t\n\005trunc\020S\022\024\n\020unpack2x16_float\020T" + "\022\024\n\020unpack2x16_snorm\020U\022\024\n\020unpack2x16_uno" + "rm\020V\022\023\n\017unpack4x8_snorm\020W\022\023\n\017unpack4x8_u" + "norm\020X\022\016\n\nunpack4xi8\020Y\022\016\n\nunpack4xu8\020Z\022\025" + "\n\021workgroup_barrier\020[\022\023\n\017texture_barrier" + "\020\\\022\026\n\022texture_dimensions\020]\022\022\n\016texture_ga" + "ther\020^\022\032\n\026texture_gather_compare\020_\022\026\n\022te" + "xture_num_layers\020`\022\026\n\022texture_num_levels" + "\020a\022\027\n\023texture_num_samples\020b\022\022\n\016texture_s" + "ample\020c\022\027\n\023texture_sample_bias\020d\022\032\n\026text" + "ure_sample_compare\020e\022 \n\034texture_sample_c" + "ompare_level\020f\022\027\n\023texture_sample_grad\020g\022" + "\030\n\024texture_sample_level\020h\022%\n!texture_sam" + "ple_base_clamp_to_edge\020i\022\021\n\rtexture_stor" + "e\020j\022\020\n\014texture_load\020k\022\017\n\013atomic_load\020l\022\020" + "\n\014atomic_store\020m\022\016\n\natomic_add\020n\022\016\n\natom" + "ic_sub\020o\022\016\n\natomic_max\020p\022\016\n\natomic_min\020q" + "\022\016\n\natomic_and\020r\022\r\n\tatomic_or\020s\022\016\n\natomi" + "c_xor\020t\022\023\n\017atomic_exchange\020u\022 \n\034atomic_c" + "ompare_exchange_weak\020v\022\023\n\017subgroup_ballo" + "t\020w\022\026\n\022subgroup_broadcast\020x\022\031\n\025input_att" + "achment_load\020y\022\020\n\014subgroup_add\020z\022\032\n\026subg" + "roup_exclusive_add\020{\022\020\n\014subgroup_mul\020|\022\032" + "\n\026subgroup_exclusive_mul\020}\022\020\n\014subgroup_a" + "nd\020~\022\017\n\013subgroup_or\020\177\022\021\n\014subgroup_xor\020\200\001" + "\022\021\n\014subgroup_min\020\201\001\022\021\n\014subgroup_max\020\202\001\022\021" + "\n\014subgroup_any\020\203\001\022\021\n\014subgroup_all\020\204\001\022\023\n\016" + "subgroup_elect\020\205\001\022\035\n\030subgroup_broadcast_" + "first\020\206\001\022\025\n\020subgroup_shuffle\020\207\001\022\031\n\024subgr" + "oup_shuffle_xor\020\210\001\022\030\n\023subgroup_shuffle_u" + "p\020\211\001\022\032\n\025subgroup_shuffle_down\020\212\001\022\023\n\016quad" + "_broadcast\020\213\001\022\020\n\013quad_swap_x\020\214\001\022\020\n\013quad_" + "swap_y\020\215\001\022\027\n\022quad_swap_diagonal\020\216\001\022\033\n\026su" + "bgroup_inclusive_add\020\217\001\022\033\n\026subgroup_incl" + "usive_mul\020\220\001\022\031\n\024subgroup_matrix_load\020\221\001\022" + "\032\n\025subgroup_matrix_store\020\222\001\022\035\n\030subgroup_" + "matrix_multiply\020\223\001\022(\n#subgroup_matrix_mu" + "ltiply_accumulate\020\224\001\022\n\n\005print\020\225\001\022\037\n\032subg" + "roup_matrix_scalar_add\020\230\001\022$\n\037subgroup_ma" + "trix_scalar_multiply\020\231\001\022$\n\037subgroup_matr" + "ix_scalar_subtract\020\232\001\022\021\n\014has_resource\020\233\001" + "\022\021\n\014get_resource\020\234\001\022\020\n\013buffer_view\020\235\001\022\022\n" + "\rbuffer_length\020\236\001\"\006\010\226\001\020\226\001\"\006\010\227\001\020\227\001*\013has_b" + "inding*\013get_bindingb\006proto3" +}; +static ::absl::once_flag descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto_once; +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto = { + false, + false, + 14547, + descriptor_table_protodef_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + "src/tint/utils/protos/ir/ir.proto", + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto_once, + nullptr, + 0, + 66, + schemas, + file_default_instances, + TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto::offsets, + file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + file_level_service_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, +}; +namespace tint { +namespace core { +namespace ir { +namespace binary { +namespace pb { +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TypeBasic_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[0]; +} +PROTOBUF_CONSTINIT const uint32_t TypeBasic_internal_data_[] = { + 524288u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TypeBuiltinStruct_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[1]; +} +PROTOBUF_CONSTINIT const uint32_t TypeBuiltinStruct_internal_data_[] = { + 1179648u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL PipelineStage_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[2]; +} +PROTOBUF_CONSTINIT const uint32_t PipelineStage_internal_data_[] = { + 196608u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL AddressSpace_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[3]; +} +PROTOBUF_CONSTINIT const uint32_t AddressSpace_internal_data_[] = { + 524288u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL AccessControl_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[4]; +} +PROTOBUF_CONSTINIT const uint32_t AccessControl_internal_data_[] = { + 196608u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL UnaryOp_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[5]; +} +PROTOBUF_CONSTINIT const uint32_t UnaryOp_internal_data_[] = { + 327680u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL BinaryOp_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[6]; +} +PROTOBUF_CONSTINIT const uint32_t BinaryOp_internal_data_[] = { + 1179648u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TextureDimension_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[7]; +} +PROTOBUF_CONSTINIT const uint32_t TextureDimension_internal_data_[] = { + 393216u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TexelFormat_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[8]; +} +PROTOBUF_CONSTINIT const uint32_t TexelFormat_internal_data_[] = { + 2621440u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL SamplerKind_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[9]; +} +PROTOBUF_CONSTINIT const uint32_t SamplerKind_internal_data_[] = { + 131072u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL InterpolationType_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[10]; +} +PROTOBUF_CONSTINIT const uint32_t InterpolationType_internal_data_[] = { + 196608u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL InterpolationSampling_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[11]; +} +PROTOBUF_CONSTINIT const uint32_t InterpolationSampling_internal_data_[] = { + 327680u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL BuiltinValue_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[12]; +} +PROTOBUF_CONSTINIT const uint32_t BuiltinValue_internal_data_[] = { + 1376256u, 0u, }; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL BuiltinFn_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto); + return file_level_enum_descriptors_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto[13]; +} +PROTOBUF_CONSTINIT const uint32_t BuiltinFn_internal_data_[] = { + 9830400u, 32u, 508u, }; +// =================================================================== + +class Module::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Module, _impl_._has_bits_); +}; + +Module::Module(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Module_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Module) +} +PROTOBUF_NDEBUG_INLINE Module::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::Module& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + types_{visibility, arena, from.types_}, + values_{visibility, arena, from.values_}, + constant_values_{visibility, arena, from.constant_values_}, + functions_{visibility, arena, from.functions_}, + blocks_{visibility, arena, from.blocks_} {} + +Module::Module( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Module& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Module_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Module* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.root_block_ = from._impl_.root_block_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.Module) +} +PROTOBUF_NDEBUG_INLINE Module::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + types_{visibility, arena}, + values_{visibility, arena}, + constant_values_{visibility, arena}, + functions_{visibility, arena}, + blocks_{visibility, arena} {} + +inline void Module::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.root_block_ = {}; +} +Module::~Module() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Module) + SharedDtor(*this); +} +inline void Module::SharedDtor(MessageLite& self) { + Module& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL Module::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Module(arena); +} +constexpr auto Module::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Module, _impl_.types_) + + decltype(Module::_impl_.types_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Module, _impl_.values_) + + decltype(Module::_impl_.values_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Module, _impl_.constant_values_) + + decltype(Module::_impl_.constant_values_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Module, _impl_.functions_) + + decltype(Module::_impl_.functions_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Module, _impl_.blocks_) + + decltype(Module::_impl_.blocks_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(Module), alignof(Module), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Module::PlacementNew_, + sizeof(Module), + alignof(Module)); + } +} +constexpr auto Module::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Module_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Module::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Module::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Module::ByteSizeLong, + &Module::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Module, _impl_._cached_size_), + false, + }, + &Module::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Module_class_data_ = + Module::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Module::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Module_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Module_class_data_.tc_table); + return Module_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<3, 6, 5, 0, 2> +Module::_table_ = { + { + PROTOBUF_FIELD_OFFSET(Module, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967232, // skipmap + offsetof(decltype(_table_), field_entries), + 6, // num_field_entries + 5, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Module_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Module>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // repeated .tint.core.ir.binary.pb.Type types = 1; + {::_pbi::TcParser::FastMtR1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(Module, _impl_.types_)}}, + // repeated .tint.core.ir.binary.pb.Value values = 2; + {::_pbi::TcParser::FastMtR1, + {18, 63, 1, PROTOBUF_FIELD_OFFSET(Module, _impl_.values_)}}, + // repeated .tint.core.ir.binary.pb.ConstantValue constant_values = 3; + {::_pbi::TcParser::FastMtR1, + {26, 63, 2, PROTOBUF_FIELD_OFFSET(Module, _impl_.constant_values_)}}, + // repeated .tint.core.ir.binary.pb.Function functions = 4; + {::_pbi::TcParser::FastMtR1, + {34, 63, 3, PROTOBUF_FIELD_OFFSET(Module, _impl_.functions_)}}, + // repeated .tint.core.ir.binary.pb.Block blocks = 5; + {::_pbi::TcParser::FastMtR1, + {42, 63, 4, PROTOBUF_FIELD_OFFSET(Module, _impl_.blocks_)}}, + // uint32 root_block = 6; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Module, _impl_.root_block_), 0>(), + {48, 0, 0, PROTOBUF_FIELD_OFFSET(Module, _impl_.root_block_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated .tint.core.ir.binary.pb.Type types = 1; + {PROTOBUF_FIELD_OFFSET(Module, _impl_.types_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .tint.core.ir.binary.pb.Value values = 2; + {PROTOBUF_FIELD_OFFSET(Module, _impl_.values_), -1, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .tint.core.ir.binary.pb.ConstantValue constant_values = 3; + {PROTOBUF_FIELD_OFFSET(Module, _impl_.constant_values_), -1, 2, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .tint.core.ir.binary.pb.Function functions = 4; + {PROTOBUF_FIELD_OFFSET(Module, _impl_.functions_), -1, 3, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .tint.core.ir.binary.pb.Block blocks = 5; + {PROTOBUF_FIELD_OFFSET(Module, _impl_.blocks_), -1, 4, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint32 root_block = 6; + {PROTOBUF_FIELD_OFFSET(Module, _impl_.root_block_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Type>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Value>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValue>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Function>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Block>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void Module::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Module) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.types_.Clear(); + _impl_.values_.Clear(); + _impl_.constant_values_.Clear(); + _impl_.functions_.Clear(); + _impl_.blocks_.Clear(); + _impl_.root_block_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Module::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Module& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Module::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Module& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Module) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .tint.core.ir.binary.pb.Type types = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_types_size()); + i < n; i++) { + const auto& repfield = this_._internal_types().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .tint.core.ir.binary.pb.Value values = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_values_size()); + i < n; i++) { + const auto& repfield = this_._internal_values().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .tint.core.ir.binary.pb.ConstantValue constant_values = 3; + for (unsigned i = 0, n = static_cast( + this_._internal_constant_values_size()); + i < n; i++) { + const auto& repfield = this_._internal_constant_values().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .tint.core.ir.binary.pb.Function functions = 4; + for (unsigned i = 0, n = static_cast( + this_._internal_functions_size()); + i < n; i++) { + const auto& repfield = this_._internal_functions().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .tint.core.ir.binary.pb.Block blocks = 5; + for (unsigned i = 0, n = static_cast( + this_._internal_blocks_size()); + i < n; i++) { + const auto& repfield = this_._internal_blocks().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, repfield, repfield.GetCachedSize(), + target, stream); + } + + // uint32 root_block = 6; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_root_block() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 6, this_._internal_root_block(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Module) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Module::ByteSizeLong(const MessageLite& base) { + const Module& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Module::ByteSizeLong() const { + const Module& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Module) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .tint.core.ir.binary.pb.Type types = 1; + { + total_size += 1UL * this_._internal_types_size(); + for (const auto& msg : this_._internal_types()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .tint.core.ir.binary.pb.Value values = 2; + { + total_size += 1UL * this_._internal_values_size(); + for (const auto& msg : this_._internal_values()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .tint.core.ir.binary.pb.ConstantValue constant_values = 3; + { + total_size += 1UL * this_._internal_constant_values_size(); + for (const auto& msg : this_._internal_constant_values()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .tint.core.ir.binary.pb.Function functions = 4; + { + total_size += 1UL * this_._internal_functions_size(); + for (const auto& msg : this_._internal_functions()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .tint.core.ir.binary.pb.Block blocks = 5; + { + total_size += 1UL * this_._internal_blocks_size(); + for (const auto& msg : this_._internal_blocks()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + { + // uint32 root_block = 6; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_root_block() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_root_block()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Module::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Module) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_types()->MergeFrom( + from._internal_types()); + _this->_internal_mutable_values()->MergeFrom( + from._internal_values()); + _this->_internal_mutable_constant_values()->MergeFrom( + from._internal_constant_values()); + _this->_internal_mutable_functions()->MergeFrom( + from._internal_functions()); + _this->_internal_mutable_blocks()->MergeFrom( + from._internal_blocks()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_root_block() != 0) { + _this->_impl_.root_block_ = from._impl_.root_block_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Module::CopyFrom(const Module& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Module) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Module::InternalSwap(Module* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.types_.InternalSwap(&other->_impl_.types_); + _impl_.values_.InternalSwap(&other->_impl_.values_); + _impl_.constant_values_.InternalSwap(&other->_impl_.constant_values_); + _impl_.functions_.InternalSwap(&other->_impl_.functions_); + _impl_.blocks_.InternalSwap(&other->_impl_.blocks_); + swap(_impl_.root_block_, other->_impl_.root_block_); +} + +::google::protobuf::Metadata Module::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class Type::_Internal { + public: + static constexpr ::int32_t kOneofCaseOffset = + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Type, _impl_._oneof_case_); +}; + +void Type::set_allocated_vector(::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE vector) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (vector) { + ::google::protobuf::Arena* submessage_arena = vector->GetArena(); + if (message_arena != submessage_arena) { + vector = ::google::protobuf::internal::GetOwnedMessage(message_arena, vector, submessage_arena); + } + set_has_vector(); + _impl_.kind_.vector_ = vector; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.vector) +} +void Type::set_allocated_matrix(::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE matrix) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (matrix) { + ::google::protobuf::Arena* submessage_arena = matrix->GetArena(); + if (message_arena != submessage_arena) { + matrix = ::google::protobuf::internal::GetOwnedMessage(message_arena, matrix, submessage_arena); + } + set_has_matrix(); + _impl_.kind_.matrix_ = matrix; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.matrix) +} +void Type::set_allocated_array(::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE array) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (array) { + ::google::protobuf::Arena* submessage_arena = array->GetArena(); + if (message_arena != submessage_arena) { + array = ::google::protobuf::internal::GetOwnedMessage(message_arena, array, submessage_arena); + } + set_has_array(); + _impl_.kind_.array_ = array; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.array) +} +void Type::set_allocated_pointer(::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE pointer) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (pointer) { + ::google::protobuf::Arena* submessage_arena = pointer->GetArena(); + if (message_arena != submessage_arena) { + pointer = ::google::protobuf::internal::GetOwnedMessage(message_arena, pointer, submessage_arena); + } + set_has_pointer(); + _impl_.kind_.pointer_ = pointer; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.pointer) +} +void Type::set_allocated_struct_(::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE struct_) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (struct_) { + ::google::protobuf::Arena* submessage_arena = struct_->GetArena(); + if (message_arena != submessage_arena) { + struct_ = ::google::protobuf::internal::GetOwnedMessage(message_arena, struct_, submessage_arena); + } + set_has_struct_(); + _impl_.kind_.struct__ = struct_; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.struct) +} +void Type::set_allocated_atomic(::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE atomic) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (atomic) { + ::google::protobuf::Arena* submessage_arena = atomic->GetArena(); + if (message_arena != submessage_arena) { + atomic = ::google::protobuf::internal::GetOwnedMessage(message_arena, atomic, submessage_arena); + } + set_has_atomic(); + _impl_.kind_.atomic_ = atomic; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.atomic) +} +void Type::set_allocated_depth_texture(::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE depth_texture) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (depth_texture) { + ::google::protobuf::Arena* submessage_arena = depth_texture->GetArena(); + if (message_arena != submessage_arena) { + depth_texture = ::google::protobuf::internal::GetOwnedMessage(message_arena, depth_texture, submessage_arena); + } + set_has_depth_texture(); + _impl_.kind_.depth_texture_ = depth_texture; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.depth_texture) +} +void Type::set_allocated_sampled_texture(::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE sampled_texture) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (sampled_texture) { + ::google::protobuf::Arena* submessage_arena = sampled_texture->GetArena(); + if (message_arena != submessage_arena) { + sampled_texture = ::google::protobuf::internal::GetOwnedMessage(message_arena, sampled_texture, submessage_arena); + } + set_has_sampled_texture(); + _impl_.kind_.sampled_texture_ = sampled_texture; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.sampled_texture) +} +void Type::set_allocated_multisampled_texture(::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE multisampled_texture) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (multisampled_texture) { + ::google::protobuf::Arena* submessage_arena = multisampled_texture->GetArena(); + if (message_arena != submessage_arena) { + multisampled_texture = ::google::protobuf::internal::GetOwnedMessage(message_arena, multisampled_texture, submessage_arena); + } + set_has_multisampled_texture(); + _impl_.kind_.multisampled_texture_ = multisampled_texture; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.multisampled_texture) +} +void Type::set_allocated_depth_multisampled_texture(::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE depth_multisampled_texture) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (depth_multisampled_texture) { + ::google::protobuf::Arena* submessage_arena = depth_multisampled_texture->GetArena(); + if (message_arena != submessage_arena) { + depth_multisampled_texture = ::google::protobuf::internal::GetOwnedMessage(message_arena, depth_multisampled_texture, submessage_arena); + } + set_has_depth_multisampled_texture(); + _impl_.kind_.depth_multisampled_texture_ = depth_multisampled_texture; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.depth_multisampled_texture) +} +void Type::set_allocated_storage_texture(::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE storage_texture) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (storage_texture) { + ::google::protobuf::Arena* submessage_arena = storage_texture->GetArena(); + if (message_arena != submessage_arena) { + storage_texture = ::google::protobuf::internal::GetOwnedMessage(message_arena, storage_texture, submessage_arena); + } + set_has_storage_texture(); + _impl_.kind_.storage_texture_ = storage_texture; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.storage_texture) +} +void Type::set_allocated_external_texture(::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE external_texture) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (external_texture) { + ::google::protobuf::Arena* submessage_arena = external_texture->GetArena(); + if (message_arena != submessage_arena) { + external_texture = ::google::protobuf::internal::GetOwnedMessage(message_arena, external_texture, submessage_arena); + } + set_has_external_texture(); + _impl_.kind_.external_texture_ = external_texture; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.external_texture) +} +void Type::set_allocated_sampler(::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE sampler) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (sampler) { + ::google::protobuf::Arena* submessage_arena = sampler->GetArena(); + if (message_arena != submessage_arena) { + sampler = ::google::protobuf::internal::GetOwnedMessage(message_arena, sampler, submessage_arena); + } + set_has_sampler(); + _impl_.kind_.sampler_ = sampler; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.sampler) +} +void Type::set_allocated_input_attachment(::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE input_attachment) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (input_attachment) { + ::google::protobuf::Arena* submessage_arena = input_attachment->GetArena(); + if (message_arena != submessage_arena) { + input_attachment = ::google::protobuf::internal::GetOwnedMessage(message_arena, input_attachment, submessage_arena); + } + set_has_input_attachment(); + _impl_.kind_.input_attachment_ = input_attachment; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.input_attachment) +} +void Type::set_allocated_subgroup_matrix_left(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE subgroup_matrix_left) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (subgroup_matrix_left) { + ::google::protobuf::Arena* submessage_arena = subgroup_matrix_left->GetArena(); + if (message_arena != submessage_arena) { + subgroup_matrix_left = ::google::protobuf::internal::GetOwnedMessage(message_arena, subgroup_matrix_left, submessage_arena); + } + set_has_subgroup_matrix_left(); + _impl_.kind_.subgroup_matrix_left_ = subgroup_matrix_left; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.subgroup_matrix_left) +} +void Type::set_allocated_subgroup_matrix_right(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE subgroup_matrix_right) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (subgroup_matrix_right) { + ::google::protobuf::Arena* submessage_arena = subgroup_matrix_right->GetArena(); + if (message_arena != submessage_arena) { + subgroup_matrix_right = ::google::protobuf::internal::GetOwnedMessage(message_arena, subgroup_matrix_right, submessage_arena); + } + set_has_subgroup_matrix_right(); + _impl_.kind_.subgroup_matrix_right_ = subgroup_matrix_right; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.subgroup_matrix_right) +} +void Type::set_allocated_subgroup_matrix_result(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE subgroup_matrix_result) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (subgroup_matrix_result) { + ::google::protobuf::Arena* submessage_arena = subgroup_matrix_result->GetArena(); + if (message_arena != submessage_arena) { + subgroup_matrix_result = ::google::protobuf::internal::GetOwnedMessage(message_arena, subgroup_matrix_result, submessage_arena); + } + set_has_subgroup_matrix_result(); + _impl_.kind_.subgroup_matrix_result_ = subgroup_matrix_result; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.subgroup_matrix_result) +} +void Type::set_allocated_binding_array(::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE binding_array) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (binding_array) { + ::google::protobuf::Arena* submessage_arena = binding_array->GetArena(); + if (message_arena != submessage_arena) { + binding_array = ::google::protobuf::internal::GetOwnedMessage(message_arena, binding_array, submessage_arena); + } + set_has_binding_array(); + _impl_.kind_.binding_array_ = binding_array; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.binding_array) +} +void Type::set_allocated_texel_buffer(::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE texel_buffer) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (texel_buffer) { + ::google::protobuf::Arena* submessage_arena = texel_buffer->GetArena(); + if (message_arena != submessage_arena) { + texel_buffer = ::google::protobuf::internal::GetOwnedMessage(message_arena, texel_buffer, submessage_arena); + } + set_has_texel_buffer(); + _impl_.kind_.texel_buffer_ = texel_buffer; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.texel_buffer) +} +void Type::set_allocated_buffer(::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE buffer) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (buffer) { + ::google::protobuf::Arena* submessage_arena = buffer->GetArena(); + if (message_arena != submessage_arena) { + buffer = ::google::protobuf::internal::GetOwnedMessage(message_arena, buffer, submessage_arena); + } + set_has_buffer(); + _impl_.kind_.buffer_ = buffer; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Type.buffer) +} +Type::Type(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Type_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Type) +} +PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::Type& from_msg) + : kind_{}, + _cached_size_{0}, + _oneof_case_{from._oneof_case_[0]} {} + +Type::Type( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Type& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Type_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Type* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + switch (kind_case()) { + case KIND_NOT_SET: + break; + case kBasic: + _impl_.kind_.basic_ = from._impl_.kind_.basic_; + break; + case kVector: + _impl_.kind_.vector_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.vector_); + break; + case kMatrix: + _impl_.kind_.matrix_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.matrix_); + break; + case kArray: + _impl_.kind_.array_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.array_); + break; + case kPointer: + _impl_.kind_.pointer_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.pointer_); + break; + case kStruct: + _impl_.kind_.struct__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.struct__); + break; + case kAtomic: + _impl_.kind_.atomic_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.atomic_); + break; + case kDepthTexture: + _impl_.kind_.depth_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.depth_texture_); + break; + case kSampledTexture: + _impl_.kind_.sampled_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.sampled_texture_); + break; + case kMultisampledTexture: + _impl_.kind_.multisampled_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.multisampled_texture_); + break; + case kDepthMultisampledTexture: + _impl_.kind_.depth_multisampled_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.depth_multisampled_texture_); + break; + case kStorageTexture: + _impl_.kind_.storage_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.storage_texture_); + break; + case kExternalTexture: + _impl_.kind_.external_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.external_texture_); + break; + case kSampler: + _impl_.kind_.sampler_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.sampler_); + break; + case kInputAttachment: + _impl_.kind_.input_attachment_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.input_attachment_); + break; + case kSubgroupMatrixLeft: + _impl_.kind_.subgroup_matrix_left_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.subgroup_matrix_left_); + break; + case kSubgroupMatrixRight: + _impl_.kind_.subgroup_matrix_right_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.subgroup_matrix_right_); + break; + case kSubgroupMatrixResult: + _impl_.kind_.subgroup_matrix_result_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.subgroup_matrix_result_); + break; + case kBuiltinStruct: + _impl_.kind_.builtin_struct_ = from._impl_.kind_.builtin_struct_; + break; + case kBindingArray: + _impl_.kind_.binding_array_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.binding_array_); + break; + case kTexelBuffer: + _impl_.kind_.texel_buffer_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.texel_buffer_); + break; + case kBuffer: + _impl_.kind_.buffer_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.buffer_); + break; + } + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.Type) +} +PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +inline void Type::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +Type::~Type() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Type) + SharedDtor(*this); +} +inline void Type::SharedDtor(MessageLite& self) { + Type& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + if (this_.has_kind()) { + this_.clear_kind(); + } + this_._impl_.~Impl_(); +} + +void Type::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:tint.core.ir.binary.pb.Type) + ::google::protobuf::internal::TSanWrite(&_impl_); + switch (kind_case()) { + case kBasic: { + // No need to clear + break; + } + case kVector: { + if (GetArena() == nullptr) { + delete _impl_.kind_.vector_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.vector_); + } + break; + } + case kMatrix: { + if (GetArena() == nullptr) { + delete _impl_.kind_.matrix_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.matrix_); + } + break; + } + case kArray: { + if (GetArena() == nullptr) { + delete _impl_.kind_.array_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.array_); + } + break; + } + case kPointer: { + if (GetArena() == nullptr) { + delete _impl_.kind_.pointer_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.pointer_); + } + break; + } + case kStruct: { + if (GetArena() == nullptr) { + delete _impl_.kind_.struct__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.struct__); + } + break; + } + case kAtomic: { + if (GetArena() == nullptr) { + delete _impl_.kind_.atomic_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.atomic_); + } + break; + } + case kDepthTexture: { + if (GetArena() == nullptr) { + delete _impl_.kind_.depth_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.depth_texture_); + } + break; + } + case kSampledTexture: { + if (GetArena() == nullptr) { + delete _impl_.kind_.sampled_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.sampled_texture_); + } + break; + } + case kMultisampledTexture: { + if (GetArena() == nullptr) { + delete _impl_.kind_.multisampled_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.multisampled_texture_); + } + break; + } + case kDepthMultisampledTexture: { + if (GetArena() == nullptr) { + delete _impl_.kind_.depth_multisampled_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.depth_multisampled_texture_); + } + break; + } + case kStorageTexture: { + if (GetArena() == nullptr) { + delete _impl_.kind_.storage_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.storage_texture_); + } + break; + } + case kExternalTexture: { + if (GetArena() == nullptr) { + delete _impl_.kind_.external_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.external_texture_); + } + break; + } + case kSampler: { + if (GetArena() == nullptr) { + delete _impl_.kind_.sampler_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.sampler_); + } + break; + } + case kInputAttachment: { + if (GetArena() == nullptr) { + delete _impl_.kind_.input_attachment_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.input_attachment_); + } + break; + } + case kSubgroupMatrixLeft: { + if (GetArena() == nullptr) { + delete _impl_.kind_.subgroup_matrix_left_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.subgroup_matrix_left_); + } + break; + } + case kSubgroupMatrixRight: { + if (GetArena() == nullptr) { + delete _impl_.kind_.subgroup_matrix_right_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.subgroup_matrix_right_); + } + break; + } + case kSubgroupMatrixResult: { + if (GetArena() == nullptr) { + delete _impl_.kind_.subgroup_matrix_result_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.subgroup_matrix_result_); + } + break; + } + case kBuiltinStruct: { + // No need to clear + break; + } + case kBindingArray: { + if (GetArena() == nullptr) { + delete _impl_.kind_.binding_array_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.binding_array_); + } + break; + } + case kTexelBuffer: { + if (GetArena() == nullptr) { + delete _impl_.kind_.texel_buffer_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.texel_buffer_); + } + break; + } + case kBuffer: { + if (GetArena() == nullptr) { + delete _impl_.kind_.buffer_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.buffer_); + } + break; + } + case KIND_NOT_SET: { + break; + } + } + _impl_._oneof_case_[0] = KIND_NOT_SET; +} + + +inline void* PROTOBUF_NONNULL Type::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Type(arena); +} +constexpr auto Type::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Type), + alignof(Type)); +} +constexpr auto Type::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Type_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Type::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Type::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Type::ByteSizeLong, + &Type::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Type, _impl_._cached_size_), + false, + }, + &Type::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Type_class_data_ = + Type::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Type::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Type_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Type_class_data_.tc_table); + return Type_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 22, 20, 0, 2> +Type::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 23, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4288675840, // skipmap + offsetof(decltype(_table_), field_entries), + 22, // num_field_entries + 20, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Type_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Type>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TypeBasic basic = 1; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.basic_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kOpenEnum)}, + // .tint.core.ir.binary.pb.TypeVector vector = 2; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.vector_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeMatrix matrix = 3; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.matrix_), _Internal::kOneofCaseOffset + 0, 1, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeArray array = 4; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.array_), _Internal::kOneofCaseOffset + 0, 2, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypePointer pointer = 5; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.pointer_), _Internal::kOneofCaseOffset + 0, 3, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeStruct struct = 6; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.struct__), _Internal::kOneofCaseOffset + 0, 4, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeAtomic atomic = 7; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.atomic_), _Internal::kOneofCaseOffset + 0, 5, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeDepthTexture depth_texture = 8; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.depth_texture_), _Internal::kOneofCaseOffset + 0, 6, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeSampledTexture sampled_texture = 9; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.sampled_texture_), _Internal::kOneofCaseOffset + 0, 7, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeMultisampledTexture multisampled_texture = 10; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.multisampled_texture_), _Internal::kOneofCaseOffset + 0, 8, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeDepthMultisampledTexture depth_multisampled_texture = 11; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.depth_multisampled_texture_), _Internal::kOneofCaseOffset + 0, 9, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeStorageTexture storage_texture = 12; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.storage_texture_), _Internal::kOneofCaseOffset + 0, 10, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeExternalTexture external_texture = 13; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.external_texture_), _Internal::kOneofCaseOffset + 0, 11, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeSampler sampler = 14; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.sampler_), _Internal::kOneofCaseOffset + 0, 12, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeInputAttachment input_attachment = 15; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.input_attachment_), _Internal::kOneofCaseOffset + 0, 13, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_left = 16; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.subgroup_matrix_left_), _Internal::kOneofCaseOffset + 0, 14, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_right = 17; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.subgroup_matrix_right_), _Internal::kOneofCaseOffset + 0, 15, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_result = 18; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.subgroup_matrix_result_), _Internal::kOneofCaseOffset + 0, 16, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeBuiltinStruct builtin_struct = 19; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.builtin_struct_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kOpenEnum)}, + // .tint.core.ir.binary.pb.TypeBindingArray binding_array = 20; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.binding_array_), _Internal::kOneofCaseOffset + 0, 17, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeTexelBuffer texel_buffer = 21; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.texel_buffer_), _Internal::kOneofCaseOffset + 0, 18, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.TypeBuffer buffer = 23; + {PROTOBUF_FIELD_OFFSET(Type, _impl_.kind_.buffer_), _Internal::kOneofCaseOffset + 0, 19, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeVector>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeMatrix>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeArray>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypePointer>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeStruct>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeAtomic>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeDepthTexture>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSampledTexture>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeMultisampledTexture>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeStorageTexture>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeExternalTexture>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSampler>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeInputAttachment>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSubgroupMatrix>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSubgroupMatrix>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSubgroupMatrix>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeBindingArray>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeTexelBuffer>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeBuffer>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void Type::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Type) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + clear_kind(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Type::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Type& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Type::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Type& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Type) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + switch (this_.kind_case()) { + case kBasic: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_basic(), target); + break; + } + case kVector: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.kind_.vector_, this_._impl_.kind_.vector_->GetCachedSize(), target, + stream); + break; + } + case kMatrix: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.kind_.matrix_, this_._impl_.kind_.matrix_->GetCachedSize(), target, + stream); + break; + } + case kArray: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.kind_.array_, this_._impl_.kind_.array_->GetCachedSize(), target, + stream); + break; + } + case kPointer: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.kind_.pointer_, this_._impl_.kind_.pointer_->GetCachedSize(), target, + stream); + break; + } + case kStruct: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.kind_.struct__, this_._impl_.kind_.struct__->GetCachedSize(), target, + stream); + break; + } + case kAtomic: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, *this_._impl_.kind_.atomic_, this_._impl_.kind_.atomic_->GetCachedSize(), target, + stream); + break; + } + case kDepthTexture: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.kind_.depth_texture_, this_._impl_.kind_.depth_texture_->GetCachedSize(), target, + stream); + break; + } + case kSampledTexture: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 9, *this_._impl_.kind_.sampled_texture_, this_._impl_.kind_.sampled_texture_->GetCachedSize(), target, + stream); + break; + } + case kMultisampledTexture: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 10, *this_._impl_.kind_.multisampled_texture_, this_._impl_.kind_.multisampled_texture_->GetCachedSize(), target, + stream); + break; + } + case kDepthMultisampledTexture: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 11, *this_._impl_.kind_.depth_multisampled_texture_, this_._impl_.kind_.depth_multisampled_texture_->GetCachedSize(), target, + stream); + break; + } + case kStorageTexture: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 12, *this_._impl_.kind_.storage_texture_, this_._impl_.kind_.storage_texture_->GetCachedSize(), target, + stream); + break; + } + case kExternalTexture: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 13, *this_._impl_.kind_.external_texture_, this_._impl_.kind_.external_texture_->GetCachedSize(), target, + stream); + break; + } + case kSampler: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 14, *this_._impl_.kind_.sampler_, this_._impl_.kind_.sampler_->GetCachedSize(), target, + stream); + break; + } + case kInputAttachment: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 15, *this_._impl_.kind_.input_attachment_, this_._impl_.kind_.input_attachment_->GetCachedSize(), target, + stream); + break; + } + case kSubgroupMatrixLeft: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 16, *this_._impl_.kind_.subgroup_matrix_left_, this_._impl_.kind_.subgroup_matrix_left_->GetCachedSize(), target, + stream); + break; + } + case kSubgroupMatrixRight: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 17, *this_._impl_.kind_.subgroup_matrix_right_, this_._impl_.kind_.subgroup_matrix_right_->GetCachedSize(), target, + stream); + break; + } + case kSubgroupMatrixResult: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 18, *this_._impl_.kind_.subgroup_matrix_result_, this_._impl_.kind_.subgroup_matrix_result_->GetCachedSize(), target, + stream); + break; + } + case kBuiltinStruct: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 19, this_._internal_builtin_struct(), target); + break; + } + case kBindingArray: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 20, *this_._impl_.kind_.binding_array_, this_._impl_.kind_.binding_array_->GetCachedSize(), target, + stream); + break; + } + case kTexelBuffer: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 21, *this_._impl_.kind_.texel_buffer_, this_._impl_.kind_.texel_buffer_->GetCachedSize(), target, + stream); + break; + } + case kBuffer: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 23, *this_._impl_.kind_.buffer_, this_._impl_.kind_.buffer_->GetCachedSize(), target, + stream); + break; + } + default: + break; + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Type) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Type::ByteSizeLong(const MessageLite& base) { + const Type& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Type::ByteSizeLong() const { + const Type& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Type) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + switch (this_.kind_case()) { + // .tint.core.ir.binary.pb.TypeBasic basic = 1; + case kBasic: { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_basic()); + break; + } + // .tint.core.ir.binary.pb.TypeVector vector = 2; + case kVector: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.vector_); + break; + } + // .tint.core.ir.binary.pb.TypeMatrix matrix = 3; + case kMatrix: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.matrix_); + break; + } + // .tint.core.ir.binary.pb.TypeArray array = 4; + case kArray: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.array_); + break; + } + // .tint.core.ir.binary.pb.TypePointer pointer = 5; + case kPointer: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.pointer_); + break; + } + // .tint.core.ir.binary.pb.TypeStruct struct = 6; + case kStruct: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.struct__); + break; + } + // .tint.core.ir.binary.pb.TypeAtomic atomic = 7; + case kAtomic: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.atomic_); + break; + } + // .tint.core.ir.binary.pb.TypeDepthTexture depth_texture = 8; + case kDepthTexture: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.depth_texture_); + break; + } + // .tint.core.ir.binary.pb.TypeSampledTexture sampled_texture = 9; + case kSampledTexture: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.sampled_texture_); + break; + } + // .tint.core.ir.binary.pb.TypeMultisampledTexture multisampled_texture = 10; + case kMultisampledTexture: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.multisampled_texture_); + break; + } + // .tint.core.ir.binary.pb.TypeDepthMultisampledTexture depth_multisampled_texture = 11; + case kDepthMultisampledTexture: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.depth_multisampled_texture_); + break; + } + // .tint.core.ir.binary.pb.TypeStorageTexture storage_texture = 12; + case kStorageTexture: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.storage_texture_); + break; + } + // .tint.core.ir.binary.pb.TypeExternalTexture external_texture = 13; + case kExternalTexture: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.external_texture_); + break; + } + // .tint.core.ir.binary.pb.TypeSampler sampler = 14; + case kSampler: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.sampler_); + break; + } + // .tint.core.ir.binary.pb.TypeInputAttachment input_attachment = 15; + case kInputAttachment: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.input_attachment_); + break; + } + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_left = 16; + case kSubgroupMatrixLeft: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.subgroup_matrix_left_); + break; + } + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_right = 17; + case kSubgroupMatrixRight: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.subgroup_matrix_right_); + break; + } + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_result = 18; + case kSubgroupMatrixResult: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.subgroup_matrix_result_); + break; + } + // .tint.core.ir.binary.pb.TypeBuiltinStruct builtin_struct = 19; + case kBuiltinStruct: { + total_size += 2 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_builtin_struct()); + break; + } + // .tint.core.ir.binary.pb.TypeBindingArray binding_array = 20; + case kBindingArray: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.binding_array_); + break; + } + // .tint.core.ir.binary.pb.TypeTexelBuffer texel_buffer = 21; + case kTexelBuffer: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.texel_buffer_); + break; + } + // .tint.core.ir.binary.pb.TypeBuffer buffer = 23; + case kBuffer: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.buffer_); + break; + } + case KIND_NOT_SET: { + break; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Type::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Type) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (const uint32_t oneof_from_case = from._impl_._oneof_case_[0]) { + const uint32_t oneof_to_case = _this->_impl_._oneof_case_[0]; + const bool oneof_needs_init = oneof_to_case != oneof_from_case; + if (oneof_needs_init) { + if (oneof_to_case != 0) { + _this->clear_kind(); + } + _this->_impl_._oneof_case_[0] = oneof_from_case; + } + + switch (oneof_from_case) { + case kBasic: { + _this->_impl_.kind_.basic_ = from._impl_.kind_.basic_; + break; + } + case kVector: { + if (oneof_needs_init) { + _this->_impl_.kind_.vector_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.vector_); + } else { + _this->_impl_.kind_.vector_->MergeFrom(*from._impl_.kind_.vector_); + } + break; + } + case kMatrix: { + if (oneof_needs_init) { + _this->_impl_.kind_.matrix_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.matrix_); + } else { + _this->_impl_.kind_.matrix_->MergeFrom(*from._impl_.kind_.matrix_); + } + break; + } + case kArray: { + if (oneof_needs_init) { + _this->_impl_.kind_.array_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.array_); + } else { + _this->_impl_.kind_.array_->MergeFrom(*from._impl_.kind_.array_); + } + break; + } + case kPointer: { + if (oneof_needs_init) { + _this->_impl_.kind_.pointer_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.pointer_); + } else { + _this->_impl_.kind_.pointer_->MergeFrom(*from._impl_.kind_.pointer_); + } + break; + } + case kStruct: { + if (oneof_needs_init) { + _this->_impl_.kind_.struct__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.struct__); + } else { + _this->_impl_.kind_.struct__->MergeFrom(*from._impl_.kind_.struct__); + } + break; + } + case kAtomic: { + if (oneof_needs_init) { + _this->_impl_.kind_.atomic_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.atomic_); + } else { + _this->_impl_.kind_.atomic_->MergeFrom(*from._impl_.kind_.atomic_); + } + break; + } + case kDepthTexture: { + if (oneof_needs_init) { + _this->_impl_.kind_.depth_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.depth_texture_); + } else { + _this->_impl_.kind_.depth_texture_->MergeFrom(*from._impl_.kind_.depth_texture_); + } + break; + } + case kSampledTexture: { + if (oneof_needs_init) { + _this->_impl_.kind_.sampled_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.sampled_texture_); + } else { + _this->_impl_.kind_.sampled_texture_->MergeFrom(*from._impl_.kind_.sampled_texture_); + } + break; + } + case kMultisampledTexture: { + if (oneof_needs_init) { + _this->_impl_.kind_.multisampled_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.multisampled_texture_); + } else { + _this->_impl_.kind_.multisampled_texture_->MergeFrom(*from._impl_.kind_.multisampled_texture_); + } + break; + } + case kDepthMultisampledTexture: { + if (oneof_needs_init) { + _this->_impl_.kind_.depth_multisampled_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.depth_multisampled_texture_); + } else { + _this->_impl_.kind_.depth_multisampled_texture_->MergeFrom(*from._impl_.kind_.depth_multisampled_texture_); + } + break; + } + case kStorageTexture: { + if (oneof_needs_init) { + _this->_impl_.kind_.storage_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.storage_texture_); + } else { + _this->_impl_.kind_.storage_texture_->MergeFrom(*from._impl_.kind_.storage_texture_); + } + break; + } + case kExternalTexture: { + if (oneof_needs_init) { + _this->_impl_.kind_.external_texture_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.external_texture_); + } else { + _this->_impl_.kind_.external_texture_->MergeFrom(*from._impl_.kind_.external_texture_); + } + break; + } + case kSampler: { + if (oneof_needs_init) { + _this->_impl_.kind_.sampler_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.sampler_); + } else { + _this->_impl_.kind_.sampler_->MergeFrom(*from._impl_.kind_.sampler_); + } + break; + } + case kInputAttachment: { + if (oneof_needs_init) { + _this->_impl_.kind_.input_attachment_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.input_attachment_); + } else { + _this->_impl_.kind_.input_attachment_->MergeFrom(*from._impl_.kind_.input_attachment_); + } + break; + } + case kSubgroupMatrixLeft: { + if (oneof_needs_init) { + _this->_impl_.kind_.subgroup_matrix_left_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.subgroup_matrix_left_); + } else { + _this->_impl_.kind_.subgroup_matrix_left_->MergeFrom(*from._impl_.kind_.subgroup_matrix_left_); + } + break; + } + case kSubgroupMatrixRight: { + if (oneof_needs_init) { + _this->_impl_.kind_.subgroup_matrix_right_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.subgroup_matrix_right_); + } else { + _this->_impl_.kind_.subgroup_matrix_right_->MergeFrom(*from._impl_.kind_.subgroup_matrix_right_); + } + break; + } + case kSubgroupMatrixResult: { + if (oneof_needs_init) { + _this->_impl_.kind_.subgroup_matrix_result_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.subgroup_matrix_result_); + } else { + _this->_impl_.kind_.subgroup_matrix_result_->MergeFrom(*from._impl_.kind_.subgroup_matrix_result_); + } + break; + } + case kBuiltinStruct: { + _this->_impl_.kind_.builtin_struct_ = from._impl_.kind_.builtin_struct_; + break; + } + case kBindingArray: { + if (oneof_needs_init) { + _this->_impl_.kind_.binding_array_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.binding_array_); + } else { + _this->_impl_.kind_.binding_array_->MergeFrom(*from._impl_.kind_.binding_array_); + } + break; + } + case kTexelBuffer: { + if (oneof_needs_init) { + _this->_impl_.kind_.texel_buffer_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.texel_buffer_); + } else { + _this->_impl_.kind_.texel_buffer_->MergeFrom(*from._impl_.kind_.texel_buffer_); + } + break; + } + case kBuffer: { + if (oneof_needs_init) { + _this->_impl_.kind_.buffer_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.buffer_); + } else { + _this->_impl_.kind_.buffer_->MergeFrom(*from._impl_.kind_.buffer_); + } + break; + } + case KIND_NOT_SET: + break; + } + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Type::CopyFrom(const Type& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Type) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Type::InternalSwap(Type* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.kind_, other->_impl_.kind_); + swap(_impl_._oneof_case_[0], other->_impl_._oneof_case_[0]); +} + +::google::protobuf::Metadata Type::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeVector::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeVector, _impl_._has_bits_); +}; + +TypeVector::TypeVector(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeVector_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeVector) +} +TypeVector::TypeVector( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeVector& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeVector_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeVector::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeVector::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, width_), + 0, + offsetof(Impl_, element_type_) - + offsetof(Impl_, width_) + + sizeof(Impl_::element_type_)); +} +TypeVector::~TypeVector() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeVector) + SharedDtor(*this); +} +inline void TypeVector::SharedDtor(MessageLite& self) { + TypeVector& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeVector::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeVector(arena); +} +constexpr auto TypeVector::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeVector), + alignof(TypeVector)); +} +constexpr auto TypeVector::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeVector_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeVector::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeVector::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeVector::ByteSizeLong, + &TypeVector::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeVector, _impl_._cached_size_), + false, + }, + &TypeVector::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeVector_class_data_ = + TypeVector::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeVector::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeVector_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeVector_class_data_.tc_table); + return TypeVector_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +TypeVector::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeVector, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeVector_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeVector>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 element_type = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeVector, _impl_.element_type_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeVector, _impl_.element_type_)}}, + // uint32 width = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeVector, _impl_.width_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeVector, _impl_.width_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 width = 1; + {PROTOBUF_FIELD_OFFSET(TypeVector, _impl_.width_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 element_type = 2; + {PROTOBUF_FIELD_OFFSET(TypeVector, _impl_.element_type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeVector::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeVector) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.width_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.element_type_) - + reinterpret_cast(&_impl_.width_)) + sizeof(_impl_.element_type_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeVector::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeVector& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeVector::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeVector& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeVector) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 width = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_width() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_width(), target); + } + } + + // uint32 element_type = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_element_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_element_type(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeVector) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeVector::ByteSizeLong(const MessageLite& base) { + const TypeVector& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeVector::ByteSizeLong() const { + const TypeVector& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeVector) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // uint32 width = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_width() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_width()); + } + } + // uint32 element_type = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_element_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_element_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeVector::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeVector) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_width() != 0) { + _this->_impl_.width_ = from._impl_.width_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_element_type() != 0) { + _this->_impl_.element_type_ = from._impl_.element_type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeVector::CopyFrom(const TypeVector& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeVector) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeVector::InternalSwap(TypeVector* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeVector, _impl_.element_type_) + + sizeof(TypeVector::_impl_.element_type_) + - PROTOBUF_FIELD_OFFSET(TypeVector, _impl_.width_)>( + reinterpret_cast(&_impl_.width_), + reinterpret_cast(&other->_impl_.width_)); +} + +::google::protobuf::Metadata TypeVector::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeMatrix::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_._has_bits_); +}; + +TypeMatrix::TypeMatrix(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeMatrix_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeMatrix) +} +TypeMatrix::TypeMatrix( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeMatrix& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeMatrix_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeMatrix::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeMatrix::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, num_columns_), + 0, + offsetof(Impl_, element_type_) - + offsetof(Impl_, num_columns_) + + sizeof(Impl_::element_type_)); +} +TypeMatrix::~TypeMatrix() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeMatrix) + SharedDtor(*this); +} +inline void TypeMatrix::SharedDtor(MessageLite& self) { + TypeMatrix& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeMatrix::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeMatrix(arena); +} +constexpr auto TypeMatrix::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeMatrix), + alignof(TypeMatrix)); +} +constexpr auto TypeMatrix::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeMatrix_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeMatrix::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeMatrix::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeMatrix::ByteSizeLong, + &TypeMatrix::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_._cached_size_), + false, + }, + &TypeMatrix::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeMatrix_class_data_ = + TypeMatrix::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeMatrix::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeMatrix_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeMatrix_class_data_.tc_table); + return TypeMatrix_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +TypeMatrix::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeMatrix_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeMatrix>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 num_columns = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeMatrix, _impl_.num_columns_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.num_columns_)}}, + // uint32 num_rows = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeMatrix, _impl_.num_rows_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.num_rows_)}}, + // uint32 element_type = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeMatrix, _impl_.element_type_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.element_type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 num_columns = 1; + {PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.num_columns_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 num_rows = 2; + {PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.num_rows_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 element_type = 3; + {PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.element_type_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeMatrix::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeMatrix) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.num_columns_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.element_type_) - + reinterpret_cast(&_impl_.num_columns_)) + sizeof(_impl_.element_type_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeMatrix::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeMatrix& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeMatrix::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeMatrix& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeMatrix) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 num_columns = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_num_columns() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_num_columns(), target); + } + } + + // uint32 num_rows = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_num_rows() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_num_rows(), target); + } + } + + // uint32 element_type = 3; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_element_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_element_type(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeMatrix) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeMatrix::ByteSizeLong(const MessageLite& base) { + const TypeMatrix& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeMatrix::ByteSizeLong() const { + const TypeMatrix& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeMatrix) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // uint32 num_columns = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_num_columns() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_num_columns()); + } + } + // uint32 num_rows = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_num_rows() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_num_rows()); + } + } + // uint32 element_type = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_element_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_element_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeMatrix::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeMatrix) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_num_columns() != 0) { + _this->_impl_.num_columns_ = from._impl_.num_columns_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_num_rows() != 0) { + _this->_impl_.num_rows_ = from._impl_.num_rows_; + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_element_type() != 0) { + _this->_impl_.element_type_ = from._impl_.element_type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeMatrix::CopyFrom(const TypeMatrix& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeMatrix) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeMatrix::InternalSwap(TypeMatrix* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.element_type_) + + sizeof(TypeMatrix::_impl_.element_type_) + - PROTOBUF_FIELD_OFFSET(TypeMatrix, _impl_.num_columns_)>( + reinterpret_cast(&_impl_.num_columns_), + reinterpret_cast(&other->_impl_.num_columns_)); +} + +::google::protobuf::Metadata TypeMatrix::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeArray::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeArray, _impl_._has_bits_); +}; + +TypeArray::TypeArray(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeArray_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeArray) +} +TypeArray::TypeArray( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeArray& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeArray_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeArray::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeArray::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, element_), + 0, + offsetof(Impl_, count_) - + offsetof(Impl_, element_) + + sizeof(Impl_::count_)); +} +TypeArray::~TypeArray() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeArray) + SharedDtor(*this); +} +inline void TypeArray::SharedDtor(MessageLite& self) { + TypeArray& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeArray::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeArray(arena); +} +constexpr auto TypeArray::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeArray), + alignof(TypeArray)); +} +constexpr auto TypeArray::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeArray_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeArray::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeArray::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeArray::ByteSizeLong, + &TypeArray::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeArray, _impl_._cached_size_), + false, + }, + &TypeArray::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeArray_class_data_ = + TypeArray::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeArray::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeArray_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeArray_class_data_.tc_table); + return TypeArray_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 2, 0, 0, 2> +TypeArray::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeArray, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967290, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeArray_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeArray>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 element = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeArray, _impl_.element_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeArray, _impl_.element_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // uint32 count = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeArray, _impl_.count_), 1>(), + {24, 1, 0, PROTOBUF_FIELD_OFFSET(TypeArray, _impl_.count_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 element = 1; + {PROTOBUF_FIELD_OFFSET(TypeArray, _impl_.element_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 count = 3; + {PROTOBUF_FIELD_OFFSET(TypeArray, _impl_.count_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeArray::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeArray) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.element_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.count_) - + reinterpret_cast(&_impl_.element_)) + sizeof(_impl_.count_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeArray::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeArray& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeArray::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeArray& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeArray) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 element = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_element() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_element(), target); + } + } + + // uint32 count = 3; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_count() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_count(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeArray) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeArray::ByteSizeLong(const MessageLite& base) { + const TypeArray& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeArray::ByteSizeLong() const { + const TypeArray& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeArray) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // uint32 element = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_element() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_element()); + } + } + // uint32 count = 3; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_count() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_count()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeArray::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeArray) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_element() != 0) { + _this->_impl_.element_ = from._impl_.element_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_count() != 0) { + _this->_impl_.count_ = from._impl_.count_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeArray::CopyFrom(const TypeArray& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeArray) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeArray::InternalSwap(TypeArray* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeArray, _impl_.count_) + + sizeof(TypeArray::_impl_.count_) + - PROTOBUF_FIELD_OFFSET(TypeArray, _impl_.element_)>( + reinterpret_cast(&_impl_.element_), + reinterpret_cast(&other->_impl_.element_)); +} + +::google::protobuf::Metadata TypeArray::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeBindingArray::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_._has_bits_); +}; + +TypeBindingArray::TypeBindingArray(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeBindingArray_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeBindingArray) +} +TypeBindingArray::TypeBindingArray( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeBindingArray& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeBindingArray_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeBindingArray::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeBindingArray::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, element_), + 0, + offsetof(Impl_, count_) - + offsetof(Impl_, element_) + + sizeof(Impl_::count_)); +} +TypeBindingArray::~TypeBindingArray() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeBindingArray) + SharedDtor(*this); +} +inline void TypeBindingArray::SharedDtor(MessageLite& self) { + TypeBindingArray& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeBindingArray::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeBindingArray(arena); +} +constexpr auto TypeBindingArray::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeBindingArray), + alignof(TypeBindingArray)); +} +constexpr auto TypeBindingArray::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeBindingArray_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeBindingArray::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeBindingArray::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeBindingArray::ByteSizeLong, + &TypeBindingArray::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_._cached_size_), + false, + }, + &TypeBindingArray::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeBindingArray_class_data_ = + TypeBindingArray::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeBindingArray::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeBindingArray_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeBindingArray_class_data_.tc_table); + return TypeBindingArray_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +TypeBindingArray::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeBindingArray_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeBindingArray>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 count = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeBindingArray, _impl_.count_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_.count_)}}, + // uint32 element = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeBindingArray, _impl_.element_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_.element_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 element = 1; + {PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_.element_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 count = 2; + {PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_.count_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeBindingArray::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeBindingArray) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.element_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.count_) - + reinterpret_cast(&_impl_.element_)) + sizeof(_impl_.count_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeBindingArray::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeBindingArray& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeBindingArray::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeBindingArray& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeBindingArray) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 element = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_element() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_element(), target); + } + } + + // uint32 count = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_count() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_count(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeBindingArray) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeBindingArray::ByteSizeLong(const MessageLite& base) { + const TypeBindingArray& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeBindingArray::ByteSizeLong() const { + const TypeBindingArray& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeBindingArray) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // uint32 element = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_element() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_element()); + } + } + // uint32 count = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_count() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_count()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeBindingArray::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeBindingArray) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_element() != 0) { + _this->_impl_.element_ = from._impl_.element_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_count() != 0) { + _this->_impl_.count_ = from._impl_.count_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeBindingArray::CopyFrom(const TypeBindingArray& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeBindingArray) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeBindingArray::InternalSwap(TypeBindingArray* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_.count_) + + sizeof(TypeBindingArray::_impl_.count_) + - PROTOBUF_FIELD_OFFSET(TypeBindingArray, _impl_.element_)>( + reinterpret_cast(&_impl_.element_), + reinterpret_cast(&other->_impl_.element_)); +} + +::google::protobuf::Metadata TypeBindingArray::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypePointer::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypePointer, _impl_._has_bits_); +}; + +TypePointer::TypePointer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypePointer_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypePointer) +} +TypePointer::TypePointer( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypePointer& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypePointer_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypePointer::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypePointer::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, address_space_), + 0, + offsetof(Impl_, access_) - + offsetof(Impl_, address_space_) + + sizeof(Impl_::access_)); +} +TypePointer::~TypePointer() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypePointer) + SharedDtor(*this); +} +inline void TypePointer::SharedDtor(MessageLite& self) { + TypePointer& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypePointer::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypePointer(arena); +} +constexpr auto TypePointer::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypePointer), + alignof(TypePointer)); +} +constexpr auto TypePointer::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypePointer_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypePointer::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypePointer::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypePointer::ByteSizeLong, + &TypePointer::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypePointer, _impl_._cached_size_), + false, + }, + &TypePointer::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypePointer_class_data_ = + TypePointer::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypePointer::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypePointer_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypePointer_class_data_.tc_table); + return TypePointer_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +TypePointer::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypePointer, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypePointer_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypePointer>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .tint.core.ir.binary.pb.AddressSpace address_space = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypePointer, _impl_.address_space_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.address_space_)}}, + // uint32 store_type = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypePointer, _impl_.store_type_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.store_type_)}}, + // .tint.core.ir.binary.pb.AccessControl access = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypePointer, _impl_.access_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.access_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.AddressSpace address_space = 1; + {PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.address_space_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // uint32 store_type = 2; + {PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.store_type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // .tint.core.ir.binary.pb.AccessControl access = 3; + {PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.access_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypePointer::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypePointer) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.address_space_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.access_) - + reinterpret_cast(&_impl_.address_space_)) + sizeof(_impl_.access_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypePointer::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypePointer& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypePointer::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypePointer& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypePointer) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.AddressSpace address_space = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_address_space() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_address_space(), target); + } + } + + // uint32 store_type = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_store_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_store_type(), target); + } + } + + // .tint.core.ir.binary.pb.AccessControl access = 3; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_access() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_access(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypePointer) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypePointer::ByteSizeLong(const MessageLite& base) { + const TypePointer& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypePointer::ByteSizeLong() const { + const TypePointer& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypePointer) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // .tint.core.ir.binary.pb.AddressSpace address_space = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_address_space() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_address_space()); + } + } + // uint32 store_type = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_store_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_store_type()); + } + } + // .tint.core.ir.binary.pb.AccessControl access = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_access() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_access()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypePointer::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypePointer) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_address_space() != 0) { + _this->_impl_.address_space_ = from._impl_.address_space_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_store_type() != 0) { + _this->_impl_.store_type_ = from._impl_.store_type_; + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_access() != 0) { + _this->_impl_.access_ = from._impl_.access_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypePointer::CopyFrom(const TypePointer& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypePointer) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypePointer::InternalSwap(TypePointer* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.access_) + + sizeof(TypePointer::_impl_.access_) + - PROTOBUF_FIELD_OFFSET(TypePointer, _impl_.address_space_)>( + reinterpret_cast(&_impl_.address_space_), + reinterpret_cast(&other->_impl_.address_space_)); +} + +::google::protobuf::Metadata TypePointer::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeStruct::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_._has_bits_); +}; + +TypeStruct::TypeStruct(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeStruct_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeStruct) +} +PROTOBUF_NDEBUG_INLINE TypeStruct::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::TypeStruct& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + member_{visibility, arena, from.member_}, + name_(arena, from.name_) {} + +TypeStruct::TypeStruct( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const TypeStruct& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeStruct_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + TypeStruct* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.TypeStruct) +} +PROTOBUF_NDEBUG_INLINE TypeStruct::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + member_{visibility, arena}, + name_(arena) {} + +inline void TypeStruct::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +TypeStruct::~TypeStruct() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeStruct) + SharedDtor(*this); +} +inline void TypeStruct::SharedDtor(MessageLite& self) { + TypeStruct& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeStruct::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeStruct(arena); +} +constexpr auto TypeStruct::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_.member_) + + decltype(TypeStruct::_impl_.member_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(TypeStruct), alignof(TypeStruct), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&TypeStruct::PlacementNew_, + sizeof(TypeStruct), + alignof(TypeStruct)); + } +} +constexpr auto TypeStruct::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeStruct_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeStruct::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeStruct::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeStruct::ByteSizeLong, + &TypeStruct::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_._cached_size_), + false, + }, + &TypeStruct::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeStruct_class_data_ = + TypeStruct::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeStruct::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeStruct_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeStruct_class_data_.tc_table); + return TypeStruct_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 1, 46, 2> +TypeStruct::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + TypeStruct_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeStruct>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated .tint.core.ir.binary.pb.TypeStructMember member = 2; + {::_pbi::TcParser::FastMtR1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_.member_)}}, + // string name = 1; + {::_pbi::TcParser::FastUS1, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_.name_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string name = 1; + {PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // repeated .tint.core.ir.binary.pb.TypeStructMember member = 2; + {PROTOBUF_FIELD_OFFSET(TypeStruct, _impl_.member_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeStructMember>()}, + }}, + {{ + "\41\4\0\0\0\0\0\0" + "tint.core.ir.binary.pb.TypeStruct" + "name" + }}, +}; +PROTOBUF_NOINLINE void TypeStruct::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeStruct) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.member_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeStruct::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeStruct& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeStruct::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeStruct& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeStruct) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (!this_._internal_name().empty()) { + const ::std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "tint.core.ir.binary.pb.TypeStruct.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // repeated .tint.core.ir.binary.pb.TypeStructMember member = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_member_size()); + i < n; i++) { + const auto& repfield = this_._internal_member().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeStruct) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeStruct::ByteSizeLong(const MessageLite& base) { + const TypeStruct& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeStruct::ByteSizeLong() const { + const TypeStruct& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeStruct) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .tint.core.ir.binary.pb.TypeStructMember member = 2; + { + total_size += 1UL * this_._internal_member_size(); + for (const auto& msg : this_._internal_member()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + { + // string name = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeStruct::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeStruct) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_member()->MergeFrom( + from._internal_member()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeStruct::CopyFrom(const TypeStruct& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeStruct) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeStruct::InternalSwap(TypeStruct* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.member_.InternalSwap(&other->_impl_.member_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); +} + +::google::protobuf::Metadata TypeStruct::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeStructMember::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_._has_bits_); +}; + +TypeStructMember::TypeStructMember(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeStructMember_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeStructMember) +} +PROTOBUF_NDEBUG_INLINE TypeStructMember::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::TypeStructMember& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + name_(arena, from.name_) {} + +TypeStructMember::TypeStructMember( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const TypeStructMember& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeStructMember_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + TypeStructMember* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.attributes_ = ((cached_has_bits & 0x00000002U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.attributes_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, type_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, type_), + offsetof(Impl_, align_) - + offsetof(Impl_, type_) + + sizeof(Impl_::align_)); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.TypeStructMember) +} +PROTOBUF_NDEBUG_INLINE TypeStructMember::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + name_(arena) {} + +inline void TypeStructMember::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, attributes_), + 0, + offsetof(Impl_, align_) - + offsetof(Impl_, attributes_) + + sizeof(Impl_::align_)); +} +TypeStructMember::~TypeStructMember() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeStructMember) + SharedDtor(*this); +} +inline void TypeStructMember::SharedDtor(MessageLite& self) { + TypeStructMember& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.attributes_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeStructMember::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeStructMember(arena); +} +constexpr auto TypeStructMember::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(TypeStructMember), + alignof(TypeStructMember)); +} +constexpr auto TypeStructMember::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeStructMember_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeStructMember::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeStructMember::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeStructMember::ByteSizeLong, + &TypeStructMember::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_._cached_size_), + false, + }, + &TypeStructMember::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeStructMember_class_data_ = + TypeStructMember::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeStructMember::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeStructMember_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeStructMember_class_data_.tc_table); + return TypeStructMember_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<3, 5, 1, 52, 2> +TypeStructMember::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_._has_bits_), + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967264, // skipmap + offsetof(decltype(_table_), field_entries), + 5, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + TypeStructMember_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeStructMember>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string name = 1; + {::_pbi::TcParser::FastUS1, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.name_)}}, + // uint32 type = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeStructMember, _impl_.type_), 2>(), + {16, 2, 0, PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.type_)}}, + // uint32 size = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeStructMember, _impl_.size_), 3>(), + {24, 3, 0, PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.size_)}}, + // uint32 align = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeStructMember, _impl_.align_), 4>(), + {32, 4, 0, PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.align_)}}, + // optional .tint.core.ir.binary.pb.AttributesStructMember attributes = 5; + {::_pbi::TcParser::FastMtS1, + {42, 1, 0, PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.attributes_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string name = 1; + {PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint32 type = 2; + {PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.type_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 size = 3; + {PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.size_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 align = 4; + {PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.align_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional .tint.core.ir.binary.pb.AttributesStructMember attributes = 5; + {PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.attributes_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::AttributesStructMember>()}, + }}, + {{ + "\47\4\0\0\0\0\0\0" + "tint.core.ir.binary.pb.TypeStructMember" + "name" + }}, +}; +PROTOBUF_NOINLINE void TypeStructMember::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeStructMember) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(_impl_.attributes_ != nullptr); + _impl_.attributes_->Clear(); + } + } + if ((cached_has_bits & 0x0000001cU) != 0) { + ::memset(&_impl_.type_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.align_) - + reinterpret_cast(&_impl_.type_)) + sizeof(_impl_.align_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeStructMember::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeStructMember& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeStructMember::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeStructMember& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeStructMember) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (!this_._internal_name().empty()) { + const ::std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "tint.core.ir.binary.pb.TypeStructMember.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint32 type = 2; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_type(), target); + } + } + + // uint32 size = 3; + if ((this_._impl_._has_bits_[0] & 0x00000008U) != 0) { + if (this_._internal_size() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_size(), target); + } + } + + // uint32 align = 4; + if ((this_._impl_._has_bits_[0] & 0x00000010U) != 0) { + if (this_._internal_align() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 4, this_._internal_align(), target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .tint.core.ir.binary.pb.AttributesStructMember attributes = 5; + if ((cached_has_bits & 0x00000002U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.attributes_, this_._impl_.attributes_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeStructMember) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeStructMember::ByteSizeLong(const MessageLite& base) { + const TypeStructMember& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeStructMember::ByteSizeLong() const { + const TypeStructMember& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeStructMember) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x0000001fU) != 0) { + // string name = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // optional .tint.core.ir.binary.pb.AttributesStructMember attributes = 5; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.attributes_); + } + // uint32 type = 2; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + // uint32 size = 3; + if ((cached_has_bits & 0x00000008U) != 0) { + if (this_._internal_size() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_size()); + } + } + // uint32 align = 4; + if ((cached_has_bits & 0x00000010U) != 0) { + if (this_._internal_align() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_align()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeStructMember::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeStructMember) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x0000001fU) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(from._impl_.attributes_ != nullptr); + if (_this->_impl_.attributes_ == nullptr) { + _this->_impl_.attributes_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.attributes_); + } else { + _this->_impl_.attributes_->MergeFrom(*from._impl_.attributes_); + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + if ((cached_has_bits & 0x00000008U) != 0) { + if (from._internal_size() != 0) { + _this->_impl_.size_ = from._impl_.size_; + } + } + if ((cached_has_bits & 0x00000010U) != 0) { + if (from._internal_align() != 0) { + _this->_impl_.align_ = from._impl_.align_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeStructMember::CopyFrom(const TypeStructMember& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeStructMember) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeStructMember::InternalSwap(TypeStructMember* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.align_) + + sizeof(TypeStructMember::_impl_.align_) + - PROTOBUF_FIELD_OFFSET(TypeStructMember, _impl_.attributes_)>( + reinterpret_cast(&_impl_.attributes_), + reinterpret_cast(&other->_impl_.attributes_)); +} + +::google::protobuf::Metadata TypeStructMember::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeAtomic::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeAtomic, _impl_._has_bits_); +}; + +TypeAtomic::TypeAtomic(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeAtomic_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeAtomic) +} +TypeAtomic::TypeAtomic( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeAtomic& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeAtomic_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeAtomic::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeAtomic::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.type_ = {}; +} +TypeAtomic::~TypeAtomic() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeAtomic) + SharedDtor(*this); +} +inline void TypeAtomic::SharedDtor(MessageLite& self) { + TypeAtomic& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeAtomic::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeAtomic(arena); +} +constexpr auto TypeAtomic::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeAtomic), + alignof(TypeAtomic)); +} +constexpr auto TypeAtomic::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeAtomic_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeAtomic::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeAtomic::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeAtomic::ByteSizeLong, + &TypeAtomic::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeAtomic, _impl_._cached_size_), + false, + }, + &TypeAtomic::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeAtomic_class_data_ = + TypeAtomic::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeAtomic::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeAtomic_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeAtomic_class_data_.tc_table); + return TypeAtomic_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +TypeAtomic::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeAtomic, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeAtomic_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeAtomic>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeAtomic, _impl_.type_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeAtomic, _impl_.type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 type = 1; + {PROTOBUF_FIELD_OFFSET(TypeAtomic, _impl_.type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeAtomic::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeAtomic) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.type_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeAtomic::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeAtomic& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeAtomic::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeAtomic& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeAtomic) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_type(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeAtomic) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeAtomic::ByteSizeLong(const MessageLite& base) { + const TypeAtomic& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeAtomic::ByteSizeLong() const { + const TypeAtomic& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeAtomic) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // uint32 type = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeAtomic::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeAtomic) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeAtomic::CopyFrom(const TypeAtomic& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeAtomic) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeAtomic::InternalSwap(TypeAtomic* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.type_, other->_impl_.type_); +} + +::google::protobuf::Metadata TypeAtomic::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeDepthTexture::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeDepthTexture, _impl_._has_bits_); +}; + +TypeDepthTexture::TypeDepthTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeDepthTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeDepthTexture) +} +TypeDepthTexture::TypeDepthTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeDepthTexture& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeDepthTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeDepthTexture::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeDepthTexture::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.dimension_ = {}; +} +TypeDepthTexture::~TypeDepthTexture() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeDepthTexture) + SharedDtor(*this); +} +inline void TypeDepthTexture::SharedDtor(MessageLite& self) { + TypeDepthTexture& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeDepthTexture::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeDepthTexture(arena); +} +constexpr auto TypeDepthTexture::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeDepthTexture), + alignof(TypeDepthTexture)); +} +constexpr auto TypeDepthTexture::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeDepthTexture_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeDepthTexture::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeDepthTexture::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeDepthTexture::ByteSizeLong, + &TypeDepthTexture::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeDepthTexture, _impl_._cached_size_), + false, + }, + &TypeDepthTexture::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeDepthTexture_class_data_ = + TypeDepthTexture::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeDepthTexture::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeDepthTexture_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeDepthTexture_class_data_.tc_table); + return TypeDepthTexture_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +TypeDepthTexture::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeDepthTexture, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeDepthTexture_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeDepthTexture>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeDepthTexture, _impl_.dimension_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeDepthTexture, _impl_.dimension_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {PROTOBUF_FIELD_OFFSET(TypeDepthTexture, _impl_.dimension_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeDepthTexture::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeDepthTexture) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.dimension_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeDepthTexture::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeDepthTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeDepthTexture::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeDepthTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeDepthTexture) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_dimension(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeDepthTexture) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeDepthTexture::ByteSizeLong(const MessageLite& base) { + const TypeDepthTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeDepthTexture::ByteSizeLong() const { + const TypeDepthTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeDepthTexture) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_dimension()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeDepthTexture::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeDepthTexture) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_dimension() != 0) { + _this->_impl_.dimension_ = from._impl_.dimension_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeDepthTexture::CopyFrom(const TypeDepthTexture& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeDepthTexture) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeDepthTexture::InternalSwap(TypeDepthTexture* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.dimension_, other->_impl_.dimension_); +} + +::google::protobuf::Metadata TypeDepthTexture::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeSampledTexture::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_._has_bits_); +}; + +TypeSampledTexture::TypeSampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeSampledTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeSampledTexture) +} +TypeSampledTexture::TypeSampledTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeSampledTexture& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeSampledTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeSampledTexture::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeSampledTexture::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, dimension_), + 0, + offsetof(Impl_, sub_type_) - + offsetof(Impl_, dimension_) + + sizeof(Impl_::sub_type_)); +} +TypeSampledTexture::~TypeSampledTexture() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeSampledTexture) + SharedDtor(*this); +} +inline void TypeSampledTexture::SharedDtor(MessageLite& self) { + TypeSampledTexture& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeSampledTexture::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeSampledTexture(arena); +} +constexpr auto TypeSampledTexture::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeSampledTexture), + alignof(TypeSampledTexture)); +} +constexpr auto TypeSampledTexture::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeSampledTexture_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeSampledTexture::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeSampledTexture::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeSampledTexture::ByteSizeLong, + &TypeSampledTexture::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_._cached_size_), + false, + }, + &TypeSampledTexture::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeSampledTexture_class_data_ = + TypeSampledTexture::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeSampledTexture::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeSampledTexture_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeSampledTexture_class_data_.tc_table); + return TypeSampledTexture_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +TypeSampledTexture::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeSampledTexture_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSampledTexture>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 sub_type = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeSampledTexture, _impl_.sub_type_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_.sub_type_)}}, + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeSampledTexture, _impl_.dimension_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_.dimension_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_.dimension_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // uint32 sub_type = 2; + {PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_.sub_type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeSampledTexture::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeSampledTexture) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.dimension_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.sub_type_) - + reinterpret_cast(&_impl_.dimension_)) + sizeof(_impl_.sub_type_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeSampledTexture::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeSampledTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeSampledTexture::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeSampledTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeSampledTexture) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_dimension(), target); + } + } + + // uint32 sub_type = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_sub_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_sub_type(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeSampledTexture) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeSampledTexture::ByteSizeLong(const MessageLite& base) { + const TypeSampledTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeSampledTexture::ByteSizeLong() const { + const TypeSampledTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeSampledTexture) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_dimension()); + } + } + // uint32 sub_type = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_sub_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_sub_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeSampledTexture::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeSampledTexture) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_dimension() != 0) { + _this->_impl_.dimension_ = from._impl_.dimension_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_sub_type() != 0) { + _this->_impl_.sub_type_ = from._impl_.sub_type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeSampledTexture::CopyFrom(const TypeSampledTexture& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeSampledTexture) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeSampledTexture::InternalSwap(TypeSampledTexture* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_.sub_type_) + + sizeof(TypeSampledTexture::_impl_.sub_type_) + - PROTOBUF_FIELD_OFFSET(TypeSampledTexture, _impl_.dimension_)>( + reinterpret_cast(&_impl_.dimension_), + reinterpret_cast(&other->_impl_.dimension_)); +} + +::google::protobuf::Metadata TypeSampledTexture::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeMultisampledTexture::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_._has_bits_); +}; + +TypeMultisampledTexture::TypeMultisampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeMultisampledTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeMultisampledTexture) +} +TypeMultisampledTexture::TypeMultisampledTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeMultisampledTexture& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeMultisampledTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeMultisampledTexture::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeMultisampledTexture::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, dimension_), + 0, + offsetof(Impl_, sub_type_) - + offsetof(Impl_, dimension_) + + sizeof(Impl_::sub_type_)); +} +TypeMultisampledTexture::~TypeMultisampledTexture() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeMultisampledTexture) + SharedDtor(*this); +} +inline void TypeMultisampledTexture::SharedDtor(MessageLite& self) { + TypeMultisampledTexture& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeMultisampledTexture::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeMultisampledTexture(arena); +} +constexpr auto TypeMultisampledTexture::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeMultisampledTexture), + alignof(TypeMultisampledTexture)); +} +constexpr auto TypeMultisampledTexture::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeMultisampledTexture_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeMultisampledTexture::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeMultisampledTexture::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeMultisampledTexture::ByteSizeLong, + &TypeMultisampledTexture::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_._cached_size_), + false, + }, + &TypeMultisampledTexture::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeMultisampledTexture_class_data_ = + TypeMultisampledTexture::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeMultisampledTexture::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeMultisampledTexture_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeMultisampledTexture_class_data_.tc_table); + return TypeMultisampledTexture_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +TypeMultisampledTexture::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeMultisampledTexture_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeMultisampledTexture>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 sub_type = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeMultisampledTexture, _impl_.sub_type_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_.sub_type_)}}, + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeMultisampledTexture, _impl_.dimension_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_.dimension_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_.dimension_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // uint32 sub_type = 2; + {PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_.sub_type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeMultisampledTexture::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeMultisampledTexture) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.dimension_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.sub_type_) - + reinterpret_cast(&_impl_.dimension_)) + sizeof(_impl_.sub_type_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeMultisampledTexture::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeMultisampledTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeMultisampledTexture::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeMultisampledTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeMultisampledTexture) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_dimension(), target); + } + } + + // uint32 sub_type = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_sub_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_sub_type(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeMultisampledTexture) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeMultisampledTexture::ByteSizeLong(const MessageLite& base) { + const TypeMultisampledTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeMultisampledTexture::ByteSizeLong() const { + const TypeMultisampledTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeMultisampledTexture) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_dimension()); + } + } + // uint32 sub_type = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_sub_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_sub_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeMultisampledTexture::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeMultisampledTexture) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_dimension() != 0) { + _this->_impl_.dimension_ = from._impl_.dimension_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_sub_type() != 0) { + _this->_impl_.sub_type_ = from._impl_.sub_type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeMultisampledTexture::CopyFrom(const TypeMultisampledTexture& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeMultisampledTexture) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeMultisampledTexture::InternalSwap(TypeMultisampledTexture* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_.sub_type_) + + sizeof(TypeMultisampledTexture::_impl_.sub_type_) + - PROTOBUF_FIELD_OFFSET(TypeMultisampledTexture, _impl_.dimension_)>( + reinterpret_cast(&_impl_.dimension_), + reinterpret_cast(&other->_impl_.dimension_)); +} + +::google::protobuf::Metadata TypeMultisampledTexture::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeDepthMultisampledTexture::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeDepthMultisampledTexture, _impl_._has_bits_); +}; + +TypeDepthMultisampledTexture::TypeDepthMultisampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeDepthMultisampledTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) +} +TypeDepthMultisampledTexture::TypeDepthMultisampledTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeDepthMultisampledTexture& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeDepthMultisampledTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeDepthMultisampledTexture::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeDepthMultisampledTexture::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.dimension_ = {}; +} +TypeDepthMultisampledTexture::~TypeDepthMultisampledTexture() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + SharedDtor(*this); +} +inline void TypeDepthMultisampledTexture::SharedDtor(MessageLite& self) { + TypeDepthMultisampledTexture& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeDepthMultisampledTexture::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeDepthMultisampledTexture(arena); +} +constexpr auto TypeDepthMultisampledTexture::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeDepthMultisampledTexture), + alignof(TypeDepthMultisampledTexture)); +} +constexpr auto TypeDepthMultisampledTexture::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeDepthMultisampledTexture_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeDepthMultisampledTexture::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeDepthMultisampledTexture::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeDepthMultisampledTexture::ByteSizeLong, + &TypeDepthMultisampledTexture::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeDepthMultisampledTexture, _impl_._cached_size_), + false, + }, + &TypeDepthMultisampledTexture::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeDepthMultisampledTexture_class_data_ = + TypeDepthMultisampledTexture::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeDepthMultisampledTexture::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeDepthMultisampledTexture_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeDepthMultisampledTexture_class_data_.tc_table); + return TypeDepthMultisampledTexture_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +TypeDepthMultisampledTexture::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeDepthMultisampledTexture, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeDepthMultisampledTexture_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeDepthMultisampledTexture, _impl_.dimension_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeDepthMultisampledTexture, _impl_.dimension_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {PROTOBUF_FIELD_OFFSET(TypeDepthMultisampledTexture, _impl_.dimension_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeDepthMultisampledTexture::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.dimension_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeDepthMultisampledTexture::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeDepthMultisampledTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeDepthMultisampledTexture::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeDepthMultisampledTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_dimension(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeDepthMultisampledTexture::ByteSizeLong(const MessageLite& base) { + const TypeDepthMultisampledTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeDepthMultisampledTexture::ByteSizeLong() const { + const TypeDepthMultisampledTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_dimension()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeDepthMultisampledTexture::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_dimension() != 0) { + _this->_impl_.dimension_ = from._impl_.dimension_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeDepthMultisampledTexture::CopyFrom(const TypeDepthMultisampledTexture& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeDepthMultisampledTexture::InternalSwap(TypeDepthMultisampledTexture* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.dimension_, other->_impl_.dimension_); +} + +::google::protobuf::Metadata TypeDepthMultisampledTexture::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeStorageTexture::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_._has_bits_); +}; + +TypeStorageTexture::TypeStorageTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeStorageTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeStorageTexture) +} +TypeStorageTexture::TypeStorageTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeStorageTexture& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeStorageTexture_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeStorageTexture::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeStorageTexture::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, dimension_), + 0, + offsetof(Impl_, access_) - + offsetof(Impl_, dimension_) + + sizeof(Impl_::access_)); +} +TypeStorageTexture::~TypeStorageTexture() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeStorageTexture) + SharedDtor(*this); +} +inline void TypeStorageTexture::SharedDtor(MessageLite& self) { + TypeStorageTexture& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeStorageTexture::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeStorageTexture(arena); +} +constexpr auto TypeStorageTexture::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeStorageTexture), + alignof(TypeStorageTexture)); +} +constexpr auto TypeStorageTexture::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeStorageTexture_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeStorageTexture::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeStorageTexture::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeStorageTexture::ByteSizeLong, + &TypeStorageTexture::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_._cached_size_), + false, + }, + &TypeStorageTexture::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeStorageTexture_class_data_ = + TypeStorageTexture::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeStorageTexture::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeStorageTexture_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeStorageTexture_class_data_.tc_table); + return TypeStorageTexture_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +TypeStorageTexture::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeStorageTexture_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeStorageTexture>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeStorageTexture, _impl_.dimension_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.dimension_)}}, + // .tint.core.ir.binary.pb.TexelFormat texel_format = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeStorageTexture, _impl_.texel_format_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.texel_format_)}}, + // .tint.core.ir.binary.pb.AccessControl access = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeStorageTexture, _impl_.access_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.access_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + {PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.dimension_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .tint.core.ir.binary.pb.TexelFormat texel_format = 2; + {PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.texel_format_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .tint.core.ir.binary.pb.AccessControl access = 3; + {PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.access_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeStorageTexture::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeStorageTexture) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.dimension_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.access_) - + reinterpret_cast(&_impl_.dimension_)) + sizeof(_impl_.access_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeStorageTexture::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeStorageTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeStorageTexture::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeStorageTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeStorageTexture) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_dimension(), target); + } + } + + // .tint.core.ir.binary.pb.TexelFormat texel_format = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_texel_format() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_texel_format(), target); + } + } + + // .tint.core.ir.binary.pb.AccessControl access = 3; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_access() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_access(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeStorageTexture) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeStorageTexture::ByteSizeLong(const MessageLite& base) { + const TypeStorageTexture& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeStorageTexture::ByteSizeLong() const { + const TypeStorageTexture& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeStorageTexture) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_dimension() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_dimension()); + } + } + // .tint.core.ir.binary.pb.TexelFormat texel_format = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_texel_format() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_texel_format()); + } + } + // .tint.core.ir.binary.pb.AccessControl access = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_access() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_access()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeStorageTexture::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeStorageTexture) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_dimension() != 0) { + _this->_impl_.dimension_ = from._impl_.dimension_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_texel_format() != 0) { + _this->_impl_.texel_format_ = from._impl_.texel_format_; + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_access() != 0) { + _this->_impl_.access_ = from._impl_.access_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeStorageTexture::CopyFrom(const TypeStorageTexture& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeStorageTexture) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeStorageTexture::InternalSwap(TypeStorageTexture* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.access_) + + sizeof(TypeStorageTexture::_impl_.access_) + - PROTOBUF_FIELD_OFFSET(TypeStorageTexture, _impl_.dimension_)>( + reinterpret_cast(&_impl_.dimension_), + reinterpret_cast(&other->_impl_.dimension_)); +} + +::google::protobuf::Metadata TypeStorageTexture::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeResourceBinding::_Internal { + public: +}; + +TypeResourceBinding::TypeResourceBinding(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, TypeResourceBinding_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeResourceBinding) +} +TypeResourceBinding::TypeResourceBinding( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const TypeResourceBinding& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, TypeResourceBinding_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + TypeResourceBinding* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.TypeResourceBinding) +} + +inline void* PROTOBUF_NONNULL TypeResourceBinding::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeResourceBinding(arena); +} +constexpr auto TypeResourceBinding::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeResourceBinding), + alignof(TypeResourceBinding)); +} +constexpr auto TypeResourceBinding::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeResourceBinding_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeResourceBinding::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeResourceBinding::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &TypeResourceBinding::ByteSizeLong, + &TypeResourceBinding::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeResourceBinding, _impl_._cached_size_), + false, + }, + &TypeResourceBinding::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeResourceBinding_class_data_ = + TypeResourceBinding::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeResourceBinding::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeResourceBinding_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeResourceBinding_class_data_.tc_table); + return TypeResourceBinding_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +TypeResourceBinding::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeResourceBinding_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeResourceBinding>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata TypeResourceBinding::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeExternalTexture::_Internal { + public: +}; + +TypeExternalTexture::TypeExternalTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, TypeExternalTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeExternalTexture) +} +TypeExternalTexture::TypeExternalTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const TypeExternalTexture& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, TypeExternalTexture_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + TypeExternalTexture* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.TypeExternalTexture) +} + +inline void* PROTOBUF_NONNULL TypeExternalTexture::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeExternalTexture(arena); +} +constexpr auto TypeExternalTexture::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeExternalTexture), + alignof(TypeExternalTexture)); +} +constexpr auto TypeExternalTexture::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeExternalTexture_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeExternalTexture::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeExternalTexture::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &TypeExternalTexture::ByteSizeLong, + &TypeExternalTexture::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeExternalTexture, _impl_._cached_size_), + false, + }, + &TypeExternalTexture::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeExternalTexture_class_data_ = + TypeExternalTexture::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeExternalTexture::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeExternalTexture_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeExternalTexture_class_data_.tc_table); + return TypeExternalTexture_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +TypeExternalTexture::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeExternalTexture_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeExternalTexture>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata TypeExternalTexture::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeSampler::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeSampler, _impl_._has_bits_); +}; + +TypeSampler::TypeSampler(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeSampler_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeSampler) +} +TypeSampler::TypeSampler( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeSampler& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeSampler_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeSampler::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeSampler::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.kind_ = {}; +} +TypeSampler::~TypeSampler() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeSampler) + SharedDtor(*this); +} +inline void TypeSampler::SharedDtor(MessageLite& self) { + TypeSampler& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeSampler::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeSampler(arena); +} +constexpr auto TypeSampler::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeSampler), + alignof(TypeSampler)); +} +constexpr auto TypeSampler::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeSampler_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeSampler::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeSampler::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeSampler::ByteSizeLong, + &TypeSampler::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeSampler, _impl_._cached_size_), + false, + }, + &TypeSampler::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeSampler_class_data_ = + TypeSampler::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeSampler::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeSampler_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeSampler_class_data_.tc_table); + return TypeSampler_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +TypeSampler::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeSampler, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeSampler_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSampler>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .tint.core.ir.binary.pb.SamplerKind kind = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeSampler, _impl_.kind_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeSampler, _impl_.kind_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.SamplerKind kind = 1; + {PROTOBUF_FIELD_OFFSET(TypeSampler, _impl_.kind_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeSampler::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeSampler) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.kind_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeSampler::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeSampler& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeSampler::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeSampler& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeSampler) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.SamplerKind kind = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_kind() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_kind(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeSampler) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeSampler::ByteSizeLong(const MessageLite& base) { + const TypeSampler& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeSampler::ByteSizeLong() const { + const TypeSampler& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeSampler) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // .tint.core.ir.binary.pb.SamplerKind kind = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_kind() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_kind()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeSampler::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeSampler) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_kind() != 0) { + _this->_impl_.kind_ = from._impl_.kind_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeSampler::CopyFrom(const TypeSampler& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeSampler) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeSampler::InternalSwap(TypeSampler* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.kind_, other->_impl_.kind_); +} + +::google::protobuf::Metadata TypeSampler::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeInputAttachment::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeInputAttachment, _impl_._has_bits_); +}; + +TypeInputAttachment::TypeInputAttachment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeInputAttachment_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeInputAttachment) +} +TypeInputAttachment::TypeInputAttachment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeInputAttachment& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeInputAttachment_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeInputAttachment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeInputAttachment::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.sub_type_ = {}; +} +TypeInputAttachment::~TypeInputAttachment() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeInputAttachment) + SharedDtor(*this); +} +inline void TypeInputAttachment::SharedDtor(MessageLite& self) { + TypeInputAttachment& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeInputAttachment::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeInputAttachment(arena); +} +constexpr auto TypeInputAttachment::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeInputAttachment), + alignof(TypeInputAttachment)); +} +constexpr auto TypeInputAttachment::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeInputAttachment_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeInputAttachment::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeInputAttachment::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeInputAttachment::ByteSizeLong, + &TypeInputAttachment::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeInputAttachment, _impl_._cached_size_), + false, + }, + &TypeInputAttachment::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeInputAttachment_class_data_ = + TypeInputAttachment::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeInputAttachment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeInputAttachment_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeInputAttachment_class_data_.tc_table); + return TypeInputAttachment_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +TypeInputAttachment::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeInputAttachment, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeInputAttachment_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeInputAttachment>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 sub_type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeInputAttachment, _impl_.sub_type_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeInputAttachment, _impl_.sub_type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 sub_type = 1; + {PROTOBUF_FIELD_OFFSET(TypeInputAttachment, _impl_.sub_type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeInputAttachment::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeInputAttachment) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.sub_type_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeInputAttachment::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeInputAttachment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeInputAttachment::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeInputAttachment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeInputAttachment) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 sub_type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_sub_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_sub_type(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeInputAttachment) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeInputAttachment::ByteSizeLong(const MessageLite& base) { + const TypeInputAttachment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeInputAttachment::ByteSizeLong() const { + const TypeInputAttachment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeInputAttachment) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // uint32 sub_type = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_sub_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_sub_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeInputAttachment::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeInputAttachment) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_sub_type() != 0) { + _this->_impl_.sub_type_ = from._impl_.sub_type_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeInputAttachment::CopyFrom(const TypeInputAttachment& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeInputAttachment) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeInputAttachment::InternalSwap(TypeInputAttachment* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.sub_type_, other->_impl_.sub_type_); +} + +::google::protobuf::Metadata TypeInputAttachment::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeSubgroupMatrix::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_._has_bits_); +}; + +TypeSubgroupMatrix::TypeSubgroupMatrix(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeSubgroupMatrix_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeSubgroupMatrix) +} +TypeSubgroupMatrix::TypeSubgroupMatrix( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeSubgroupMatrix& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeSubgroupMatrix_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeSubgroupMatrix::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeSubgroupMatrix::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, sub_type_), + 0, + offsetof(Impl_, columns_) - + offsetof(Impl_, sub_type_) + + sizeof(Impl_::columns_)); +} +TypeSubgroupMatrix::~TypeSubgroupMatrix() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeSubgroupMatrix) + SharedDtor(*this); +} +inline void TypeSubgroupMatrix::SharedDtor(MessageLite& self) { + TypeSubgroupMatrix& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeSubgroupMatrix::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeSubgroupMatrix(arena); +} +constexpr auto TypeSubgroupMatrix::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeSubgroupMatrix), + alignof(TypeSubgroupMatrix)); +} +constexpr auto TypeSubgroupMatrix::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeSubgroupMatrix_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeSubgroupMatrix::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeSubgroupMatrix::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeSubgroupMatrix::ByteSizeLong, + &TypeSubgroupMatrix::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_._cached_size_), + false, + }, + &TypeSubgroupMatrix::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeSubgroupMatrix_class_data_ = + TypeSubgroupMatrix::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeSubgroupMatrix::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeSubgroupMatrix_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeSubgroupMatrix_class_data_.tc_table); + return TypeSubgroupMatrix_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +TypeSubgroupMatrix::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeSubgroupMatrix_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeSubgroupMatrix>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 sub_type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeSubgroupMatrix, _impl_.sub_type_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.sub_type_)}}, + // uint32 rows = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeSubgroupMatrix, _impl_.rows_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.rows_)}}, + // uint32 columns = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeSubgroupMatrix, _impl_.columns_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.columns_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 sub_type = 1; + {PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.sub_type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 rows = 2; + {PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.rows_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 columns = 3; + {PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.columns_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeSubgroupMatrix::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeSubgroupMatrix) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.sub_type_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.columns_) - + reinterpret_cast(&_impl_.sub_type_)) + sizeof(_impl_.columns_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeSubgroupMatrix::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeSubgroupMatrix& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeSubgroupMatrix::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeSubgroupMatrix& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeSubgroupMatrix) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 sub_type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_sub_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_sub_type(), target); + } + } + + // uint32 rows = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_rows() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_rows(), target); + } + } + + // uint32 columns = 3; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_columns() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_columns(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeSubgroupMatrix) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeSubgroupMatrix::ByteSizeLong(const MessageLite& base) { + const TypeSubgroupMatrix& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeSubgroupMatrix::ByteSizeLong() const { + const TypeSubgroupMatrix& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeSubgroupMatrix) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // uint32 sub_type = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_sub_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_sub_type()); + } + } + // uint32 rows = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_rows() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_rows()); + } + } + // uint32 columns = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_columns() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_columns()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeSubgroupMatrix::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeSubgroupMatrix) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_sub_type() != 0) { + _this->_impl_.sub_type_ = from._impl_.sub_type_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_rows() != 0) { + _this->_impl_.rows_ = from._impl_.rows_; + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_columns() != 0) { + _this->_impl_.columns_ = from._impl_.columns_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeSubgroupMatrix::CopyFrom(const TypeSubgroupMatrix& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeSubgroupMatrix) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeSubgroupMatrix::InternalSwap(TypeSubgroupMatrix* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.columns_) + + sizeof(TypeSubgroupMatrix::_impl_.columns_) + - PROTOBUF_FIELD_OFFSET(TypeSubgroupMatrix, _impl_.sub_type_)>( + reinterpret_cast(&_impl_.sub_type_), + reinterpret_cast(&other->_impl_.sub_type_)); +} + +::google::protobuf::Metadata TypeSubgroupMatrix::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeBuffer::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeBuffer, _impl_._has_bits_); +}; + +TypeBuffer::TypeBuffer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeBuffer_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeBuffer) +} +TypeBuffer::TypeBuffer( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeBuffer& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeBuffer_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeBuffer::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeBuffer::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.count_ = {}; +} +TypeBuffer::~TypeBuffer() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeBuffer) + SharedDtor(*this); +} +inline void TypeBuffer::SharedDtor(MessageLite& self) { + TypeBuffer& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeBuffer::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeBuffer(arena); +} +constexpr auto TypeBuffer::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeBuffer), + alignof(TypeBuffer)); +} +constexpr auto TypeBuffer::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeBuffer_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeBuffer::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeBuffer::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeBuffer::ByteSizeLong, + &TypeBuffer::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeBuffer, _impl_._cached_size_), + false, + }, + &TypeBuffer::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeBuffer_class_data_ = + TypeBuffer::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeBuffer::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeBuffer_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeBuffer_class_data_.tc_table); + return TypeBuffer_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +TypeBuffer::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeBuffer, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeBuffer_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeBuffer>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 count = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeBuffer, _impl_.count_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeBuffer, _impl_.count_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 count = 1; + {PROTOBUF_FIELD_OFFSET(TypeBuffer, _impl_.count_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeBuffer::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeBuffer) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.count_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeBuffer::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeBuffer& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeBuffer::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeBuffer& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeBuffer) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 count = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_count() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_count(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeBuffer) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeBuffer::ByteSizeLong(const MessageLite& base) { + const TypeBuffer& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeBuffer::ByteSizeLong() const { + const TypeBuffer& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeBuffer) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // uint32 count = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_count() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_count()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeBuffer::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeBuffer) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_count() != 0) { + _this->_impl_.count_ = from._impl_.count_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeBuffer::CopyFrom(const TypeBuffer& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeBuffer) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeBuffer::InternalSwap(TypeBuffer* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.count_, other->_impl_.count_); +} + +::google::protobuf::Metadata TypeBuffer::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class TypeTexelBuffer::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_._has_bits_); +}; + +TypeTexelBuffer::TypeTexelBuffer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeTexelBuffer_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.TypeTexelBuffer) +} +TypeTexelBuffer::TypeTexelBuffer( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeTexelBuffer& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, TypeTexelBuffer_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE TypeTexelBuffer::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void TypeTexelBuffer::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, texel_format_), + 0, + offsetof(Impl_, access_) - + offsetof(Impl_, texel_format_) + + sizeof(Impl_::access_)); +} +TypeTexelBuffer::~TypeTexelBuffer() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.TypeTexelBuffer) + SharedDtor(*this); +} +inline void TypeTexelBuffer::SharedDtor(MessageLite& self) { + TypeTexelBuffer& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL TypeTexelBuffer::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TypeTexelBuffer(arena); +} +constexpr auto TypeTexelBuffer::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(TypeTexelBuffer), + alignof(TypeTexelBuffer)); +} +constexpr auto TypeTexelBuffer::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_TypeTexelBuffer_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &TypeTexelBuffer::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TypeTexelBuffer::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &TypeTexelBuffer::ByteSizeLong, + &TypeTexelBuffer::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_._cached_size_), + false, + }, + &TypeTexelBuffer::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TypeTexelBuffer_class_data_ = + TypeTexelBuffer::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TypeTexelBuffer::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TypeTexelBuffer_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TypeTexelBuffer_class_data_.tc_table); + return TypeTexelBuffer_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +TypeTexelBuffer::_table_ = { + { + PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + TypeTexelBuffer_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::TypeTexelBuffer>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .tint.core.ir.binary.pb.AccessControl access = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeTexelBuffer, _impl_.access_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_.access_)}}, + // .tint.core.ir.binary.pb.TexelFormat texel_format = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TypeTexelBuffer, _impl_.texel_format_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_.texel_format_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.TexelFormat texel_format = 1; + {PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_.texel_format_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .tint.core.ir.binary.pb.AccessControl access = 2; + {PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_.access_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void TypeTexelBuffer::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.TypeTexelBuffer) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.texel_format_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.access_) - + reinterpret_cast(&_impl_.texel_format_)) + sizeof(_impl_.access_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TypeTexelBuffer::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TypeTexelBuffer& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TypeTexelBuffer::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TypeTexelBuffer& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.TypeTexelBuffer) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.TexelFormat texel_format = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_texel_format() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_texel_format(), target); + } + } + + // .tint.core.ir.binary.pb.AccessControl access = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_access() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_access(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.TypeTexelBuffer) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TypeTexelBuffer::ByteSizeLong(const MessageLite& base) { + const TypeTexelBuffer& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TypeTexelBuffer::ByteSizeLong() const { + const TypeTexelBuffer& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.TypeTexelBuffer) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // .tint.core.ir.binary.pb.TexelFormat texel_format = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_texel_format() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_texel_format()); + } + } + // .tint.core.ir.binary.pb.AccessControl access = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_access() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_access()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TypeTexelBuffer::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.TypeTexelBuffer) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_texel_format() != 0) { + _this->_impl_.texel_format_ = from._impl_.texel_format_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_access() != 0) { + _this->_impl_.access_ = from._impl_.access_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void TypeTexelBuffer::CopyFrom(const TypeTexelBuffer& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.TypeTexelBuffer) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TypeTexelBuffer::InternalSwap(TypeTexelBuffer* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_.access_) + + sizeof(TypeTexelBuffer::_impl_.access_) + - PROTOBUF_FIELD_OFFSET(TypeTexelBuffer, _impl_.texel_format_)>( + reinterpret_cast(&_impl_.texel_format_), + reinterpret_cast(&other->_impl_.texel_format_)); +} + +::google::protobuf::Metadata TypeTexelBuffer::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class Value::_Internal { + public: + static constexpr ::int32_t kOneofCaseOffset = + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Value, _impl_._oneof_case_); +}; + +void Value::set_allocated_instruction_result(::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE instruction_result) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (instruction_result) { + ::google::protobuf::Arena* submessage_arena = instruction_result->GetArena(); + if (message_arena != submessage_arena) { + instruction_result = ::google::protobuf::internal::GetOwnedMessage(message_arena, instruction_result, submessage_arena); + } + set_has_instruction_result(); + _impl_.kind_.instruction_result_ = instruction_result; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Value.instruction_result) +} +void Value::set_allocated_function_parameter(::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE function_parameter) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (function_parameter) { + ::google::protobuf::Arena* submessage_arena = function_parameter->GetArena(); + if (message_arena != submessage_arena) { + function_parameter = ::google::protobuf::internal::GetOwnedMessage(message_arena, function_parameter, submessage_arena); + } + set_has_function_parameter(); + _impl_.kind_.function_parameter_ = function_parameter; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Value.function_parameter) +} +void Value::set_allocated_block_parameter(::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE block_parameter) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (block_parameter) { + ::google::protobuf::Arena* submessage_arena = block_parameter->GetArena(); + if (message_arena != submessage_arena) { + block_parameter = ::google::protobuf::internal::GetOwnedMessage(message_arena, block_parameter, submessage_arena); + } + set_has_block_parameter(); + _impl_.kind_.block_parameter_ = block_parameter; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Value.block_parameter) +} +Value::Value(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Value_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Value) +} +PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::Value& from_msg) + : kind_{}, + _cached_size_{0}, + _oneof_case_{from._oneof_case_[0]} {} + +Value::Value( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Value& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Value_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Value* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + switch (kind_case()) { + case KIND_NOT_SET: + break; + case kFunction: + _impl_.kind_.function_ = from._impl_.kind_.function_; + break; + case kInstructionResult: + _impl_.kind_.instruction_result_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.instruction_result_); + break; + case kFunctionParameter: + _impl_.kind_.function_parameter_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.function_parameter_); + break; + case kBlockParameter: + _impl_.kind_.block_parameter_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.block_parameter_); + break; + case kConstant: + _impl_.kind_.constant_ = from._impl_.kind_.constant_; + break; + } + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.Value) +} +PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +inline void Value::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +Value::~Value() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Value) + SharedDtor(*this); +} +inline void Value::SharedDtor(MessageLite& self) { + Value& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + if (this_.has_kind()) { + this_.clear_kind(); + } + this_._impl_.~Impl_(); +} + +void Value::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:tint.core.ir.binary.pb.Value) + ::google::protobuf::internal::TSanWrite(&_impl_); + switch (kind_case()) { + case kFunction: { + // No need to clear + break; + } + case kInstructionResult: { + if (GetArena() == nullptr) { + delete _impl_.kind_.instruction_result_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.instruction_result_); + } + break; + } + case kFunctionParameter: { + if (GetArena() == nullptr) { + delete _impl_.kind_.function_parameter_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.function_parameter_); + } + break; + } + case kBlockParameter: { + if (GetArena() == nullptr) { + delete _impl_.kind_.block_parameter_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.block_parameter_); + } + break; + } + case kConstant: { + // No need to clear + break; + } + case KIND_NOT_SET: { + break; + } + } + _impl_._oneof_case_[0] = KIND_NOT_SET; +} + + +inline void* PROTOBUF_NONNULL Value::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Value(arena); +} +constexpr auto Value::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Value), + alignof(Value)); +} +constexpr auto Value::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Value_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Value::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Value::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Value::ByteSizeLong, + &Value::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Value, _impl_._cached_size_), + false, + }, + &Value::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Value_class_data_ = + Value::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Value::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Value_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Value_class_data_.tc_table); + return Value_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 5, 3, 0, 2> +Value::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 5, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967264, // skipmap + offsetof(decltype(_table_), field_entries), + 5, // num_field_entries + 3, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Value_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Value>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 function = 1; + {PROTOBUF_FIELD_OFFSET(Value, _impl_.kind_.function_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kUInt32)}, + // .tint.core.ir.binary.pb.InstructionResult instruction_result = 2; + {PROTOBUF_FIELD_OFFSET(Value, _impl_.kind_.instruction_result_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.FunctionParameter function_parameter = 3; + {PROTOBUF_FIELD_OFFSET(Value, _impl_.kind_.function_parameter_), _Internal::kOneofCaseOffset + 0, 1, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.BlockParameter block_parameter = 4; + {PROTOBUF_FIELD_OFFSET(Value, _impl_.kind_.block_parameter_), _Internal::kOneofCaseOffset + 0, 2, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint32 constant = 5; + {PROTOBUF_FIELD_OFFSET(Value, _impl_.kind_.constant_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kUInt32)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionResult>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::FunctionParameter>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::BlockParameter>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void Value::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Value) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + clear_kind(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Value::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Value& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Value::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Value& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Value) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + switch (this_.kind_case()) { + case kFunction: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_function(), target); + break; + } + case kInstructionResult: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.kind_.instruction_result_, this_._impl_.kind_.instruction_result_->GetCachedSize(), target, + stream); + break; + } + case kFunctionParameter: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.kind_.function_parameter_, this_._impl_.kind_.function_parameter_->GetCachedSize(), target, + stream); + break; + } + case kBlockParameter: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.kind_.block_parameter_, this_._impl_.kind_.block_parameter_->GetCachedSize(), target, + stream); + break; + } + case kConstant: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 5, this_._internal_constant(), target); + break; + } + default: + break; + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Value) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Value::ByteSizeLong(const MessageLite& base) { + const Value& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Value::ByteSizeLong() const { + const Value& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Value) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + switch (this_.kind_case()) { + // uint32 function = 1; + case kFunction: { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_function()); + break; + } + // .tint.core.ir.binary.pb.InstructionResult instruction_result = 2; + case kInstructionResult: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.instruction_result_); + break; + } + // .tint.core.ir.binary.pb.FunctionParameter function_parameter = 3; + case kFunctionParameter: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.function_parameter_); + break; + } + // .tint.core.ir.binary.pb.BlockParameter block_parameter = 4; + case kBlockParameter: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.block_parameter_); + break; + } + // uint32 constant = 5; + case kConstant: { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_constant()); + break; + } + case KIND_NOT_SET: { + break; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Value::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Value) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (const uint32_t oneof_from_case = from._impl_._oneof_case_[0]) { + const uint32_t oneof_to_case = _this->_impl_._oneof_case_[0]; + const bool oneof_needs_init = oneof_to_case != oneof_from_case; + if (oneof_needs_init) { + if (oneof_to_case != 0) { + _this->clear_kind(); + } + _this->_impl_._oneof_case_[0] = oneof_from_case; + } + + switch (oneof_from_case) { + case kFunction: { + _this->_impl_.kind_.function_ = from._impl_.kind_.function_; + break; + } + case kInstructionResult: { + if (oneof_needs_init) { + _this->_impl_.kind_.instruction_result_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.instruction_result_); + } else { + _this->_impl_.kind_.instruction_result_->MergeFrom(*from._impl_.kind_.instruction_result_); + } + break; + } + case kFunctionParameter: { + if (oneof_needs_init) { + _this->_impl_.kind_.function_parameter_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.function_parameter_); + } else { + _this->_impl_.kind_.function_parameter_->MergeFrom(*from._impl_.kind_.function_parameter_); + } + break; + } + case kBlockParameter: { + if (oneof_needs_init) { + _this->_impl_.kind_.block_parameter_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.block_parameter_); + } else { + _this->_impl_.kind_.block_parameter_->MergeFrom(*from._impl_.kind_.block_parameter_); + } + break; + } + case kConstant: { + _this->_impl_.kind_.constant_ = from._impl_.kind_.constant_; + break; + } + case KIND_NOT_SET: + break; + } + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Value::CopyFrom(const Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Value::InternalSwap(Value* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.kind_, other->_impl_.kind_); + swap(_impl_._oneof_case_[0], other->_impl_._oneof_case_[0]); +} + +::google::protobuf::Metadata Value::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionResult::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_._has_bits_); +}; + +InstructionResult::InstructionResult(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionResult_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionResult) +} +PROTOBUF_NDEBUG_INLINE InstructionResult::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::InstructionResult& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + name_(arena, from.name_) {} + +InstructionResult::InstructionResult( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionResult& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionResult_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionResult* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.type_ = from._impl_.type_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionResult) +} +PROTOBUF_NDEBUG_INLINE InstructionResult::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + name_(arena) {} + +inline void InstructionResult::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.type_ = {}; +} +InstructionResult::~InstructionResult() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionResult) + SharedDtor(*this); +} +inline void InstructionResult::SharedDtor(MessageLite& self) { + InstructionResult& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionResult::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionResult(arena); +} +constexpr auto InstructionResult::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(InstructionResult), + alignof(InstructionResult)); +} +constexpr auto InstructionResult::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionResult_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionResult::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionResult::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionResult::ByteSizeLong, + &InstructionResult::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_._cached_size_), + false, + }, + &InstructionResult::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionResult_class_data_ = + InstructionResult::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionResult::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionResult_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionResult_class_data_.tc_table); + return InstructionResult_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 53, 2> +InstructionResult::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionResult_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionResult>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // optional string name = 2; + {::_pbi::TcParser::FastUS1, + {18, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_.name_)}}, + // uint32 type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionResult, _impl_.type_), 1>(), + {8, 1, 0, PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_.type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 type = 1; + {PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_.type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional string name = 2; + {PROTOBUF_FIELD_OFFSET(InstructionResult, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\50\0\4\0\0\0\0\0" + "tint.core.ir.binary.pb.InstructionResult" + "name" + }}, +}; +PROTOBUF_NOINLINE void InstructionResult::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionResult) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + _impl_.type_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionResult::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionResult& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionResult::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionResult& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionResult) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_type(), target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 2; + if ((cached_has_bits & 0x00000001U) != 0) { + const ::std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "tint.core.ir.binary.pb.InstructionResult.name"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionResult) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionResult::ByteSizeLong(const MessageLite& base) { + const InstructionResult& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionResult::ByteSizeLong() const { + const InstructionResult& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionResult) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // optional string name = 2; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // uint32 type = 1; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionResult::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionResult) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _this->_internal_set_name(from._internal_name()); + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionResult::CopyFrom(const InstructionResult& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionResult) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionResult::InternalSwap(InstructionResult* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + swap(_impl_.type_, other->_impl_.type_); +} + +::google::protobuf::Metadata InstructionResult::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class FunctionParameter::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_._has_bits_); +}; + +FunctionParameter::FunctionParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FunctionParameter_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.FunctionParameter) +} +PROTOBUF_NDEBUG_INLINE FunctionParameter::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::FunctionParameter& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + name_(arena, from.name_) {} + +FunctionParameter::FunctionParameter( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const FunctionParameter& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FunctionParameter_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + FunctionParameter* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.attributes_ = ((cached_has_bits & 0x00000002U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.attributes_) + : nullptr; + _impl_.type_ = from._impl_.type_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.FunctionParameter) +} +PROTOBUF_NDEBUG_INLINE FunctionParameter::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + name_(arena) {} + +inline void FunctionParameter::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, attributes_), + 0, + offsetof(Impl_, type_) - + offsetof(Impl_, attributes_) + + sizeof(Impl_::type_)); +} +FunctionParameter::~FunctionParameter() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.FunctionParameter) + SharedDtor(*this); +} +inline void FunctionParameter::SharedDtor(MessageLite& self) { + FunctionParameter& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.attributes_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL FunctionParameter::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) FunctionParameter(arena); +} +constexpr auto FunctionParameter::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(FunctionParameter), + alignof(FunctionParameter)); +} +constexpr auto FunctionParameter::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FunctionParameter_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &FunctionParameter::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FunctionParameter::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FunctionParameter::ByteSizeLong, + &FunctionParameter::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_._cached_size_), + false, + }, + &FunctionParameter::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull FunctionParameter_class_data_ = + FunctionParameter::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +FunctionParameter::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FunctionParameter_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FunctionParameter_class_data_.tc_table); + return FunctionParameter_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 1, 53, 2> +FunctionParameter::_table_ = { + { + PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + FunctionParameter_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::FunctionParameter>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(FunctionParameter, _impl_.type_), 2>(), + {8, 2, 0, PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.type_)}}, + // optional string name = 2; + {::_pbi::TcParser::FastUS1, + {18, 0, 0, PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.name_)}}, + // optional .tint.core.ir.binary.pb.AttributesFunctionParameter attributes = 3; + {::_pbi::TcParser::FastMtS1, + {26, 1, 0, PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.attributes_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 type = 1; + {PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.type_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional string name = 2; + {PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // optional .tint.core.ir.binary.pb.AttributesFunctionParameter attributes = 3; + {PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.attributes_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::AttributesFunctionParameter>()}, + }}, + {{ + "\50\0\4\0\0\0\0\0" + "tint.core.ir.binary.pb.FunctionParameter" + "name" + }}, +}; +PROTOBUF_NOINLINE void FunctionParameter::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.FunctionParameter) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(_impl_.attributes_ != nullptr); + _impl_.attributes_->Clear(); + } + } + _impl_.type_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL FunctionParameter::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const FunctionParameter& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL FunctionParameter::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const FunctionParameter& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.FunctionParameter) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_type(), target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 2; + if ((cached_has_bits & 0x00000001U) != 0) { + const ::std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "tint.core.ir.binary.pb.FunctionParameter.name"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional .tint.core.ir.binary.pb.AttributesFunctionParameter attributes = 3; + if ((cached_has_bits & 0x00000002U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.attributes_, this_._impl_.attributes_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.FunctionParameter) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t FunctionParameter::ByteSizeLong(const MessageLite& base) { + const FunctionParameter& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t FunctionParameter::ByteSizeLong() const { + const FunctionParameter& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.FunctionParameter) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // optional string name = 2; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .tint.core.ir.binary.pb.AttributesFunctionParameter attributes = 3; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.attributes_); + } + // uint32 type = 1; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void FunctionParameter::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.FunctionParameter) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _this->_internal_set_name(from._internal_name()); + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(from._impl_.attributes_ != nullptr); + if (_this->_impl_.attributes_ == nullptr) { + _this->_impl_.attributes_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.attributes_); + } else { + _this->_impl_.attributes_->MergeFrom(*from._impl_.attributes_); + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void FunctionParameter::CopyFrom(const FunctionParameter& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.FunctionParameter) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void FunctionParameter::InternalSwap(FunctionParameter* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.type_) + + sizeof(FunctionParameter::_impl_.type_) + - PROTOBUF_FIELD_OFFSET(FunctionParameter, _impl_.attributes_)>( + reinterpret_cast(&_impl_.attributes_), + reinterpret_cast(&other->_impl_.attributes_)); +} + +::google::protobuf::Metadata FunctionParameter::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class BlockParameter::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_._has_bits_); +}; + +BlockParameter::BlockParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, BlockParameter_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.BlockParameter) +} +PROTOBUF_NDEBUG_INLINE BlockParameter::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::BlockParameter& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + name_(arena, from.name_) {} + +BlockParameter::BlockParameter( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const BlockParameter& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, BlockParameter_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + BlockParameter* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.type_ = from._impl_.type_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.BlockParameter) +} +PROTOBUF_NDEBUG_INLINE BlockParameter::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + name_(arena) {} + +inline void BlockParameter::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.type_ = {}; +} +BlockParameter::~BlockParameter() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.BlockParameter) + SharedDtor(*this); +} +inline void BlockParameter::SharedDtor(MessageLite& self) { + BlockParameter& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL BlockParameter::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) BlockParameter(arena); +} +constexpr auto BlockParameter::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(BlockParameter), + alignof(BlockParameter)); +} +constexpr auto BlockParameter::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_BlockParameter_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &BlockParameter::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &BlockParameter::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &BlockParameter::ByteSizeLong, + &BlockParameter::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_._cached_size_), + false, + }, + &BlockParameter::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull BlockParameter_class_data_ = + BlockParameter::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +BlockParameter::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&BlockParameter_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(BlockParameter_class_data_.tc_table); + return BlockParameter_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 50, 2> +BlockParameter::_table_ = { + { + PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + BlockParameter_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::BlockParameter>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // optional string name = 2; + {::_pbi::TcParser::FastUS1, + {18, 0, 0, PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_.name_)}}, + // uint32 type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(BlockParameter, _impl_.type_), 1>(), + {8, 1, 0, PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_.type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 type = 1; + {PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_.type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional string name = 2; + {PROTOBUF_FIELD_OFFSET(BlockParameter, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\45\0\4\0\0\0\0\0" + "tint.core.ir.binary.pb.BlockParameter" + "name" + }}, +}; +PROTOBUF_NOINLINE void BlockParameter::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.BlockParameter) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + _impl_.type_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL BlockParameter::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const BlockParameter& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL BlockParameter::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const BlockParameter& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.BlockParameter) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_type(), target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 2; + if ((cached_has_bits & 0x00000001U) != 0) { + const ::std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "tint.core.ir.binary.pb.BlockParameter.name"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.BlockParameter) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t BlockParameter::ByteSizeLong(const MessageLite& base) { + const BlockParameter& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t BlockParameter::ByteSizeLong() const { + const BlockParameter& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.BlockParameter) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // optional string name = 2; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // uint32 type = 1; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void BlockParameter::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.BlockParameter) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _this->_internal_set_name(from._internal_name()); + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void BlockParameter::CopyFrom(const BlockParameter& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.BlockParameter) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void BlockParameter::InternalSwap(BlockParameter* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + swap(_impl_.type_, other->_impl_.type_); +} + +::google::protobuf::Metadata BlockParameter::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class ConstantValue::_Internal { + public: + static constexpr ::int32_t kOneofCaseOffset = + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValue, _impl_._oneof_case_); +}; + +void ConstantValue::set_allocated_scalar(::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE scalar) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (scalar) { + ::google::protobuf::Arena* submessage_arena = scalar->GetArena(); + if (message_arena != submessage_arena) { + scalar = ::google::protobuf::internal::GetOwnedMessage(message_arena, scalar, submessage_arena); + } + set_has_scalar(); + _impl_.kind_.scalar_ = scalar; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.ConstantValue.scalar) +} +void ConstantValue::set_allocated_composite(::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE composite) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (composite) { + ::google::protobuf::Arena* submessage_arena = composite->GetArena(); + if (message_arena != submessage_arena) { + composite = ::google::protobuf::internal::GetOwnedMessage(message_arena, composite, submessage_arena); + } + set_has_composite(); + _impl_.kind_.composite_ = composite; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.ConstantValue.composite) +} +void ConstantValue::set_allocated_splat(::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE splat) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (splat) { + ::google::protobuf::Arena* submessage_arena = splat->GetArena(); + if (message_arena != submessage_arena) { + splat = ::google::protobuf::internal::GetOwnedMessage(message_arena, splat, submessage_arena); + } + set_has_splat(); + _impl_.kind_.splat_ = splat; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.ConstantValue.splat) +} +ConstantValue::ConstantValue(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.ConstantValue) +} +PROTOBUF_NDEBUG_INLINE ConstantValue::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::ConstantValue& from_msg) + : kind_{}, + _cached_size_{0}, + _oneof_case_{from._oneof_case_[0]} {} + +ConstantValue::ConstantValue( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ConstantValue& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ConstantValue* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + switch (kind_case()) { + case KIND_NOT_SET: + break; + case kScalar: + _impl_.kind_.scalar_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.scalar_); + break; + case kComposite: + _impl_.kind_.composite_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.composite_); + break; + case kSplat: + _impl_.kind_.splat_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.splat_); + break; + } + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.ConstantValue) +} +PROTOBUF_NDEBUG_INLINE ConstantValue::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +inline void ConstantValue::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +ConstantValue::~ConstantValue() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.ConstantValue) + SharedDtor(*this); +} +inline void ConstantValue::SharedDtor(MessageLite& self) { + ConstantValue& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + if (this_.has_kind()) { + this_.clear_kind(); + } + this_._impl_.~Impl_(); +} + +void ConstantValue::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:tint.core.ir.binary.pb.ConstantValue) + ::google::protobuf::internal::TSanWrite(&_impl_); + switch (kind_case()) { + case kScalar: { + if (GetArena() == nullptr) { + delete _impl_.kind_.scalar_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.scalar_); + } + break; + } + case kComposite: { + if (GetArena() == nullptr) { + delete _impl_.kind_.composite_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.composite_); + } + break; + } + case kSplat: { + if (GetArena() == nullptr) { + delete _impl_.kind_.splat_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.splat_); + } + break; + } + case KIND_NOT_SET: { + break; + } + } + _impl_._oneof_case_[0] = KIND_NOT_SET; +} + + +inline void* PROTOBUF_NONNULL ConstantValue::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ConstantValue(arena); +} +constexpr auto ConstantValue::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ConstantValue), + alignof(ConstantValue)); +} +constexpr auto ConstantValue::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ConstantValue_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &ConstantValue::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ConstantValue::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ConstantValue::ByteSizeLong, + &ConstantValue::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ConstantValue, _impl_._cached_size_), + false, + }, + &ConstantValue::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ConstantValue_class_data_ = + ConstantValue::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ConstantValue::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ConstantValue_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ConstantValue_class_data_.tc_table); + return ConstantValue_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 3, 3, 0, 2> +ConstantValue::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 3, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 3, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + ConstantValue_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValue>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.ConstantValueScalar scalar = 1; + {PROTOBUF_FIELD_OFFSET(ConstantValue, _impl_.kind_.scalar_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.ConstantValueComposite composite = 2; + {PROTOBUF_FIELD_OFFSET(ConstantValue, _impl_.kind_.composite_), _Internal::kOneofCaseOffset + 0, 1, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.ConstantValueSplat splat = 3; + {PROTOBUF_FIELD_OFFSET(ConstantValue, _impl_.kind_.splat_), _Internal::kOneofCaseOffset + 0, 2, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValueScalar>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValueComposite>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValueSplat>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void ConstantValue::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.ConstantValue) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + clear_kind(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ConstantValue::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ConstantValue& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ConstantValue::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ConstantValue& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.ConstantValue) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + switch (this_.kind_case()) { + case kScalar: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.kind_.scalar_, this_._impl_.kind_.scalar_->GetCachedSize(), target, + stream); + break; + } + case kComposite: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.kind_.composite_, this_._impl_.kind_.composite_->GetCachedSize(), target, + stream); + break; + } + case kSplat: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.kind_.splat_, this_._impl_.kind_.splat_->GetCachedSize(), target, + stream); + break; + } + default: + break; + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.ConstantValue) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ConstantValue::ByteSizeLong(const MessageLite& base) { + const ConstantValue& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ConstantValue::ByteSizeLong() const { + const ConstantValue& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.ConstantValue) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + switch (this_.kind_case()) { + // .tint.core.ir.binary.pb.ConstantValueScalar scalar = 1; + case kScalar: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.scalar_); + break; + } + // .tint.core.ir.binary.pb.ConstantValueComposite composite = 2; + case kComposite: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.composite_); + break; + } + // .tint.core.ir.binary.pb.ConstantValueSplat splat = 3; + case kSplat: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.splat_); + break; + } + case KIND_NOT_SET: { + break; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ConstantValue::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.ConstantValue) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (const uint32_t oneof_from_case = from._impl_._oneof_case_[0]) { + const uint32_t oneof_to_case = _this->_impl_._oneof_case_[0]; + const bool oneof_needs_init = oneof_to_case != oneof_from_case; + if (oneof_needs_init) { + if (oneof_to_case != 0) { + _this->clear_kind(); + } + _this->_impl_._oneof_case_[0] = oneof_from_case; + } + + switch (oneof_from_case) { + case kScalar: { + if (oneof_needs_init) { + _this->_impl_.kind_.scalar_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.scalar_); + } else { + _this->_impl_.kind_.scalar_->MergeFrom(*from._impl_.kind_.scalar_); + } + break; + } + case kComposite: { + if (oneof_needs_init) { + _this->_impl_.kind_.composite_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.composite_); + } else { + _this->_impl_.kind_.composite_->MergeFrom(*from._impl_.kind_.composite_); + } + break; + } + case kSplat: { + if (oneof_needs_init) { + _this->_impl_.kind_.splat_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.splat_); + } else { + _this->_impl_.kind_.splat_->MergeFrom(*from._impl_.kind_.splat_); + } + break; + } + case KIND_NOT_SET: + break; + } + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void ConstantValue::CopyFrom(const ConstantValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.ConstantValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ConstantValue::InternalSwap(ConstantValue* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.kind_, other->_impl_.kind_); + swap(_impl_._oneof_case_[0], other->_impl_._oneof_case_[0]); +} + +::google::protobuf::Metadata ConstantValue::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class ConstantValueScalar::_Internal { + public: + static constexpr ::int32_t kOneofCaseOffset = + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::ConstantValueScalar, _impl_._oneof_case_); +}; + +ConstantValueScalar::ConstantValueScalar(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValueScalar_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.ConstantValueScalar) +} +ConstantValueScalar::ConstantValueScalar( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ConstantValueScalar& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValueScalar_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE ConstantValueScalar::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +inline void ConstantValueScalar::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +ConstantValueScalar::~ConstantValueScalar() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.ConstantValueScalar) + SharedDtor(*this); +} +inline void ConstantValueScalar::SharedDtor(MessageLite& self) { + ConstantValueScalar& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + if (this_.has_kind()) { + this_.clear_kind(); + } + this_._impl_.~Impl_(); +} + +void ConstantValueScalar::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:tint.core.ir.binary.pb.ConstantValueScalar) + ::google::protobuf::internal::TSanWrite(&_impl_); + switch (kind_case()) { + case kBool: { + // No need to clear + break; + } + case kI32: { + // No need to clear + break; + } + case kU32: { + // No need to clear + break; + } + case kF32: { + // No need to clear + break; + } + case kF16: { + // No need to clear + break; + } + case KIND_NOT_SET: { + break; + } + } + _impl_._oneof_case_[0] = KIND_NOT_SET; +} + + +inline void* PROTOBUF_NONNULL ConstantValueScalar::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ConstantValueScalar(arena); +} +constexpr auto ConstantValueScalar::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ConstantValueScalar), + alignof(ConstantValueScalar)); +} +constexpr auto ConstantValueScalar::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ConstantValueScalar_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &ConstantValueScalar::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ConstantValueScalar::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ConstantValueScalar::ByteSizeLong, + &ConstantValueScalar::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ConstantValueScalar, _impl_._cached_size_), + false, + }, + &ConstantValueScalar::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ConstantValueScalar_class_data_ = + ConstantValueScalar::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ConstantValueScalar::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ConstantValueScalar_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ConstantValueScalar_class_data_.tc_table); + return ConstantValueScalar_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 5, 0, 0, 2> +ConstantValueScalar::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 5, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967264, // skipmap + offsetof(decltype(_table_), field_entries), + 5, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + ConstantValueScalar_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValueScalar>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // bool bool = 1; + {PROTOBUF_FIELD_OFFSET(ConstantValueScalar, _impl_.kind_.bool__), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kBool)}, + // int32 i32 = 2; + {PROTOBUF_FIELD_OFFSET(ConstantValueScalar, _impl_.kind_.i32_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kInt32)}, + // uint32 u32 = 3; + {PROTOBUF_FIELD_OFFSET(ConstantValueScalar, _impl_.kind_.u32_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kUInt32)}, + // float f32 = 4; + {PROTOBUF_FIELD_OFFSET(ConstantValueScalar, _impl_.kind_.f32_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kFloat)}, + // float f16 = 5; + {PROTOBUF_FIELD_OFFSET(ConstantValueScalar, _impl_.kind_.f16_), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kFloat)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void ConstantValueScalar::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.ConstantValueScalar) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + clear_kind(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ConstantValueScalar::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ConstantValueScalar& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ConstantValueScalar::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ConstantValueScalar& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.ConstantValueScalar) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + switch (this_.kind_case()) { + case kBool: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 1, this_._internal_bool_(), target); + break; + } + case kI32: { + target = + ::google::protobuf::internal::WireFormatLite::WriteInt32ToArrayWithField<2>( + stream, this_._internal_i32(), target); + break; + } + case kU32: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_u32(), target); + break; + } + case kF32: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteFloatToArray( + 4, this_._internal_f32(), target); + break; + } + case kF16: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteFloatToArray( + 5, this_._internal_f16(), target); + break; + } + default: + break; + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.ConstantValueScalar) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ConstantValueScalar::ByteSizeLong(const MessageLite& base) { + const ConstantValueScalar& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ConstantValueScalar::ByteSizeLong() const { + const ConstantValueScalar& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.ConstantValueScalar) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + switch (this_.kind_case()) { + // bool bool = 1; + case kBool: { + total_size += 2; + break; + } + // int32 i32 = 2; + case kI32: { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_i32()); + break; + } + // uint32 u32 = 3; + case kU32: { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_u32()); + break; + } + // float f32 = 4; + case kF32: { + total_size += 5; + break; + } + // float f16 = 5; + case kF16: { + total_size += 5; + break; + } + case KIND_NOT_SET: { + break; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ConstantValueScalar::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.ConstantValueScalar) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (const uint32_t oneof_from_case = from._impl_._oneof_case_[0]) { + const uint32_t oneof_to_case = _this->_impl_._oneof_case_[0]; + const bool oneof_needs_init = oneof_to_case != oneof_from_case; + if (oneof_needs_init) { + if (oneof_to_case != 0) { + _this->clear_kind(); + } + _this->_impl_._oneof_case_[0] = oneof_from_case; + } + + switch (oneof_from_case) { + case kBool: { + _this->_impl_.kind_.bool__ = from._impl_.kind_.bool__; + break; + } + case kI32: { + _this->_impl_.kind_.i32_ = from._impl_.kind_.i32_; + break; + } + case kU32: { + _this->_impl_.kind_.u32_ = from._impl_.kind_.u32_; + break; + } + case kF32: { + _this->_impl_.kind_.f32_ = from._impl_.kind_.f32_; + break; + } + case kF16: { + _this->_impl_.kind_.f16_ = from._impl_.kind_.f16_; + break; + } + case KIND_NOT_SET: + break; + } + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void ConstantValueScalar::CopyFrom(const ConstantValueScalar& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.ConstantValueScalar) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ConstantValueScalar::InternalSwap(ConstantValueScalar* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.kind_, other->_impl_.kind_); + swap(_impl_._oneof_case_[0], other->_impl_._oneof_case_[0]); +} + +::google::protobuf::Metadata ConstantValueScalar::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class ConstantValueComposite::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_._has_bits_); +}; + +ConstantValueComposite::ConstantValueComposite(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValueComposite_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.ConstantValueComposite) +} +PROTOBUF_NDEBUG_INLINE ConstantValueComposite::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::ConstantValueComposite& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + elements_{visibility, arena, from.elements_}, + _elements_cached_byte_size_{0} {} + +ConstantValueComposite::ConstantValueComposite( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ConstantValueComposite& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValueComposite_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ConstantValueComposite* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.type_ = from._impl_.type_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.ConstantValueComposite) +} +PROTOBUF_NDEBUG_INLINE ConstantValueComposite::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + elements_{visibility, arena}, + _elements_cached_byte_size_{0} {} + +inline void ConstantValueComposite::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.type_ = {}; +} +ConstantValueComposite::~ConstantValueComposite() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.ConstantValueComposite) + SharedDtor(*this); +} +inline void ConstantValueComposite::SharedDtor(MessageLite& self) { + ConstantValueComposite& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL ConstantValueComposite::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ConstantValueComposite(arena); +} +constexpr auto ConstantValueComposite::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_.elements_) + + decltype(ConstantValueComposite::_impl_.elements_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(ConstantValueComposite), alignof(ConstantValueComposite), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&ConstantValueComposite::PlacementNew_, + sizeof(ConstantValueComposite), + alignof(ConstantValueComposite)); + } +} +constexpr auto ConstantValueComposite::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ConstantValueComposite_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &ConstantValueComposite::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ConstantValueComposite::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ConstantValueComposite::ByteSizeLong, + &ConstantValueComposite::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_._cached_size_), + false, + }, + &ConstantValueComposite::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ConstantValueComposite_class_data_ = + ConstantValueComposite::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ConstantValueComposite::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ConstantValueComposite_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ConstantValueComposite_class_data_.tc_table); + return ConstantValueComposite_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +ConstantValueComposite::_table_ = { + { + PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + ConstantValueComposite_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValueComposite>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated uint32 elements = 2; + {::_pbi::TcParser::FastV32P1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_.elements_)}}, + // uint32 type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ConstantValueComposite, _impl_.type_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_.type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 type = 1; + {PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_.type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // repeated uint32 elements = 2; + {PROTOBUF_FIELD_OFFSET(ConstantValueComposite, _impl_.elements_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void ConstantValueComposite::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.ConstantValueComposite) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.elements_.Clear(); + _impl_.type_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ConstantValueComposite::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ConstantValueComposite& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ConstantValueComposite::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ConstantValueComposite& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.ConstantValueComposite) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_type(), target); + } + } + + // repeated uint32 elements = 2; + { + int byte_size = this_._impl_._elements_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 2, this_._internal_elements(), byte_size, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.ConstantValueComposite) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ConstantValueComposite::ByteSizeLong(const MessageLite& base) { + const ConstantValueComposite& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ConstantValueComposite::ByteSizeLong() const { + const ConstantValueComposite& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.ConstantValueComposite) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 elements = 2; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_elements(), 1, + this_._impl_._elements_cached_byte_size_); + } + } + { + // uint32 type = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ConstantValueComposite::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.ConstantValueComposite) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_elements()->MergeFrom(from._internal_elements()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void ConstantValueComposite::CopyFrom(const ConstantValueComposite& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.ConstantValueComposite) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ConstantValueComposite::InternalSwap(ConstantValueComposite* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.elements_.InternalSwap(&other->_impl_.elements_); + swap(_impl_.type_, other->_impl_.type_); +} + +::google::protobuf::Metadata ConstantValueComposite::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class ConstantValueSplat::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_._has_bits_); +}; + +ConstantValueSplat::ConstantValueSplat(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValueSplat_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.ConstantValueSplat) +} +ConstantValueSplat::ConstantValueSplat( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ConstantValueSplat& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ConstantValueSplat_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE ConstantValueSplat::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void ConstantValueSplat::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, type_), + 0, + offsetof(Impl_, count_) - + offsetof(Impl_, type_) + + sizeof(Impl_::count_)); +} +ConstantValueSplat::~ConstantValueSplat() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.ConstantValueSplat) + SharedDtor(*this); +} +inline void ConstantValueSplat::SharedDtor(MessageLite& self) { + ConstantValueSplat& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL ConstantValueSplat::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ConstantValueSplat(arena); +} +constexpr auto ConstantValueSplat::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ConstantValueSplat), + alignof(ConstantValueSplat)); +} +constexpr auto ConstantValueSplat::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ConstantValueSplat_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &ConstantValueSplat::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ConstantValueSplat::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ConstantValueSplat::ByteSizeLong, + &ConstantValueSplat::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_._cached_size_), + false, + }, + &ConstantValueSplat::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ConstantValueSplat_class_data_ = + ConstantValueSplat::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ConstantValueSplat::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ConstantValueSplat_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ConstantValueSplat_class_data_.tc_table); + return ConstantValueSplat_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +ConstantValueSplat::_table_ = { + { + PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + ConstantValueSplat_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::ConstantValueSplat>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ConstantValueSplat, _impl_.type_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.type_)}}, + // uint32 elements = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ConstantValueSplat, _impl_.elements_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.elements_)}}, + // uint32 count = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ConstantValueSplat, _impl_.count_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.count_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 type = 1; + {PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 elements = 2; + {PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.elements_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 count = 3; + {PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.count_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void ConstantValueSplat::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.ConstantValueSplat) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.type_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.count_) - + reinterpret_cast(&_impl_.type_)) + sizeof(_impl_.count_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ConstantValueSplat::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ConstantValueSplat& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ConstantValueSplat::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ConstantValueSplat& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.ConstantValueSplat) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_type(), target); + } + } + + // uint32 elements = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_elements() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_elements(), target); + } + } + + // uint32 count = 3; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_count() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_count(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.ConstantValueSplat) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ConstantValueSplat::ByteSizeLong(const MessageLite& base) { + const ConstantValueSplat& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ConstantValueSplat::ByteSizeLong() const { + const ConstantValueSplat& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.ConstantValueSplat) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // uint32 type = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_type()); + } + } + // uint32 elements = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_elements() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_elements()); + } + } + // uint32 count = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_count() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_count()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ConstantValueSplat::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.ConstantValueSplat) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_elements() != 0) { + _this->_impl_.elements_ = from._impl_.elements_; + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_count() != 0) { + _this->_impl_.count_ = from._impl_.count_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void ConstantValueSplat::CopyFrom(const ConstantValueSplat& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.ConstantValueSplat) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ConstantValueSplat::InternalSwap(ConstantValueSplat* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.count_) + + sizeof(ConstantValueSplat::_impl_.count_) + - PROTOBUF_FIELD_OFFSET(ConstantValueSplat, _impl_.type_)>( + reinterpret_cast(&_impl_.type_), + reinterpret_cast(&other->_impl_.type_)); +} + +::google::protobuf::Metadata ConstantValueSplat::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class Function::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Function, _impl_._has_bits_); +}; + +Function::Function(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Function_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Function) +} +PROTOBUF_NDEBUG_INLINE Function::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::Function& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + parameters_{visibility, arena, from.parameters_}, + _parameters_cached_byte_size_{0}, + name_(arena, from.name_) {} + +Function::Function( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Function& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Function_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Function* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.workgroup_size_ = ((cached_has_bits & 0x00000002U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.workgroup_size_) + : nullptr; + _impl_.return_interpolation_ = ((cached_has_bits & 0x00000004U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.return_interpolation_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, return_type_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, return_type_), + offsetof(Impl_, subgroup_size_) - + offsetof(Impl_, return_type_) + + sizeof(Impl_::subgroup_size_)); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.Function) +} +PROTOBUF_NDEBUG_INLINE Function::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + parameters_{visibility, arena}, + _parameters_cached_byte_size_{0}, + name_(arena) {} + +inline void Function::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, workgroup_size_), + 0, + offsetof(Impl_, subgroup_size_) - + offsetof(Impl_, workgroup_size_) + + sizeof(Impl_::subgroup_size_)); +} +Function::~Function() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Function) + SharedDtor(*this); +} +inline void Function::SharedDtor(MessageLite& self) { + Function& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.workgroup_size_; + delete this_._impl_.return_interpolation_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL Function::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Function(arena); +} +constexpr auto Function::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Function, _impl_.parameters_) + + decltype(Function::_impl_.parameters_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Function), alignof(Function), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Function::PlacementNew_, + sizeof(Function), + alignof(Function)); + } +} +constexpr auto Function::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Function_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Function::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Function::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Function::ByteSizeLong, + &Function::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Function, _impl_._cached_size_), + false, + }, + &Function::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Function_class_data_ = + Function::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Function::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Function_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Function_class_data_.tc_table); + return Function_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<4, 11, 2, 52, 2> +Function::_table_ = { + { + PROTOBUF_FIELD_OFFSET(Function, _impl_._has_bits_), + 0, // no _extensions_ + 11, 120, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294965248, // skipmap + offsetof(decltype(_table_), field_entries), + 11, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Function_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Function>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 return_type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Function, _impl_.return_type_), 3>(), + {8, 3, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.return_type_)}}, + // uint32 block = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Function, _impl_.block_), 4>(), + {16, 4, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.block_)}}, + // optional string name = 3; + {::_pbi::TcParser::FastUS1, + {26, 0, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.name_)}}, + // optional .tint.core.ir.binary.pb.PipelineStage pipeline_stage = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Function, _impl_.pipeline_stage_), 5>(), + {32, 5, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.pipeline_stage_)}}, + // optional .tint.core.ir.binary.pb.WorkgroupSize workgroup_size = 5; + {::_pbi::TcParser::FastMtS1, + {42, 1, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.workgroup_size_)}}, + // repeated uint32 parameters = 6; + {::_pbi::TcParser::FastV32P1, + {50, 63, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.parameters_)}}, + // optional uint32 return_location = 7; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Function, _impl_.return_location_), 6>(), + {56, 6, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.return_location_)}}, + // optional .tint.core.ir.binary.pb.Interpolation return_interpolation = 8; + {::_pbi::TcParser::FastMtS1, + {66, 2, 1, PROTOBUF_FIELD_OFFSET(Function, _impl_.return_interpolation_)}}, + // optional .tint.core.ir.binary.pb.BuiltinValue return_builtin = 9; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Function, _impl_.return_builtin_), 7>(), + {72, 7, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.return_builtin_)}}, + // bool return_invariant = 10; + {::_pbi::TcParser::SingularVarintNoZag1(), + {80, 8, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.return_invariant_)}}, + // optional uint32 subgroup_size = 11; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Function, _impl_.subgroup_size_), 9>(), + {88, 9, 0, PROTOBUF_FIELD_OFFSET(Function, _impl_.subgroup_size_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 return_type = 1; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.return_type_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 block = 2; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.block_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional string name = 3; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // optional .tint.core.ir.binary.pb.PipelineStage pipeline_stage = 4; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.pipeline_stage_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // optional .tint.core.ir.binary.pb.WorkgroupSize workgroup_size = 5; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.workgroup_size_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated uint32 parameters = 6; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.parameters_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + // optional uint32 return_location = 7; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.return_location_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional .tint.core.ir.binary.pb.Interpolation return_interpolation = 8; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.return_interpolation_), _Internal::kHasBitsOffset + 2, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // optional .tint.core.ir.binary.pb.BuiltinValue return_builtin = 9; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.return_builtin_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // bool return_invariant = 10; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.return_invariant_), _Internal::kHasBitsOffset + 8, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional uint32 subgroup_size = 11; + {PROTOBUF_FIELD_OFFSET(Function, _impl_.subgroup_size_), _Internal::kHasBitsOffset + 9, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::WorkgroupSize>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Interpolation>()}, + }}, + {{ + "\37\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0" + "tint.core.ir.binary.pb.Function" + "name" + }}, +}; +PROTOBUF_NOINLINE void Function::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Function) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.parameters_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(_impl_.workgroup_size_ != nullptr); + _impl_.workgroup_size_->Clear(); + } + if ((cached_has_bits & 0x00000004U) != 0) { + ABSL_DCHECK(_impl_.return_interpolation_ != nullptr); + _impl_.return_interpolation_->Clear(); + } + } + if ((cached_has_bits & 0x000000f8U) != 0) { + ::memset(&_impl_.return_type_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.return_builtin_) - + reinterpret_cast(&_impl_.return_type_)) + sizeof(_impl_.return_builtin_)); + } + if ((cached_has_bits & 0x00000300U) != 0) { + ::memset(&_impl_.return_invariant_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.subgroup_size_) - + reinterpret_cast(&_impl_.return_invariant_)) + sizeof(_impl_.subgroup_size_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Function::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Function& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Function::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Function& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Function) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 return_type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000008U) != 0) { + if (this_._internal_return_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_return_type(), target); + } + } + + // uint32 block = 2; + if ((this_._impl_._has_bits_[0] & 0x00000010U) != 0) { + if (this_._internal_block() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_block(), target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 3; + if ((cached_has_bits & 0x00000001U) != 0) { + const ::std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "tint.core.ir.binary.pb.Function.name"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // optional .tint.core.ir.binary.pb.PipelineStage pipeline_stage = 4; + if ((cached_has_bits & 0x00000020U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_pipeline_stage(), target); + } + + // optional .tint.core.ir.binary.pb.WorkgroupSize workgroup_size = 5; + if ((cached_has_bits & 0x00000002U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.workgroup_size_, this_._impl_.workgroup_size_->GetCachedSize(), target, + stream); + } + + // repeated uint32 parameters = 6; + { + int byte_size = this_._impl_._parameters_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 6, this_._internal_parameters(), byte_size, target); + } + } + + // optional uint32 return_location = 7; + if ((cached_has_bits & 0x00000040U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 7, this_._internal_return_location(), target); + } + + // optional .tint.core.ir.binary.pb.Interpolation return_interpolation = 8; + if ((cached_has_bits & 0x00000004U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.return_interpolation_, this_._impl_.return_interpolation_->GetCachedSize(), target, + stream); + } + + // optional .tint.core.ir.binary.pb.BuiltinValue return_builtin = 9; + if ((cached_has_bits & 0x00000080U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 9, this_._internal_return_builtin(), target); + } + + // bool return_invariant = 10; + if ((cached_has_bits & 0x00000100U) != 0) { + if (this_._internal_return_invariant() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 10, this_._internal_return_invariant(), target); + } + } + + // optional uint32 subgroup_size = 11; + if ((cached_has_bits & 0x00000200U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 11, this_._internal_subgroup_size(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Function) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Function::ByteSizeLong(const MessageLite& base) { + const Function& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Function::ByteSizeLong() const { + const Function& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Function) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 parameters = 6; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_parameters(), 1, + this_._impl_._parameters_cached_byte_size_); + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x000000ffU) != 0) { + // optional string name = 3; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .tint.core.ir.binary.pb.WorkgroupSize workgroup_size = 5; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.workgroup_size_); + } + // optional .tint.core.ir.binary.pb.Interpolation return_interpolation = 8; + if ((cached_has_bits & 0x00000004U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.return_interpolation_); + } + // uint32 return_type = 1; + if ((cached_has_bits & 0x00000008U) != 0) { + if (this_._internal_return_type() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_return_type()); + } + } + // uint32 block = 2; + if ((cached_has_bits & 0x00000010U) != 0) { + if (this_._internal_block() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_block()); + } + } + // optional .tint.core.ir.binary.pb.PipelineStage pipeline_stage = 4; + if ((cached_has_bits & 0x00000020U) != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_pipeline_stage()); + } + // optional uint32 return_location = 7; + if ((cached_has_bits & 0x00000040U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_return_location()); + } + // optional .tint.core.ir.binary.pb.BuiltinValue return_builtin = 9; + if ((cached_has_bits & 0x00000080U) != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_return_builtin()); + } + } + if ((cached_has_bits & 0x00000300U) != 0) { + // bool return_invariant = 10; + if ((cached_has_bits & 0x00000100U) != 0) { + if (this_._internal_return_invariant() != 0) { + total_size += 2; + } + } + // optional uint32 subgroup_size = 11; + if ((cached_has_bits & 0x00000200U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_subgroup_size()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Function::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Function) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_parameters()->MergeFrom(from._internal_parameters()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x000000ffU) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _this->_internal_set_name(from._internal_name()); + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(from._impl_.workgroup_size_ != nullptr); + if (_this->_impl_.workgroup_size_ == nullptr) { + _this->_impl_.workgroup_size_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.workgroup_size_); + } else { + _this->_impl_.workgroup_size_->MergeFrom(*from._impl_.workgroup_size_); + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + ABSL_DCHECK(from._impl_.return_interpolation_ != nullptr); + if (_this->_impl_.return_interpolation_ == nullptr) { + _this->_impl_.return_interpolation_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.return_interpolation_); + } else { + _this->_impl_.return_interpolation_->MergeFrom(*from._impl_.return_interpolation_); + } + } + if ((cached_has_bits & 0x00000008U) != 0) { + if (from._internal_return_type() != 0) { + _this->_impl_.return_type_ = from._impl_.return_type_; + } + } + if ((cached_has_bits & 0x00000010U) != 0) { + if (from._internal_block() != 0) { + _this->_impl_.block_ = from._impl_.block_; + } + } + if ((cached_has_bits & 0x00000020U) != 0) { + _this->_impl_.pipeline_stage_ = from._impl_.pipeline_stage_; + } + if ((cached_has_bits & 0x00000040U) != 0) { + _this->_impl_.return_location_ = from._impl_.return_location_; + } + if ((cached_has_bits & 0x00000080U) != 0) { + _this->_impl_.return_builtin_ = from._impl_.return_builtin_; + } + } + if ((cached_has_bits & 0x00000300U) != 0) { + if ((cached_has_bits & 0x00000100U) != 0) { + if (from._internal_return_invariant() != 0) { + _this->_impl_.return_invariant_ = from._impl_.return_invariant_; + } + } + if ((cached_has_bits & 0x00000200U) != 0) { + _this->_impl_.subgroup_size_ = from._impl_.subgroup_size_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Function::CopyFrom(const Function& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Function) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Function::InternalSwap(Function* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.parameters_.InternalSwap(&other->_impl_.parameters_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Function, _impl_.subgroup_size_) + + sizeof(Function::_impl_.subgroup_size_) + - PROTOBUF_FIELD_OFFSET(Function, _impl_.workgroup_size_)>( + reinterpret_cast(&_impl_.workgroup_size_), + reinterpret_cast(&other->_impl_.workgroup_size_)); +} + +::google::protobuf::Metadata Function::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class WorkgroupSize::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_._has_bits_); +}; + +WorkgroupSize::WorkgroupSize(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, WorkgroupSize_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.WorkgroupSize) +} +WorkgroupSize::WorkgroupSize( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const WorkgroupSize& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, WorkgroupSize_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE WorkgroupSize::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void WorkgroupSize::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, x_), + 0, + offsetof(Impl_, z_) - + offsetof(Impl_, x_) + + sizeof(Impl_::z_)); +} +WorkgroupSize::~WorkgroupSize() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.WorkgroupSize) + SharedDtor(*this); +} +inline void WorkgroupSize::SharedDtor(MessageLite& self) { + WorkgroupSize& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL WorkgroupSize::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) WorkgroupSize(arena); +} +constexpr auto WorkgroupSize::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(WorkgroupSize), + alignof(WorkgroupSize)); +} +constexpr auto WorkgroupSize::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_WorkgroupSize_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &WorkgroupSize::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &WorkgroupSize::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &WorkgroupSize::ByteSizeLong, + &WorkgroupSize::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_._cached_size_), + false, + }, + &WorkgroupSize::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull WorkgroupSize_class_data_ = + WorkgroupSize::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +WorkgroupSize::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&WorkgroupSize_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(WorkgroupSize_class_data_.tc_table); + return WorkgroupSize_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +WorkgroupSize::_table_ = { + { + PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + WorkgroupSize_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::WorkgroupSize>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 x = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(WorkgroupSize, _impl_.x_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.x_)}}, + // uint32 y = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(WorkgroupSize, _impl_.y_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.y_)}}, + // uint32 z = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(WorkgroupSize, _impl_.z_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.z_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 x = 1; + {PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.x_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 y = 2; + {PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.y_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 z = 3; + {PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.z_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void WorkgroupSize::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.WorkgroupSize) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.x_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.z_) - + reinterpret_cast(&_impl_.x_)) + sizeof(_impl_.z_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL WorkgroupSize::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const WorkgroupSize& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL WorkgroupSize::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const WorkgroupSize& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.WorkgroupSize) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 x = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_x() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_x(), target); + } + } + + // uint32 y = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_y() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_y(), target); + } + } + + // uint32 z = 3; + if ((this_._impl_._has_bits_[0] & 0x00000004U) != 0) { + if (this_._internal_z() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_z(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.WorkgroupSize) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t WorkgroupSize::ByteSizeLong(const MessageLite& base) { + const WorkgroupSize& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t WorkgroupSize::ByteSizeLong() const { + const WorkgroupSize& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.WorkgroupSize) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // uint32 x = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_x() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_x()); + } + } + // uint32 y = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_y() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_y()); + } + } + // uint32 z = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + if (this_._internal_z() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_z()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void WorkgroupSize::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.WorkgroupSize) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_x() != 0) { + _this->_impl_.x_ = from._impl_.x_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_y() != 0) { + _this->_impl_.y_ = from._impl_.y_; + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + if (from._internal_z() != 0) { + _this->_impl_.z_ = from._impl_.z_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void WorkgroupSize::CopyFrom(const WorkgroupSize& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.WorkgroupSize) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void WorkgroupSize::InternalSwap(WorkgroupSize* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.z_) + + sizeof(WorkgroupSize::_impl_.z_) + - PROTOBUF_FIELD_OFFSET(WorkgroupSize, _impl_.x_)>( + reinterpret_cast(&_impl_.x_), + reinterpret_cast(&other->_impl_.x_)); +} + +::google::protobuf::Metadata WorkgroupSize::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class Block::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Block, _impl_._has_bits_); +}; + +Block::Block(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Block_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Block) +} +PROTOBUF_NDEBUG_INLINE Block::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::Block& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + parameters_{visibility, arena, from.parameters_}, + _parameters_cached_byte_size_{0}, + instructions_{visibility, arena, from.instructions_} {} + +Block::Block( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Block& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Block_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Block* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.is_multi_in_ = from._impl_.is_multi_in_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.Block) +} +PROTOBUF_NDEBUG_INLINE Block::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + parameters_{visibility, arena}, + _parameters_cached_byte_size_{0}, + instructions_{visibility, arena} {} + +inline void Block::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.is_multi_in_ = {}; +} +Block::~Block() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Block) + SharedDtor(*this); +} +inline void Block::SharedDtor(MessageLite& self) { + Block& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL Block::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Block(arena); +} +constexpr auto Block::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Block, _impl_.parameters_) + + decltype(Block::_impl_.parameters_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Block, _impl_.instructions_) + + decltype(Block::_impl_.instructions_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(Block), alignof(Block), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Block::PlacementNew_, + sizeof(Block), + alignof(Block)); + } +} +constexpr auto Block::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Block_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Block::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Block::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Block::ByteSizeLong, + &Block::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Block, _impl_._cached_size_), + false, + }, + &Block::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Block_class_data_ = + Block::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Block::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Block_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Block_class_data_.tc_table); + return Block_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 1, 0, 2> +Block::_table_ = { + { + PROTOBUF_FIELD_OFFSET(Block, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Block_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Block>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // repeated uint32 parameters = 1; + {::_pbi::TcParser::FastV32P1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(Block, _impl_.parameters_)}}, + // repeated .tint.core.ir.binary.pb.Instruction instructions = 2; + {::_pbi::TcParser::FastMtR1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(Block, _impl_.instructions_)}}, + // bool is_multi_in = 3; + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 0, 0, PROTOBUF_FIELD_OFFSET(Block, _impl_.is_multi_in_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated uint32 parameters = 1; + {PROTOBUF_FIELD_OFFSET(Block, _impl_.parameters_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + // repeated .tint.core.ir.binary.pb.Instruction instructions = 2; + {PROTOBUF_FIELD_OFFSET(Block, _impl_.instructions_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool is_multi_in = 3; + {PROTOBUF_FIELD_OFFSET(Block, _impl_.is_multi_in_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Instruction>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void Block::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Block) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.parameters_.Clear(); + _impl_.instructions_.Clear(); + _impl_.is_multi_in_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Block::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Block& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Block::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Block& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Block) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated uint32 parameters = 1; + { + int byte_size = this_._impl_._parameters_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 1, this_._internal_parameters(), byte_size, target); + } + } + + // repeated .tint.core.ir.binary.pb.Instruction instructions = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_instructions_size()); + i < n; i++) { + const auto& repfield = this_._internal_instructions().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // bool is_multi_in = 3; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_is_multi_in() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_is_multi_in(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Block) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Block::ByteSizeLong(const MessageLite& base) { + const Block& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Block::ByteSizeLong() const { + const Block& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Block) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 parameters = 1; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_parameters(), 1, + this_._impl_._parameters_cached_byte_size_); + } + // repeated .tint.core.ir.binary.pb.Instruction instructions = 2; + { + total_size += 1UL * this_._internal_instructions_size(); + for (const auto& msg : this_._internal_instructions()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + { + // bool is_multi_in = 3; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_is_multi_in() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Block::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Block) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_parameters()->MergeFrom(from._internal_parameters()); + _this->_internal_mutable_instructions()->MergeFrom( + from._internal_instructions()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_is_multi_in() != 0) { + _this->_impl_.is_multi_in_ = from._impl_.is_multi_in_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Block::CopyFrom(const Block& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Block) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Block::InternalSwap(Block* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.parameters_.InternalSwap(&other->_impl_.parameters_); + _impl_.instructions_.InternalSwap(&other->_impl_.instructions_); + swap(_impl_.is_multi_in_, other->_impl_.is_multi_in_); +} + +::google::protobuf::Metadata Block::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class Instruction::_Internal { + public: + static constexpr ::int32_t kOneofCaseOffset = + PROTOBUF_FIELD_OFFSET(::tint::core::ir::binary::pb::Instruction, _impl_._oneof_case_); +}; + +void Instruction::set_allocated_return_(::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE return_) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (return_) { + ::google::protobuf::Arena* submessage_arena = return_->GetArena(); + if (message_arena != submessage_arena) { + return_ = ::google::protobuf::internal::GetOwnedMessage(message_arena, return_, submessage_arena); + } + set_has_return_(); + _impl_.kind_.return__ = return_; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.return) +} +void Instruction::set_allocated_unary(::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE unary) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (unary) { + ::google::protobuf::Arena* submessage_arena = unary->GetArena(); + if (message_arena != submessage_arena) { + unary = ::google::protobuf::internal::GetOwnedMessage(message_arena, unary, submessage_arena); + } + set_has_unary(); + _impl_.kind_.unary_ = unary; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.unary) +} +void Instruction::set_allocated_binary(::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE binary) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (binary) { + ::google::protobuf::Arena* submessage_arena = binary->GetArena(); + if (message_arena != submessage_arena) { + binary = ::google::protobuf::internal::GetOwnedMessage(message_arena, binary, submessage_arena); + } + set_has_binary(); + _impl_.kind_.binary_ = binary; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.binary) +} +void Instruction::set_allocated_discard(::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE discard) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (discard) { + ::google::protobuf::Arena* submessage_arena = discard->GetArena(); + if (message_arena != submessage_arena) { + discard = ::google::protobuf::internal::GetOwnedMessage(message_arena, discard, submessage_arena); + } + set_has_discard(); + _impl_.kind_.discard_ = discard; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.discard) +} +void Instruction::set_allocated_let(::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE let) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (let) { + ::google::protobuf::Arena* submessage_arena = let->GetArena(); + if (message_arena != submessage_arena) { + let = ::google::protobuf::internal::GetOwnedMessage(message_arena, let, submessage_arena); + } + set_has_let(); + _impl_.kind_.let_ = let; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.let) +} +void Instruction::set_allocated_var(::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE var) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (var) { + ::google::protobuf::Arena* submessage_arena = var->GetArena(); + if (message_arena != submessage_arena) { + var = ::google::protobuf::internal::GetOwnedMessage(message_arena, var, submessage_arena); + } + set_has_var(); + _impl_.kind_.var_ = var; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.var) +} +void Instruction::set_allocated_bitcast(::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE bitcast) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (bitcast) { + ::google::protobuf::Arena* submessage_arena = bitcast->GetArena(); + if (message_arena != submessage_arena) { + bitcast = ::google::protobuf::internal::GetOwnedMessage(message_arena, bitcast, submessage_arena); + } + set_has_bitcast(); + _impl_.kind_.bitcast_ = bitcast; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.bitcast) +} +void Instruction::set_allocated_construct(::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE construct) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (construct) { + ::google::protobuf::Arena* submessage_arena = construct->GetArena(); + if (message_arena != submessage_arena) { + construct = ::google::protobuf::internal::GetOwnedMessage(message_arena, construct, submessage_arena); + } + set_has_construct(); + _impl_.kind_.construct_ = construct; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.construct) +} +void Instruction::set_allocated_convert(::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE convert) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (convert) { + ::google::protobuf::Arena* submessage_arena = convert->GetArena(); + if (message_arena != submessage_arena) { + convert = ::google::protobuf::internal::GetOwnedMessage(message_arena, convert, submessage_arena); + } + set_has_convert(); + _impl_.kind_.convert_ = convert; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.convert) +} +void Instruction::set_allocated_access(::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE access) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (access) { + ::google::protobuf::Arena* submessage_arena = access->GetArena(); + if (message_arena != submessage_arena) { + access = ::google::protobuf::internal::GetOwnedMessage(message_arena, access, submessage_arena); + } + set_has_access(); + _impl_.kind_.access_ = access; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.access) +} +void Instruction::set_allocated_user_call(::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE user_call) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (user_call) { + ::google::protobuf::Arena* submessage_arena = user_call->GetArena(); + if (message_arena != submessage_arena) { + user_call = ::google::protobuf::internal::GetOwnedMessage(message_arena, user_call, submessage_arena); + } + set_has_user_call(); + _impl_.kind_.user_call_ = user_call; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.user_call) +} +void Instruction::set_allocated_builtin_call(::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE builtin_call) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (builtin_call) { + ::google::protobuf::Arena* submessage_arena = builtin_call->GetArena(); + if (message_arena != submessage_arena) { + builtin_call = ::google::protobuf::internal::GetOwnedMessage(message_arena, builtin_call, submessage_arena); + } + set_has_builtin_call(); + _impl_.kind_.builtin_call_ = builtin_call; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.builtin_call) +} +void Instruction::set_allocated_load(::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE load) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (load) { + ::google::protobuf::Arena* submessage_arena = load->GetArena(); + if (message_arena != submessage_arena) { + load = ::google::protobuf::internal::GetOwnedMessage(message_arena, load, submessage_arena); + } + set_has_load(); + _impl_.kind_.load_ = load; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.load) +} +void Instruction::set_allocated_store(::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE store) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (store) { + ::google::protobuf::Arena* submessage_arena = store->GetArena(); + if (message_arena != submessage_arena) { + store = ::google::protobuf::internal::GetOwnedMessage(message_arena, store, submessage_arena); + } + set_has_store(); + _impl_.kind_.store_ = store; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.store) +} +void Instruction::set_allocated_load_vector_element(::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE load_vector_element) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (load_vector_element) { + ::google::protobuf::Arena* submessage_arena = load_vector_element->GetArena(); + if (message_arena != submessage_arena) { + load_vector_element = ::google::protobuf::internal::GetOwnedMessage(message_arena, load_vector_element, submessage_arena); + } + set_has_load_vector_element(); + _impl_.kind_.load_vector_element_ = load_vector_element; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.load_vector_element) +} +void Instruction::set_allocated_store_vector_element(::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE store_vector_element) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (store_vector_element) { + ::google::protobuf::Arena* submessage_arena = store_vector_element->GetArena(); + if (message_arena != submessage_arena) { + store_vector_element = ::google::protobuf::internal::GetOwnedMessage(message_arena, store_vector_element, submessage_arena); + } + set_has_store_vector_element(); + _impl_.kind_.store_vector_element_ = store_vector_element; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.store_vector_element) +} +void Instruction::set_allocated_swizzle(::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE swizzle) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (swizzle) { + ::google::protobuf::Arena* submessage_arena = swizzle->GetArena(); + if (message_arena != submessage_arena) { + swizzle = ::google::protobuf::internal::GetOwnedMessage(message_arena, swizzle, submessage_arena); + } + set_has_swizzle(); + _impl_.kind_.swizzle_ = swizzle; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.swizzle) +} +void Instruction::set_allocated_if_(::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE if_) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (if_) { + ::google::protobuf::Arena* submessage_arena = if_->GetArena(); + if (message_arena != submessage_arena) { + if_ = ::google::protobuf::internal::GetOwnedMessage(message_arena, if_, submessage_arena); + } + set_has_if_(); + _impl_.kind_.if__ = if_; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.if) +} +void Instruction::set_allocated_switch_(::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE switch_) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (switch_) { + ::google::protobuf::Arena* submessage_arena = switch_->GetArena(); + if (message_arena != submessage_arena) { + switch_ = ::google::protobuf::internal::GetOwnedMessage(message_arena, switch_, submessage_arena); + } + set_has_switch_(); + _impl_.kind_.switch__ = switch_; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.switch) +} +void Instruction::set_allocated_loop(::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE loop) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (loop) { + ::google::protobuf::Arena* submessage_arena = loop->GetArena(); + if (message_arena != submessage_arena) { + loop = ::google::protobuf::internal::GetOwnedMessage(message_arena, loop, submessage_arena); + } + set_has_loop(); + _impl_.kind_.loop_ = loop; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.loop) +} +void Instruction::set_allocated_exit_if(::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE exit_if) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (exit_if) { + ::google::protobuf::Arena* submessage_arena = exit_if->GetArena(); + if (message_arena != submessage_arena) { + exit_if = ::google::protobuf::internal::GetOwnedMessage(message_arena, exit_if, submessage_arena); + } + set_has_exit_if(); + _impl_.kind_.exit_if_ = exit_if; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.exit_if) +} +void Instruction::set_allocated_exit_switch(::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE exit_switch) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (exit_switch) { + ::google::protobuf::Arena* submessage_arena = exit_switch->GetArena(); + if (message_arena != submessage_arena) { + exit_switch = ::google::protobuf::internal::GetOwnedMessage(message_arena, exit_switch, submessage_arena); + } + set_has_exit_switch(); + _impl_.kind_.exit_switch_ = exit_switch; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.exit_switch) +} +void Instruction::set_allocated_exit_loop(::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE exit_loop) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (exit_loop) { + ::google::protobuf::Arena* submessage_arena = exit_loop->GetArena(); + if (message_arena != submessage_arena) { + exit_loop = ::google::protobuf::internal::GetOwnedMessage(message_arena, exit_loop, submessage_arena); + } + set_has_exit_loop(); + _impl_.kind_.exit_loop_ = exit_loop; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.exit_loop) +} +void Instruction::set_allocated_next_iteration(::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE next_iteration) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (next_iteration) { + ::google::protobuf::Arena* submessage_arena = next_iteration->GetArena(); + if (message_arena != submessage_arena) { + next_iteration = ::google::protobuf::internal::GetOwnedMessage(message_arena, next_iteration, submessage_arena); + } + set_has_next_iteration(); + _impl_.kind_.next_iteration_ = next_iteration; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.next_iteration) +} +void Instruction::set_allocated_continue_(::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE continue_) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (continue_) { + ::google::protobuf::Arena* submessage_arena = continue_->GetArena(); + if (message_arena != submessage_arena) { + continue_ = ::google::protobuf::internal::GetOwnedMessage(message_arena, continue_, submessage_arena); + } + set_has_continue_(); + _impl_.kind_.continue__ = continue_; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.continue) +} +void Instruction::set_allocated_break_if(::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE break_if) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (break_if) { + ::google::protobuf::Arena* submessage_arena = break_if->GetArena(); + if (message_arena != submessage_arena) { + break_if = ::google::protobuf::internal::GetOwnedMessage(message_arena, break_if, submessage_arena); + } + set_has_break_if(); + _impl_.kind_.break_if_ = break_if; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.break_if) +} +void Instruction::set_allocated_unreachable(::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE unreachable) { + ::google::protobuf::Arena* message_arena = GetArena(); + clear_kind(); + if (unreachable) { + ::google::protobuf::Arena* submessage_arena = unreachable->GetArena(); + if (message_arena != submessage_arena) { + unreachable = ::google::protobuf::internal::GetOwnedMessage(message_arena, unreachable, submessage_arena); + } + set_has_unreachable(); + _impl_.kind_.unreachable_ = unreachable; + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Instruction.unreachable) +} +Instruction::Instruction(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Instruction_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Instruction) +} +PROTOBUF_NDEBUG_INLINE Instruction::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::Instruction& from_msg) + : operands_{visibility, arena, from.operands_}, + _operands_cached_byte_size_{0}, + results_{visibility, arena, from.results_}, + _results_cached_byte_size_{0}, + kind_{}, + _cached_size_{0}, + _oneof_case_{from._oneof_case_[0]} {} + +Instruction::Instruction( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Instruction& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Instruction_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Instruction* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + switch (kind_case()) { + case KIND_NOT_SET: + break; + case kReturn: + _impl_.kind_.return__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.return__); + break; + case kUnary: + _impl_.kind_.unary_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.unary_); + break; + case kBinary: + _impl_.kind_.binary_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.binary_); + break; + case kDiscard: + _impl_.kind_.discard_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.discard_); + break; + case kLet: + _impl_.kind_.let_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.let_); + break; + case kVar: + _impl_.kind_.var_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.var_); + break; + case kBitcast: + _impl_.kind_.bitcast_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.bitcast_); + break; + case kConstruct: + _impl_.kind_.construct_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.construct_); + break; + case kConvert: + _impl_.kind_.convert_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.convert_); + break; + case kAccess: + _impl_.kind_.access_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.access_); + break; + case kUserCall: + _impl_.kind_.user_call_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.user_call_); + break; + case kBuiltinCall: + _impl_.kind_.builtin_call_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.builtin_call_); + break; + case kLoad: + _impl_.kind_.load_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.load_); + break; + case kStore: + _impl_.kind_.store_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.store_); + break; + case kLoadVectorElement: + _impl_.kind_.load_vector_element_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.load_vector_element_); + break; + case kStoreVectorElement: + _impl_.kind_.store_vector_element_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.store_vector_element_); + break; + case kSwizzle: + _impl_.kind_.swizzle_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.swizzle_); + break; + case kIf: + _impl_.kind_.if__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.if__); + break; + case kSwitch: + _impl_.kind_.switch__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.switch__); + break; + case kLoop: + _impl_.kind_.loop_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.loop_); + break; + case kExitIf: + _impl_.kind_.exit_if_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.exit_if_); + break; + case kExitSwitch: + _impl_.kind_.exit_switch_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.exit_switch_); + break; + case kExitLoop: + _impl_.kind_.exit_loop_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.exit_loop_); + break; + case kNextIteration: + _impl_.kind_.next_iteration_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.next_iteration_); + break; + case kContinue: + _impl_.kind_.continue__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.continue__); + break; + case kBreakIf: + _impl_.kind_.break_if_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.break_if_); + break; + case kUnreachable: + _impl_.kind_.unreachable_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.unreachable_); + break; + } + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.Instruction) +} +PROTOBUF_NDEBUG_INLINE Instruction::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : operands_{visibility, arena}, + _operands_cached_byte_size_{0}, + results_{visibility, arena}, + _results_cached_byte_size_{0}, + kind_{}, + _cached_size_{0}, + _oneof_case_{} {} + +inline void Instruction::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +Instruction::~Instruction() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Instruction) + SharedDtor(*this); +} +inline void Instruction::SharedDtor(MessageLite& self) { + Instruction& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + if (this_.has_kind()) { + this_.clear_kind(); + } + this_._impl_.~Impl_(); +} + +void Instruction::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:tint.core.ir.binary.pb.Instruction) + ::google::protobuf::internal::TSanWrite(&_impl_); + switch (kind_case()) { + case kReturn: { + if (GetArena() == nullptr) { + delete _impl_.kind_.return__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.return__); + } + break; + } + case kUnary: { + if (GetArena() == nullptr) { + delete _impl_.kind_.unary_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.unary_); + } + break; + } + case kBinary: { + if (GetArena() == nullptr) { + delete _impl_.kind_.binary_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.binary_); + } + break; + } + case kDiscard: { + if (GetArena() == nullptr) { + delete _impl_.kind_.discard_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.discard_); + } + break; + } + case kLet: { + if (GetArena() == nullptr) { + delete _impl_.kind_.let_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.let_); + } + break; + } + case kVar: { + if (GetArena() == nullptr) { + delete _impl_.kind_.var_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.var_); + } + break; + } + case kBitcast: { + if (GetArena() == nullptr) { + delete _impl_.kind_.bitcast_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.bitcast_); + } + break; + } + case kConstruct: { + if (GetArena() == nullptr) { + delete _impl_.kind_.construct_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.construct_); + } + break; + } + case kConvert: { + if (GetArena() == nullptr) { + delete _impl_.kind_.convert_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.convert_); + } + break; + } + case kAccess: { + if (GetArena() == nullptr) { + delete _impl_.kind_.access_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.access_); + } + break; + } + case kUserCall: { + if (GetArena() == nullptr) { + delete _impl_.kind_.user_call_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.user_call_); + } + break; + } + case kBuiltinCall: { + if (GetArena() == nullptr) { + delete _impl_.kind_.builtin_call_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.builtin_call_); + } + break; + } + case kLoad: { + if (GetArena() == nullptr) { + delete _impl_.kind_.load_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.load_); + } + break; + } + case kStore: { + if (GetArena() == nullptr) { + delete _impl_.kind_.store_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.store_); + } + break; + } + case kLoadVectorElement: { + if (GetArena() == nullptr) { + delete _impl_.kind_.load_vector_element_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.load_vector_element_); + } + break; + } + case kStoreVectorElement: { + if (GetArena() == nullptr) { + delete _impl_.kind_.store_vector_element_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.store_vector_element_); + } + break; + } + case kSwizzle: { + if (GetArena() == nullptr) { + delete _impl_.kind_.swizzle_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.swizzle_); + } + break; + } + case kIf: { + if (GetArena() == nullptr) { + delete _impl_.kind_.if__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.if__); + } + break; + } + case kSwitch: { + if (GetArena() == nullptr) { + delete _impl_.kind_.switch__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.switch__); + } + break; + } + case kLoop: { + if (GetArena() == nullptr) { + delete _impl_.kind_.loop_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.loop_); + } + break; + } + case kExitIf: { + if (GetArena() == nullptr) { + delete _impl_.kind_.exit_if_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.exit_if_); + } + break; + } + case kExitSwitch: { + if (GetArena() == nullptr) { + delete _impl_.kind_.exit_switch_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.exit_switch_); + } + break; + } + case kExitLoop: { + if (GetArena() == nullptr) { + delete _impl_.kind_.exit_loop_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.exit_loop_); + } + break; + } + case kNextIteration: { + if (GetArena() == nullptr) { + delete _impl_.kind_.next_iteration_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.next_iteration_); + } + break; + } + case kContinue: { + if (GetArena() == nullptr) { + delete _impl_.kind_.continue__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.continue__); + } + break; + } + case kBreakIf: { + if (GetArena() == nullptr) { + delete _impl_.kind_.break_if_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.break_if_); + } + break; + } + case kUnreachable: { + if (GetArena() == nullptr) { + delete _impl_.kind_.unreachable_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.unreachable_); + } + break; + } + case KIND_NOT_SET: { + break; + } + } + _impl_._oneof_case_[0] = KIND_NOT_SET; +} + + +inline void* PROTOBUF_NONNULL Instruction::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Instruction(arena); +} +constexpr auto Instruction::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Instruction, _impl_.operands_) + + decltype(Instruction::_impl_.operands_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Instruction, _impl_.results_) + + decltype(Instruction::_impl_.results_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(Instruction), alignof(Instruction), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Instruction::PlacementNew_, + sizeof(Instruction), + alignof(Instruction)); + } +} +constexpr auto Instruction::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Instruction_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Instruction::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Instruction::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Instruction::ByteSizeLong, + &Instruction::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Instruction, _impl_._cached_size_), + false, + }, + &Instruction::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Instruction_class_data_ = + Instruction::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Instruction::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Instruction_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Instruction_class_data_.tc_table); + return Instruction_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 29, 27, 0, 2> +Instruction::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 29, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 3758096384, // skipmap + offsetof(decltype(_table_), field_entries), + 29, // num_field_entries + 27, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Instruction_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Instruction>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated uint32 results = 2; + {::_pbi::TcParser::FastV32P1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(Instruction, _impl_.results_)}}, + // repeated uint32 operands = 1; + {::_pbi::TcParser::FastV32P1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(Instruction, _impl_.operands_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated uint32 operands = 1; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.operands_), 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + // repeated uint32 results = 2; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.results_), 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + // .tint.core.ir.binary.pb.InstructionReturn return = 3; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.return__), _Internal::kOneofCaseOffset + 0, 0, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionUnary unary = 4; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.unary_), _Internal::kOneofCaseOffset + 0, 1, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionBinary binary = 5; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.binary_), _Internal::kOneofCaseOffset + 0, 2, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionDiscard discard = 6; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.discard_), _Internal::kOneofCaseOffset + 0, 3, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionLet let = 7; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.let_), _Internal::kOneofCaseOffset + 0, 4, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionVar var = 8; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.var_), _Internal::kOneofCaseOffset + 0, 5, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionBitcast bitcast = 9; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.bitcast_), _Internal::kOneofCaseOffset + 0, 6, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionConstruct construct = 10; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.construct_), _Internal::kOneofCaseOffset + 0, 7, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionConvert convert = 11; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.convert_), _Internal::kOneofCaseOffset + 0, 8, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionAccess access = 12; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.access_), _Internal::kOneofCaseOffset + 0, 9, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionUserCall user_call = 13; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.user_call_), _Internal::kOneofCaseOffset + 0, 10, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionBuiltinCall builtin_call = 14; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.builtin_call_), _Internal::kOneofCaseOffset + 0, 11, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionLoad load = 15; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.load_), _Internal::kOneofCaseOffset + 0, 12, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionStore store = 16; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.store_), _Internal::kOneofCaseOffset + 0, 13, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionLoadVectorElement load_vector_element = 17; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.load_vector_element_), _Internal::kOneofCaseOffset + 0, 14, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionStoreVectorElement store_vector_element = 18; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.store_vector_element_), _Internal::kOneofCaseOffset + 0, 15, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionSwizzle swizzle = 19; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.swizzle_), _Internal::kOneofCaseOffset + 0, 16, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionIf if = 20; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.if__), _Internal::kOneofCaseOffset + 0, 17, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionSwitch switch = 21; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.switch__), _Internal::kOneofCaseOffset + 0, 18, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionLoop loop = 22; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.loop_), _Internal::kOneofCaseOffset + 0, 19, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionExitIf exit_if = 23; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.exit_if_), _Internal::kOneofCaseOffset + 0, 20, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionExitSwitch exit_switch = 24; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.exit_switch_), _Internal::kOneofCaseOffset + 0, 21, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionExitLoop exit_loop = 25; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.exit_loop_), _Internal::kOneofCaseOffset + 0, 22, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionNextIteration next_iteration = 26; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.next_iteration_), _Internal::kOneofCaseOffset + 0, 23, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionContinue continue = 27; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.continue__), _Internal::kOneofCaseOffset + 0, 24, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionBreakIf break_if = 28; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.break_if_), _Internal::kOneofCaseOffset + 0, 25, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + // .tint.core.ir.binary.pb.InstructionUnreachable unreachable = 29; + {PROTOBUF_FIELD_OFFSET(Instruction, _impl_.kind_.unreachable_), _Internal::kOneofCaseOffset + 0, 26, (0 | ::_fl::kFcOneof | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionReturn>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionUnary>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBinary>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionDiscard>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLet>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionVar>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBitcast>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionConstruct>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionConvert>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionAccess>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionUserCall>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBuiltinCall>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLoad>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionStore>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLoadVectorElement>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionStoreVectorElement>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionSwizzle>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionIf>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionSwitch>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLoop>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionExitIf>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionExitSwitch>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionExitLoop>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionNextIteration>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionContinue>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBreakIf>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionUnreachable>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void Instruction::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Instruction) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.operands_.Clear(); + _impl_.results_.Clear(); + clear_kind(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Instruction::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Instruction& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Instruction::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Instruction& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Instruction) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated uint32 operands = 1; + { + int byte_size = this_._impl_._operands_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 1, this_._internal_operands(), byte_size, target); + } + } + + // repeated uint32 results = 2; + { + int byte_size = this_._impl_._results_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 2, this_._internal_results(), byte_size, target); + } + } + + switch (this_.kind_case()) { + case kReturn: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.kind_.return__, this_._impl_.kind_.return__->GetCachedSize(), target, + stream); + break; + } + case kUnary: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.kind_.unary_, this_._impl_.kind_.unary_->GetCachedSize(), target, + stream); + break; + } + case kBinary: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.kind_.binary_, this_._impl_.kind_.binary_->GetCachedSize(), target, + stream); + break; + } + case kDiscard: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.kind_.discard_, this_._impl_.kind_.discard_->GetCachedSize(), target, + stream); + break; + } + case kLet: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, *this_._impl_.kind_.let_, this_._impl_.kind_.let_->GetCachedSize(), target, + stream); + break; + } + case kVar: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.kind_.var_, this_._impl_.kind_.var_->GetCachedSize(), target, + stream); + break; + } + case kBitcast: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 9, *this_._impl_.kind_.bitcast_, this_._impl_.kind_.bitcast_->GetCachedSize(), target, + stream); + break; + } + case kConstruct: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 10, *this_._impl_.kind_.construct_, this_._impl_.kind_.construct_->GetCachedSize(), target, + stream); + break; + } + case kConvert: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 11, *this_._impl_.kind_.convert_, this_._impl_.kind_.convert_->GetCachedSize(), target, + stream); + break; + } + case kAccess: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 12, *this_._impl_.kind_.access_, this_._impl_.kind_.access_->GetCachedSize(), target, + stream); + break; + } + case kUserCall: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 13, *this_._impl_.kind_.user_call_, this_._impl_.kind_.user_call_->GetCachedSize(), target, + stream); + break; + } + case kBuiltinCall: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 14, *this_._impl_.kind_.builtin_call_, this_._impl_.kind_.builtin_call_->GetCachedSize(), target, + stream); + break; + } + case kLoad: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 15, *this_._impl_.kind_.load_, this_._impl_.kind_.load_->GetCachedSize(), target, + stream); + break; + } + case kStore: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 16, *this_._impl_.kind_.store_, this_._impl_.kind_.store_->GetCachedSize(), target, + stream); + break; + } + case kLoadVectorElement: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 17, *this_._impl_.kind_.load_vector_element_, this_._impl_.kind_.load_vector_element_->GetCachedSize(), target, + stream); + break; + } + case kStoreVectorElement: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 18, *this_._impl_.kind_.store_vector_element_, this_._impl_.kind_.store_vector_element_->GetCachedSize(), target, + stream); + break; + } + case kSwizzle: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 19, *this_._impl_.kind_.swizzle_, this_._impl_.kind_.swizzle_->GetCachedSize(), target, + stream); + break; + } + case kIf: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 20, *this_._impl_.kind_.if__, this_._impl_.kind_.if__->GetCachedSize(), target, + stream); + break; + } + case kSwitch: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 21, *this_._impl_.kind_.switch__, this_._impl_.kind_.switch__->GetCachedSize(), target, + stream); + break; + } + case kLoop: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 22, *this_._impl_.kind_.loop_, this_._impl_.kind_.loop_->GetCachedSize(), target, + stream); + break; + } + case kExitIf: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 23, *this_._impl_.kind_.exit_if_, this_._impl_.kind_.exit_if_->GetCachedSize(), target, + stream); + break; + } + case kExitSwitch: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 24, *this_._impl_.kind_.exit_switch_, this_._impl_.kind_.exit_switch_->GetCachedSize(), target, + stream); + break; + } + case kExitLoop: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 25, *this_._impl_.kind_.exit_loop_, this_._impl_.kind_.exit_loop_->GetCachedSize(), target, + stream); + break; + } + case kNextIteration: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 26, *this_._impl_.kind_.next_iteration_, this_._impl_.kind_.next_iteration_->GetCachedSize(), target, + stream); + break; + } + case kContinue: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 27, *this_._impl_.kind_.continue__, this_._impl_.kind_.continue__->GetCachedSize(), target, + stream); + break; + } + case kBreakIf: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 28, *this_._impl_.kind_.break_if_, this_._impl_.kind_.break_if_->GetCachedSize(), target, + stream); + break; + } + case kUnreachable: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 29, *this_._impl_.kind_.unreachable_, this_._impl_.kind_.unreachable_->GetCachedSize(), target, + stream); + break; + } + default: + break; + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Instruction) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Instruction::ByteSizeLong(const MessageLite& base) { + const Instruction& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Instruction::ByteSizeLong() const { + const Instruction& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Instruction) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 operands = 1; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_operands(), 1, + this_._impl_._operands_cached_byte_size_); + } + // repeated uint32 results = 2; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_results(), 1, + this_._impl_._results_cached_byte_size_); + } + } + switch (this_.kind_case()) { + // .tint.core.ir.binary.pb.InstructionReturn return = 3; + case kReturn: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.return__); + break; + } + // .tint.core.ir.binary.pb.InstructionUnary unary = 4; + case kUnary: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.unary_); + break; + } + // .tint.core.ir.binary.pb.InstructionBinary binary = 5; + case kBinary: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.binary_); + break; + } + // .tint.core.ir.binary.pb.InstructionDiscard discard = 6; + case kDiscard: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.discard_); + break; + } + // .tint.core.ir.binary.pb.InstructionLet let = 7; + case kLet: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.let_); + break; + } + // .tint.core.ir.binary.pb.InstructionVar var = 8; + case kVar: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.var_); + break; + } + // .tint.core.ir.binary.pb.InstructionBitcast bitcast = 9; + case kBitcast: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.bitcast_); + break; + } + // .tint.core.ir.binary.pb.InstructionConstruct construct = 10; + case kConstruct: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.construct_); + break; + } + // .tint.core.ir.binary.pb.InstructionConvert convert = 11; + case kConvert: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.convert_); + break; + } + // .tint.core.ir.binary.pb.InstructionAccess access = 12; + case kAccess: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.access_); + break; + } + // .tint.core.ir.binary.pb.InstructionUserCall user_call = 13; + case kUserCall: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.user_call_); + break; + } + // .tint.core.ir.binary.pb.InstructionBuiltinCall builtin_call = 14; + case kBuiltinCall: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.builtin_call_); + break; + } + // .tint.core.ir.binary.pb.InstructionLoad load = 15; + case kLoad: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.load_); + break; + } + // .tint.core.ir.binary.pb.InstructionStore store = 16; + case kStore: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.store_); + break; + } + // .tint.core.ir.binary.pb.InstructionLoadVectorElement load_vector_element = 17; + case kLoadVectorElement: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.load_vector_element_); + break; + } + // .tint.core.ir.binary.pb.InstructionStoreVectorElement store_vector_element = 18; + case kStoreVectorElement: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.store_vector_element_); + break; + } + // .tint.core.ir.binary.pb.InstructionSwizzle swizzle = 19; + case kSwizzle: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.swizzle_); + break; + } + // .tint.core.ir.binary.pb.InstructionIf if = 20; + case kIf: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.if__); + break; + } + // .tint.core.ir.binary.pb.InstructionSwitch switch = 21; + case kSwitch: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.switch__); + break; + } + // .tint.core.ir.binary.pb.InstructionLoop loop = 22; + case kLoop: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.loop_); + break; + } + // .tint.core.ir.binary.pb.InstructionExitIf exit_if = 23; + case kExitIf: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.exit_if_); + break; + } + // .tint.core.ir.binary.pb.InstructionExitSwitch exit_switch = 24; + case kExitSwitch: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.exit_switch_); + break; + } + // .tint.core.ir.binary.pb.InstructionExitLoop exit_loop = 25; + case kExitLoop: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.exit_loop_); + break; + } + // .tint.core.ir.binary.pb.InstructionNextIteration next_iteration = 26; + case kNextIteration: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.next_iteration_); + break; + } + // .tint.core.ir.binary.pb.InstructionContinue continue = 27; + case kContinue: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.continue__); + break; + } + // .tint.core.ir.binary.pb.InstructionBreakIf break_if = 28; + case kBreakIf: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.break_if_); + break; + } + // .tint.core.ir.binary.pb.InstructionUnreachable unreachable = 29; + case kUnreachable: { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.unreachable_); + break; + } + case KIND_NOT_SET: { + break; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Instruction::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Instruction) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_operands()->MergeFrom(from._internal_operands()); + _this->_internal_mutable_results()->MergeFrom(from._internal_results()); + if (const uint32_t oneof_from_case = from._impl_._oneof_case_[0]) { + const uint32_t oneof_to_case = _this->_impl_._oneof_case_[0]; + const bool oneof_needs_init = oneof_to_case != oneof_from_case; + if (oneof_needs_init) { + if (oneof_to_case != 0) { + _this->clear_kind(); + } + _this->_impl_._oneof_case_[0] = oneof_from_case; + } + + switch (oneof_from_case) { + case kReturn: { + if (oneof_needs_init) { + _this->_impl_.kind_.return__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.return__); + } else { + _this->_impl_.kind_.return__->MergeFrom(*from._impl_.kind_.return__); + } + break; + } + case kUnary: { + if (oneof_needs_init) { + _this->_impl_.kind_.unary_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.unary_); + } else { + _this->_impl_.kind_.unary_->MergeFrom(*from._impl_.kind_.unary_); + } + break; + } + case kBinary: { + if (oneof_needs_init) { + _this->_impl_.kind_.binary_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.binary_); + } else { + _this->_impl_.kind_.binary_->MergeFrom(*from._impl_.kind_.binary_); + } + break; + } + case kDiscard: { + if (oneof_needs_init) { + _this->_impl_.kind_.discard_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.discard_); + } else { + _this->_impl_.kind_.discard_->MergeFrom(*from._impl_.kind_.discard_); + } + break; + } + case kLet: { + if (oneof_needs_init) { + _this->_impl_.kind_.let_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.let_); + } else { + _this->_impl_.kind_.let_->MergeFrom(*from._impl_.kind_.let_); + } + break; + } + case kVar: { + if (oneof_needs_init) { + _this->_impl_.kind_.var_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.var_); + } else { + _this->_impl_.kind_.var_->MergeFrom(*from._impl_.kind_.var_); + } + break; + } + case kBitcast: { + if (oneof_needs_init) { + _this->_impl_.kind_.bitcast_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.bitcast_); + } else { + _this->_impl_.kind_.bitcast_->MergeFrom(*from._impl_.kind_.bitcast_); + } + break; + } + case kConstruct: { + if (oneof_needs_init) { + _this->_impl_.kind_.construct_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.construct_); + } else { + _this->_impl_.kind_.construct_->MergeFrom(*from._impl_.kind_.construct_); + } + break; + } + case kConvert: { + if (oneof_needs_init) { + _this->_impl_.kind_.convert_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.convert_); + } else { + _this->_impl_.kind_.convert_->MergeFrom(*from._impl_.kind_.convert_); + } + break; + } + case kAccess: { + if (oneof_needs_init) { + _this->_impl_.kind_.access_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.access_); + } else { + _this->_impl_.kind_.access_->MergeFrom(*from._impl_.kind_.access_); + } + break; + } + case kUserCall: { + if (oneof_needs_init) { + _this->_impl_.kind_.user_call_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.user_call_); + } else { + _this->_impl_.kind_.user_call_->MergeFrom(*from._impl_.kind_.user_call_); + } + break; + } + case kBuiltinCall: { + if (oneof_needs_init) { + _this->_impl_.kind_.builtin_call_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.builtin_call_); + } else { + _this->_impl_.kind_.builtin_call_->MergeFrom(*from._impl_.kind_.builtin_call_); + } + break; + } + case kLoad: { + if (oneof_needs_init) { + _this->_impl_.kind_.load_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.load_); + } else { + _this->_impl_.kind_.load_->MergeFrom(*from._impl_.kind_.load_); + } + break; + } + case kStore: { + if (oneof_needs_init) { + _this->_impl_.kind_.store_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.store_); + } else { + _this->_impl_.kind_.store_->MergeFrom(*from._impl_.kind_.store_); + } + break; + } + case kLoadVectorElement: { + if (oneof_needs_init) { + _this->_impl_.kind_.load_vector_element_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.load_vector_element_); + } else { + _this->_impl_.kind_.load_vector_element_->MergeFrom(*from._impl_.kind_.load_vector_element_); + } + break; + } + case kStoreVectorElement: { + if (oneof_needs_init) { + _this->_impl_.kind_.store_vector_element_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.store_vector_element_); + } else { + _this->_impl_.kind_.store_vector_element_->MergeFrom(*from._impl_.kind_.store_vector_element_); + } + break; + } + case kSwizzle: { + if (oneof_needs_init) { + _this->_impl_.kind_.swizzle_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.swizzle_); + } else { + _this->_impl_.kind_.swizzle_->MergeFrom(*from._impl_.kind_.swizzle_); + } + break; + } + case kIf: { + if (oneof_needs_init) { + _this->_impl_.kind_.if__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.if__); + } else { + _this->_impl_.kind_.if__->MergeFrom(*from._impl_.kind_.if__); + } + break; + } + case kSwitch: { + if (oneof_needs_init) { + _this->_impl_.kind_.switch__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.switch__); + } else { + _this->_impl_.kind_.switch__->MergeFrom(*from._impl_.kind_.switch__); + } + break; + } + case kLoop: { + if (oneof_needs_init) { + _this->_impl_.kind_.loop_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.loop_); + } else { + _this->_impl_.kind_.loop_->MergeFrom(*from._impl_.kind_.loop_); + } + break; + } + case kExitIf: { + if (oneof_needs_init) { + _this->_impl_.kind_.exit_if_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.exit_if_); + } else { + _this->_impl_.kind_.exit_if_->MergeFrom(*from._impl_.kind_.exit_if_); + } + break; + } + case kExitSwitch: { + if (oneof_needs_init) { + _this->_impl_.kind_.exit_switch_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.exit_switch_); + } else { + _this->_impl_.kind_.exit_switch_->MergeFrom(*from._impl_.kind_.exit_switch_); + } + break; + } + case kExitLoop: { + if (oneof_needs_init) { + _this->_impl_.kind_.exit_loop_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.exit_loop_); + } else { + _this->_impl_.kind_.exit_loop_->MergeFrom(*from._impl_.kind_.exit_loop_); + } + break; + } + case kNextIteration: { + if (oneof_needs_init) { + _this->_impl_.kind_.next_iteration_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.next_iteration_); + } else { + _this->_impl_.kind_.next_iteration_->MergeFrom(*from._impl_.kind_.next_iteration_); + } + break; + } + case kContinue: { + if (oneof_needs_init) { + _this->_impl_.kind_.continue__ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.continue__); + } else { + _this->_impl_.kind_.continue__->MergeFrom(*from._impl_.kind_.continue__); + } + break; + } + case kBreakIf: { + if (oneof_needs_init) { + _this->_impl_.kind_.break_if_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.break_if_); + } else { + _this->_impl_.kind_.break_if_->MergeFrom(*from._impl_.kind_.break_if_); + } + break; + } + case kUnreachable: { + if (oneof_needs_init) { + _this->_impl_.kind_.unreachable_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.kind_.unreachable_); + } else { + _this->_impl_.kind_.unreachable_->MergeFrom(*from._impl_.kind_.unreachable_); + } + break; + } + case KIND_NOT_SET: + break; + } + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Instruction::CopyFrom(const Instruction& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Instruction) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Instruction::InternalSwap(Instruction* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.operands_.InternalSwap(&other->_impl_.operands_); + _impl_.results_.InternalSwap(&other->_impl_.results_); + swap(_impl_.kind_, other->_impl_.kind_); + swap(_impl_._oneof_case_[0], other->_impl_._oneof_case_[0]); +} + +::google::protobuf::Metadata Instruction::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionReturn::_Internal { + public: +}; + +InstructionReturn::InstructionReturn(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionReturn_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionReturn) +} +InstructionReturn::InstructionReturn( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionReturn& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionReturn_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionReturn* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionReturn) +} + +inline void* PROTOBUF_NONNULL InstructionReturn::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionReturn(arena); +} +constexpr auto InstructionReturn::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionReturn), + alignof(InstructionReturn)); +} +constexpr auto InstructionReturn::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionReturn_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionReturn::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionReturn::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionReturn::ByteSizeLong, + &InstructionReturn::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionReturn, _impl_._cached_size_), + false, + }, + &InstructionReturn::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionReturn_class_data_ = + InstructionReturn::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionReturn::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionReturn_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionReturn_class_data_.tc_table); + return InstructionReturn_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionReturn::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionReturn_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionReturn>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionReturn::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionUnary::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionUnary, _impl_._has_bits_); +}; + +InstructionUnary::InstructionUnary(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionUnary_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionUnary) +} +InstructionUnary::InstructionUnary( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionUnary& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionUnary_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE InstructionUnary::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void InstructionUnary::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.op_ = {}; +} +InstructionUnary::~InstructionUnary() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionUnary) + SharedDtor(*this); +} +inline void InstructionUnary::SharedDtor(MessageLite& self) { + InstructionUnary& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionUnary::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionUnary(arena); +} +constexpr auto InstructionUnary::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionUnary), + alignof(InstructionUnary)); +} +constexpr auto InstructionUnary::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionUnary_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionUnary::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionUnary::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionUnary::ByteSizeLong, + &InstructionUnary::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionUnary, _impl_._cached_size_), + false, + }, + &InstructionUnary::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionUnary_class_data_ = + InstructionUnary::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionUnary::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionUnary_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionUnary_class_data_.tc_table); + return InstructionUnary_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +InstructionUnary::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionUnary, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionUnary_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionUnary>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .tint.core.ir.binary.pb.UnaryOp op = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionUnary, _impl_.op_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionUnary, _impl_.op_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.UnaryOp op = 1; + {PROTOBUF_FIELD_OFFSET(InstructionUnary, _impl_.op_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionUnary::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionUnary) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.op_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionUnary::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionUnary& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionUnary::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionUnary& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionUnary) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.UnaryOp op = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_op() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_op(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionUnary) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionUnary::ByteSizeLong(const MessageLite& base) { + const InstructionUnary& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionUnary::ByteSizeLong() const { + const InstructionUnary& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionUnary) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // .tint.core.ir.binary.pb.UnaryOp op = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_op() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_op()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionUnary::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionUnary) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_op() != 0) { + _this->_impl_.op_ = from._impl_.op_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionUnary::CopyFrom(const InstructionUnary& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionUnary) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionUnary::InternalSwap(InstructionUnary* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.op_, other->_impl_.op_); +} + +::google::protobuf::Metadata InstructionUnary::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionBinary::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionBinary, _impl_._has_bits_); +}; + +InstructionBinary::InstructionBinary(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionBinary_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionBinary) +} +InstructionBinary::InstructionBinary( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionBinary& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionBinary_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE InstructionBinary::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void InstructionBinary::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.op_ = {}; +} +InstructionBinary::~InstructionBinary() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionBinary) + SharedDtor(*this); +} +inline void InstructionBinary::SharedDtor(MessageLite& self) { + InstructionBinary& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionBinary::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionBinary(arena); +} +constexpr auto InstructionBinary::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionBinary), + alignof(InstructionBinary)); +} +constexpr auto InstructionBinary::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionBinary_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionBinary::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionBinary::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionBinary::ByteSizeLong, + &InstructionBinary::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionBinary, _impl_._cached_size_), + false, + }, + &InstructionBinary::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionBinary_class_data_ = + InstructionBinary::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionBinary::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionBinary_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionBinary_class_data_.tc_table); + return InstructionBinary_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +InstructionBinary::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionBinary, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionBinary_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBinary>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .tint.core.ir.binary.pb.BinaryOp op = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionBinary, _impl_.op_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionBinary, _impl_.op_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.BinaryOp op = 1; + {PROTOBUF_FIELD_OFFSET(InstructionBinary, _impl_.op_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionBinary::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionBinary) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.op_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionBinary::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionBinary& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionBinary::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionBinary& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionBinary) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.BinaryOp op = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_op() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_op(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionBinary) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionBinary::ByteSizeLong(const MessageLite& base) { + const InstructionBinary& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionBinary::ByteSizeLong() const { + const InstructionBinary& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionBinary) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // .tint.core.ir.binary.pb.BinaryOp op = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_op() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_op()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionBinary::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionBinary) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_op() != 0) { + _this->_impl_.op_ = from._impl_.op_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionBinary::CopyFrom(const InstructionBinary& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionBinary) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionBinary::InternalSwap(InstructionBinary* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.op_, other->_impl_.op_); +} + +::google::protobuf::Metadata InstructionBinary::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionBitcast::_Internal { + public: +}; + +InstructionBitcast::InstructionBitcast(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionBitcast_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionBitcast) +} +InstructionBitcast::InstructionBitcast( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionBitcast& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionBitcast_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionBitcast* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionBitcast) +} + +inline void* PROTOBUF_NONNULL InstructionBitcast::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionBitcast(arena); +} +constexpr auto InstructionBitcast::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionBitcast), + alignof(InstructionBitcast)); +} +constexpr auto InstructionBitcast::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionBitcast_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionBitcast::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionBitcast::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionBitcast::ByteSizeLong, + &InstructionBitcast::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionBitcast, _impl_._cached_size_), + false, + }, + &InstructionBitcast::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionBitcast_class_data_ = + InstructionBitcast::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionBitcast::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionBitcast_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionBitcast_class_data_.tc_table); + return InstructionBitcast_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionBitcast::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionBitcast_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBitcast>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionBitcast::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionConstruct::_Internal { + public: +}; + +InstructionConstruct::InstructionConstruct(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionConstruct_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionConstruct) +} +InstructionConstruct::InstructionConstruct( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionConstruct& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionConstruct_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionConstruct* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionConstruct) +} + +inline void* PROTOBUF_NONNULL InstructionConstruct::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionConstruct(arena); +} +constexpr auto InstructionConstruct::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionConstruct), + alignof(InstructionConstruct)); +} +constexpr auto InstructionConstruct::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionConstruct_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionConstruct::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionConstruct::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionConstruct::ByteSizeLong, + &InstructionConstruct::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionConstruct, _impl_._cached_size_), + false, + }, + &InstructionConstruct::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionConstruct_class_data_ = + InstructionConstruct::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionConstruct::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionConstruct_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionConstruct_class_data_.tc_table); + return InstructionConstruct_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionConstruct::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionConstruct_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionConstruct>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionConstruct::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionDiscard::_Internal { + public: +}; + +InstructionDiscard::InstructionDiscard(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionDiscard_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionDiscard) +} +InstructionDiscard::InstructionDiscard( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionDiscard& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionDiscard_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionDiscard* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionDiscard) +} + +inline void* PROTOBUF_NONNULL InstructionDiscard::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionDiscard(arena); +} +constexpr auto InstructionDiscard::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionDiscard), + alignof(InstructionDiscard)); +} +constexpr auto InstructionDiscard::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionDiscard_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionDiscard::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionDiscard::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionDiscard::ByteSizeLong, + &InstructionDiscard::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionDiscard, _impl_._cached_size_), + false, + }, + &InstructionDiscard::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionDiscard_class_data_ = + InstructionDiscard::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionDiscard::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionDiscard_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionDiscard_class_data_.tc_table); + return InstructionDiscard_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionDiscard::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionDiscard_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionDiscard>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionDiscard::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionLet::_Internal { + public: +}; + +InstructionLet::InstructionLet(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionLet_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionLet) +} +InstructionLet::InstructionLet( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionLet& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionLet_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionLet* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionLet) +} + +inline void* PROTOBUF_NONNULL InstructionLet::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionLet(arena); +} +constexpr auto InstructionLet::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionLet), + alignof(InstructionLet)); +} +constexpr auto InstructionLet::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionLet_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionLet::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionLet::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionLet::ByteSizeLong, + &InstructionLet::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionLet, _impl_._cached_size_), + false, + }, + &InstructionLet::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionLet_class_data_ = + InstructionLet::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionLet::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionLet_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionLet_class_data_.tc_table); + return InstructionLet_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionLet::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionLet_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLet>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionLet::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionVar::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_._has_bits_); +}; + +InstructionVar::InstructionVar(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionVar_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionVar) +} +PROTOBUF_NDEBUG_INLINE InstructionVar::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::InstructionVar& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +InstructionVar::InstructionVar( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionVar& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionVar_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionVar* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.binding_point_ = ((cached_has_bits & 0x00000001U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.binding_point_) + : nullptr; + _impl_.input_attachment_index_ = from._impl_.input_attachment_index_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionVar) +} +PROTOBUF_NDEBUG_INLINE InstructionVar::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void InstructionVar::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, binding_point_), + 0, + offsetof(Impl_, input_attachment_index_) - + offsetof(Impl_, binding_point_) + + sizeof(Impl_::input_attachment_index_)); +} +InstructionVar::~InstructionVar() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionVar) + SharedDtor(*this); +} +inline void InstructionVar::SharedDtor(MessageLite& self) { + InstructionVar& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.binding_point_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionVar::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionVar(arena); +} +constexpr auto InstructionVar::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionVar), + alignof(InstructionVar)); +} +constexpr auto InstructionVar::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionVar_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionVar::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionVar::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionVar::ByteSizeLong, + &InstructionVar::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_._cached_size_), + false, + }, + &InstructionVar::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionVar_class_data_ = + InstructionVar::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionVar::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionVar_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionVar_class_data_.tc_table); + return InstructionVar_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 1, 0, 2> +InstructionVar::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + InstructionVar_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionVar>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // optional uint32 input_attachment_index = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionVar, _impl_.input_attachment_index_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_.input_attachment_index_)}}, + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 1; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_.binding_point_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 1; + {PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_.binding_point_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // optional uint32 input_attachment_index = 2; + {PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_.input_attachment_index_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::BindingPoint>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionVar::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionVar) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + ABSL_DCHECK(_impl_.binding_point_ != nullptr); + _impl_.binding_point_->Clear(); + } + _impl_.input_attachment_index_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionVar::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionVar& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionVar::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionVar& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionVar) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.binding_point_, this_._impl_.binding_point_->GetCachedSize(), target, + stream); + } + + // optional uint32 input_attachment_index = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_input_attachment_index(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionVar) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionVar::ByteSizeLong(const MessageLite& base) { + const InstructionVar& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionVar::ByteSizeLong() const { + const InstructionVar& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionVar) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.binding_point_); + } + // optional uint32 input_attachment_index = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_input_attachment_index()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionVar::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionVar) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + ABSL_DCHECK(from._impl_.binding_point_ != nullptr); + if (_this->_impl_.binding_point_ == nullptr) { + _this->_impl_.binding_point_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.binding_point_); + } else { + _this->_impl_.binding_point_->MergeFrom(*from._impl_.binding_point_); + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + _this->_impl_.input_attachment_index_ = from._impl_.input_attachment_index_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionVar::CopyFrom(const InstructionVar& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionVar) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionVar::InternalSwap(InstructionVar* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_.input_attachment_index_) + + sizeof(InstructionVar::_impl_.input_attachment_index_) + - PROTOBUF_FIELD_OFFSET(InstructionVar, _impl_.binding_point_)>( + reinterpret_cast(&_impl_.binding_point_), + reinterpret_cast(&other->_impl_.binding_point_)); +} + +::google::protobuf::Metadata InstructionVar::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionConvert::_Internal { + public: +}; + +InstructionConvert::InstructionConvert(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionConvert_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionConvert) +} +InstructionConvert::InstructionConvert( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionConvert& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionConvert_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionConvert* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionConvert) +} + +inline void* PROTOBUF_NONNULL InstructionConvert::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionConvert(arena); +} +constexpr auto InstructionConvert::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionConvert), + alignof(InstructionConvert)); +} +constexpr auto InstructionConvert::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionConvert_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionConvert::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionConvert::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionConvert::ByteSizeLong, + &InstructionConvert::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionConvert, _impl_._cached_size_), + false, + }, + &InstructionConvert::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionConvert_class_data_ = + InstructionConvert::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionConvert::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionConvert_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionConvert_class_data_.tc_table); + return InstructionConvert_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionConvert::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionConvert_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionConvert>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionConvert::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionAccess::_Internal { + public: +}; + +InstructionAccess::InstructionAccess(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionAccess_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionAccess) +} +InstructionAccess::InstructionAccess( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionAccess& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionAccess_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionAccess* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionAccess) +} + +inline void* PROTOBUF_NONNULL InstructionAccess::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionAccess(arena); +} +constexpr auto InstructionAccess::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionAccess), + alignof(InstructionAccess)); +} +constexpr auto InstructionAccess::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionAccess_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionAccess::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionAccess::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionAccess::ByteSizeLong, + &InstructionAccess::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionAccess, _impl_._cached_size_), + false, + }, + &InstructionAccess::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionAccess_class_data_ = + InstructionAccess::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionAccess::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionAccess_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionAccess_class_data_.tc_table); + return InstructionAccess_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionAccess::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionAccess_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionAccess>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionAccess::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionUserCall::_Internal { + public: +}; + +InstructionUserCall::InstructionUserCall(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionUserCall_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionUserCall) +} +InstructionUserCall::InstructionUserCall( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionUserCall& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionUserCall_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionUserCall* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionUserCall) +} + +inline void* PROTOBUF_NONNULL InstructionUserCall::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionUserCall(arena); +} +constexpr auto InstructionUserCall::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionUserCall), + alignof(InstructionUserCall)); +} +constexpr auto InstructionUserCall::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionUserCall_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionUserCall::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionUserCall::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionUserCall::ByteSizeLong, + &InstructionUserCall::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionUserCall, _impl_._cached_size_), + false, + }, + &InstructionUserCall::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionUserCall_class_data_ = + InstructionUserCall::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionUserCall::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionUserCall_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionUserCall_class_data_.tc_table); + return InstructionUserCall_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionUserCall::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionUserCall_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionUserCall>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionUserCall::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionBuiltinCall::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_._has_bits_); +}; + +InstructionBuiltinCall::InstructionBuiltinCall(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionBuiltinCall_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionBuiltinCall) +} +PROTOBUF_NDEBUG_INLINE InstructionBuiltinCall::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::InstructionBuiltinCall& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + explicit_template_params_{visibility, arena, from.explicit_template_params_}, + _explicit_template_params_cached_byte_size_{0} {} + +InstructionBuiltinCall::InstructionBuiltinCall( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionBuiltinCall& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionBuiltinCall_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionBuiltinCall* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.builtin_ = from._impl_.builtin_; + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionBuiltinCall) +} +PROTOBUF_NDEBUG_INLINE InstructionBuiltinCall::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + explicit_template_params_{visibility, arena}, + _explicit_template_params_cached_byte_size_{0} {} + +inline void InstructionBuiltinCall::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.builtin_ = {}; +} +InstructionBuiltinCall::~InstructionBuiltinCall() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionBuiltinCall) + SharedDtor(*this); +} +inline void InstructionBuiltinCall::SharedDtor(MessageLite& self) { + InstructionBuiltinCall& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionBuiltinCall::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionBuiltinCall(arena); +} +constexpr auto InstructionBuiltinCall::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_.explicit_template_params_) + + decltype(InstructionBuiltinCall::_impl_.explicit_template_params_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(InstructionBuiltinCall), alignof(InstructionBuiltinCall), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&InstructionBuiltinCall::PlacementNew_, + sizeof(InstructionBuiltinCall), + alignof(InstructionBuiltinCall)); + } +} +constexpr auto InstructionBuiltinCall::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionBuiltinCall_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionBuiltinCall::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionBuiltinCall::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionBuiltinCall::ByteSizeLong, + &InstructionBuiltinCall::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_._cached_size_), + false, + }, + &InstructionBuiltinCall::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionBuiltinCall_class_data_ = + InstructionBuiltinCall::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionBuiltinCall::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionBuiltinCall_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionBuiltinCall_class_data_.tc_table); + return InstructionBuiltinCall_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +InstructionBuiltinCall::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionBuiltinCall_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBuiltinCall>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated uint32 explicit_template_params = 2; + {::_pbi::TcParser::FastV32P1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_.explicit_template_params_)}}, + // .tint.core.ir.binary.pb.BuiltinFn builtin = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionBuiltinCall, _impl_.builtin_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_.builtin_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.BuiltinFn builtin = 1; + {PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_.builtin_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // repeated uint32 explicit_template_params = 2; + {PROTOBUF_FIELD_OFFSET(InstructionBuiltinCall, _impl_.explicit_template_params_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionBuiltinCall::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionBuiltinCall) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.explicit_template_params_.Clear(); + _impl_.builtin_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionBuiltinCall::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionBuiltinCall& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionBuiltinCall::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionBuiltinCall& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionBuiltinCall) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.BuiltinFn builtin = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_builtin() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_builtin(), target); + } + } + + // repeated uint32 explicit_template_params = 2; + { + int byte_size = this_._impl_._explicit_template_params_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 2, this_._internal_explicit_template_params(), byte_size, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionBuiltinCall) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionBuiltinCall::ByteSizeLong(const MessageLite& base) { + const InstructionBuiltinCall& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionBuiltinCall::ByteSizeLong() const { + const InstructionBuiltinCall& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionBuiltinCall) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 explicit_template_params = 2; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_explicit_template_params(), 1, + this_._impl_._explicit_template_params_cached_byte_size_); + } + } + { + // .tint.core.ir.binary.pb.BuiltinFn builtin = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_builtin() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_builtin()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionBuiltinCall::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionBuiltinCall) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_explicit_template_params()->MergeFrom(from._internal_explicit_template_params()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_builtin() != 0) { + _this->_impl_.builtin_ = from._impl_.builtin_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionBuiltinCall::CopyFrom(const InstructionBuiltinCall& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionBuiltinCall) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionBuiltinCall::InternalSwap(InstructionBuiltinCall* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.explicit_template_params_.InternalSwap(&other->_impl_.explicit_template_params_); + swap(_impl_.builtin_, other->_impl_.builtin_); +} + +::google::protobuf::Metadata InstructionBuiltinCall::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionLoad::_Internal { + public: +}; + +InstructionLoad::InstructionLoad(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionLoad_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionLoad) +} +InstructionLoad::InstructionLoad( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionLoad& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionLoad_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionLoad* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionLoad) +} + +inline void* PROTOBUF_NONNULL InstructionLoad::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionLoad(arena); +} +constexpr auto InstructionLoad::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionLoad), + alignof(InstructionLoad)); +} +constexpr auto InstructionLoad::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionLoad_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionLoad::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionLoad::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionLoad::ByteSizeLong, + &InstructionLoad::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionLoad, _impl_._cached_size_), + false, + }, + &InstructionLoad::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionLoad_class_data_ = + InstructionLoad::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionLoad::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionLoad_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionLoad_class_data_.tc_table); + return InstructionLoad_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionLoad::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionLoad_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLoad>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionLoad::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionStore::_Internal { + public: +}; + +InstructionStore::InstructionStore(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionStore_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionStore) +} +InstructionStore::InstructionStore( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionStore& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionStore_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionStore* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionStore) +} + +inline void* PROTOBUF_NONNULL InstructionStore::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionStore(arena); +} +constexpr auto InstructionStore::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionStore), + alignof(InstructionStore)); +} +constexpr auto InstructionStore::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionStore_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionStore::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionStore::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionStore::ByteSizeLong, + &InstructionStore::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionStore, _impl_._cached_size_), + false, + }, + &InstructionStore::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionStore_class_data_ = + InstructionStore::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionStore::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionStore_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionStore_class_data_.tc_table); + return InstructionStore_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionStore::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionStore_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionStore>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionStore::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionLoadVectorElement::_Internal { + public: +}; + +InstructionLoadVectorElement::InstructionLoadVectorElement(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionLoadVectorElement_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionLoadVectorElement) +} +InstructionLoadVectorElement::InstructionLoadVectorElement( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionLoadVectorElement& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionLoadVectorElement_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionLoadVectorElement* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionLoadVectorElement) +} + +inline void* PROTOBUF_NONNULL InstructionLoadVectorElement::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionLoadVectorElement(arena); +} +constexpr auto InstructionLoadVectorElement::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionLoadVectorElement), + alignof(InstructionLoadVectorElement)); +} +constexpr auto InstructionLoadVectorElement::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionLoadVectorElement_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionLoadVectorElement::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionLoadVectorElement::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionLoadVectorElement::ByteSizeLong, + &InstructionLoadVectorElement::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionLoadVectorElement, _impl_._cached_size_), + false, + }, + &InstructionLoadVectorElement::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionLoadVectorElement_class_data_ = + InstructionLoadVectorElement::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionLoadVectorElement::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionLoadVectorElement_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionLoadVectorElement_class_data_.tc_table); + return InstructionLoadVectorElement_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionLoadVectorElement::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionLoadVectorElement_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLoadVectorElement>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionLoadVectorElement::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionStoreVectorElement::_Internal { + public: +}; + +InstructionStoreVectorElement::InstructionStoreVectorElement(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionStoreVectorElement_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionStoreVectorElement) +} +InstructionStoreVectorElement::InstructionStoreVectorElement( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionStoreVectorElement& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionStoreVectorElement_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionStoreVectorElement* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionStoreVectorElement) +} + +inline void* PROTOBUF_NONNULL InstructionStoreVectorElement::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionStoreVectorElement(arena); +} +constexpr auto InstructionStoreVectorElement::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionStoreVectorElement), + alignof(InstructionStoreVectorElement)); +} +constexpr auto InstructionStoreVectorElement::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionStoreVectorElement_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionStoreVectorElement::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionStoreVectorElement::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionStoreVectorElement::ByteSizeLong, + &InstructionStoreVectorElement::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionStoreVectorElement, _impl_._cached_size_), + false, + }, + &InstructionStoreVectorElement::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionStoreVectorElement_class_data_ = + InstructionStoreVectorElement::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionStoreVectorElement::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionStoreVectorElement_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionStoreVectorElement_class_data_.tc_table); + return InstructionStoreVectorElement_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionStoreVectorElement::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionStoreVectorElement_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionStoreVectorElement>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionStoreVectorElement::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionSwizzle::_Internal { + public: +}; + +InstructionSwizzle::InstructionSwizzle(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionSwizzle_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionSwizzle) +} +PROTOBUF_NDEBUG_INLINE InstructionSwizzle::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::InstructionSwizzle& from_msg) + : indices_{visibility, arena, from.indices_}, + _indices_cached_byte_size_{0}, + _cached_size_{0} {} + +InstructionSwizzle::InstructionSwizzle( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionSwizzle& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionSwizzle_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionSwizzle* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionSwizzle) +} +PROTOBUF_NDEBUG_INLINE InstructionSwizzle::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : indices_{visibility, arena}, + _indices_cached_byte_size_{0}, + _cached_size_{0} {} + +inline void InstructionSwizzle::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +InstructionSwizzle::~InstructionSwizzle() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionSwizzle) + SharedDtor(*this); +} +inline void InstructionSwizzle::SharedDtor(MessageLite& self) { + InstructionSwizzle& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionSwizzle::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionSwizzle(arena); +} +constexpr auto InstructionSwizzle::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(InstructionSwizzle, _impl_.indices_) + + decltype(InstructionSwizzle::_impl_.indices_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(InstructionSwizzle), alignof(InstructionSwizzle), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&InstructionSwizzle::PlacementNew_, + sizeof(InstructionSwizzle), + alignof(InstructionSwizzle)); + } +} +constexpr auto InstructionSwizzle::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionSwizzle_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionSwizzle::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionSwizzle::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionSwizzle::ByteSizeLong, + &InstructionSwizzle::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionSwizzle, _impl_._cached_size_), + false, + }, + &InstructionSwizzle::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionSwizzle_class_data_ = + InstructionSwizzle::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionSwizzle::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionSwizzle_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionSwizzle_class_data_.tc_table); + return InstructionSwizzle_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +InstructionSwizzle::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionSwizzle_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionSwizzle>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated uint32 indices = 1; + {::_pbi::TcParser::FastV32P1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(InstructionSwizzle, _impl_.indices_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated uint32 indices = 1; + {PROTOBUF_FIELD_OFFSET(InstructionSwizzle, _impl_.indices_), 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionSwizzle::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionSwizzle) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.indices_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionSwizzle::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionSwizzle& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionSwizzle::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionSwizzle& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionSwizzle) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated uint32 indices = 1; + { + int byte_size = this_._impl_._indices_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 1, this_._internal_indices(), byte_size, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionSwizzle) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionSwizzle::ByteSizeLong(const MessageLite& base) { + const InstructionSwizzle& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionSwizzle::ByteSizeLong() const { + const InstructionSwizzle& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionSwizzle) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 indices = 1; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_indices(), 1, + this_._impl_._indices_cached_byte_size_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionSwizzle::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionSwizzle) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_indices()->MergeFrom(from._internal_indices()); + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionSwizzle::CopyFrom(const InstructionSwizzle& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionSwizzle) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionSwizzle::InternalSwap(InstructionSwizzle* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.indices_.InternalSwap(&other->_impl_.indices_); +} + +::google::protobuf::Metadata InstructionSwizzle::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionIf::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_._has_bits_); +}; + +InstructionIf::InstructionIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionIf_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionIf) +} +InstructionIf::InstructionIf( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionIf& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionIf_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE InstructionIf::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void InstructionIf::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, true__), + 0, + offsetof(Impl_, false__) - + offsetof(Impl_, true__) + + sizeof(Impl_::false__)); +} +InstructionIf::~InstructionIf() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionIf) + SharedDtor(*this); +} +inline void InstructionIf::SharedDtor(MessageLite& self) { + InstructionIf& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionIf::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionIf(arena); +} +constexpr auto InstructionIf::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionIf), + alignof(InstructionIf)); +} +constexpr auto InstructionIf::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionIf_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionIf::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionIf::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionIf::ByteSizeLong, + &InstructionIf::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_._cached_size_), + false, + }, + &InstructionIf::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionIf_class_data_ = + InstructionIf::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionIf::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionIf_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionIf_class_data_.tc_table); + return InstructionIf_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +InstructionIf::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionIf_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionIf>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // optional uint32 false = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionIf, _impl_.false__), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_.false__)}}, + // optional uint32 true = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionIf, _impl_.true__), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_.true__)}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional uint32 true = 1; + {PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_.true__), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 false = 2; + {PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_.false__), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionIf::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionIf) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.true__, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.false__) - + reinterpret_cast(&_impl_.true__)) + sizeof(_impl_.false__)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionIf::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionIf& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionIf::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionIf& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionIf) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional uint32 true = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_true_(), target); + } + + // optional uint32 false = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_false_(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionIf) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionIf::ByteSizeLong(const MessageLite& base) { + const InstructionIf& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionIf::ByteSizeLong() const { + const InstructionIf& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionIf) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // optional uint32 true = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_true_()); + } + // optional uint32 false = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_false_()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionIf::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionIf) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _this->_impl_.true__ = from._impl_.true__; + } + if ((cached_has_bits & 0x00000002U) != 0) { + _this->_impl_.false__ = from._impl_.false__; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionIf::CopyFrom(const InstructionIf& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionIf) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionIf::InternalSwap(InstructionIf* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_.false__) + + sizeof(InstructionIf::_impl_.false__) + - PROTOBUF_FIELD_OFFSET(InstructionIf, _impl_.true__)>( + reinterpret_cast(&_impl_.true__), + reinterpret_cast(&other->_impl_.true__)); +} + +::google::protobuf::Metadata InstructionIf::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionSwitch::_Internal { + public: +}; + +InstructionSwitch::InstructionSwitch(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionSwitch_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionSwitch) +} +PROTOBUF_NDEBUG_INLINE InstructionSwitch::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::InstructionSwitch& from_msg) + : cases_{visibility, arena, from.cases_}, + _cached_size_{0} {} + +InstructionSwitch::InstructionSwitch( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionSwitch& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionSwitch_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionSwitch* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionSwitch) +} +PROTOBUF_NDEBUG_INLINE InstructionSwitch::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : cases_{visibility, arena}, + _cached_size_{0} {} + +inline void InstructionSwitch::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +InstructionSwitch::~InstructionSwitch() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionSwitch) + SharedDtor(*this); +} +inline void InstructionSwitch::SharedDtor(MessageLite& self) { + InstructionSwitch& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionSwitch::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionSwitch(arena); +} +constexpr auto InstructionSwitch::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(InstructionSwitch, _impl_.cases_) + + decltype(InstructionSwitch::_impl_.cases_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(InstructionSwitch), alignof(InstructionSwitch), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&InstructionSwitch::PlacementNew_, + sizeof(InstructionSwitch), + alignof(InstructionSwitch)); + } +} +constexpr auto InstructionSwitch::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionSwitch_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionSwitch::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionSwitch::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionSwitch::ByteSizeLong, + &InstructionSwitch::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionSwitch, _impl_._cached_size_), + false, + }, + &InstructionSwitch::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionSwitch_class_data_ = + InstructionSwitch::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionSwitch::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionSwitch_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionSwitch_class_data_.tc_table); + return InstructionSwitch_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 1, 0, 2> +InstructionSwitch::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + InstructionSwitch_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionSwitch>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated .tint.core.ir.binary.pb.SwitchCase cases = 1; + {::_pbi::TcParser::FastMtR1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(InstructionSwitch, _impl_.cases_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated .tint.core.ir.binary.pb.SwitchCase cases = 1; + {PROTOBUF_FIELD_OFFSET(InstructionSwitch, _impl_.cases_), 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::SwitchCase>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionSwitch::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionSwitch) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.cases_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionSwitch::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionSwitch& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionSwitch::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionSwitch& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionSwitch) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .tint.core.ir.binary.pb.SwitchCase cases = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_cases_size()); + i < n; i++) { + const auto& repfield = this_._internal_cases().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionSwitch) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionSwitch::ByteSizeLong(const MessageLite& base) { + const InstructionSwitch& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionSwitch::ByteSizeLong() const { + const InstructionSwitch& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionSwitch) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .tint.core.ir.binary.pb.SwitchCase cases = 1; + { + total_size += 1UL * this_._internal_cases_size(); + for (const auto& msg : this_._internal_cases()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionSwitch::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionSwitch) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_cases()->MergeFrom( + from._internal_cases()); + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionSwitch::CopyFrom(const InstructionSwitch& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionSwitch) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionSwitch::InternalSwap(InstructionSwitch* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.cases_.InternalSwap(&other->_impl_.cases_); +} + +::google::protobuf::Metadata InstructionSwitch::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionLoop::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_._has_bits_); +}; + +InstructionLoop::InstructionLoop(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionLoop_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionLoop) +} +InstructionLoop::InstructionLoop( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionLoop& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionLoop_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE InstructionLoop::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void InstructionLoop::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, initializer_), + 0, + offsetof(Impl_, continuing_) - + offsetof(Impl_, initializer_) + + sizeof(Impl_::continuing_)); +} +InstructionLoop::~InstructionLoop() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionLoop) + SharedDtor(*this); +} +inline void InstructionLoop::SharedDtor(MessageLite& self) { + InstructionLoop& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionLoop::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionLoop(arena); +} +constexpr auto InstructionLoop::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionLoop), + alignof(InstructionLoop)); +} +constexpr auto InstructionLoop::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionLoop_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionLoop::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionLoop::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionLoop::ByteSizeLong, + &InstructionLoop::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_._cached_size_), + false, + }, + &InstructionLoop::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionLoop_class_data_ = + InstructionLoop::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionLoop::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionLoop_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionLoop_class_data_.tc_table); + return InstructionLoop_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +InstructionLoop::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionLoop_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionLoop>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional uint32 initializer = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionLoop, _impl_.initializer_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.initializer_)}}, + // optional uint32 body = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionLoop, _impl_.body_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.body_)}}, + // optional uint32 continuing = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionLoop, _impl_.continuing_), 2>(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.continuing_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional uint32 initializer = 1; + {PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.initializer_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 body = 2; + {PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.body_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 continuing = 3; + {PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.continuing_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionLoop::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionLoop) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + ::memset(&_impl_.initializer_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.continuing_) - + reinterpret_cast(&_impl_.initializer_)) + sizeof(_impl_.continuing_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionLoop::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionLoop& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionLoop::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionLoop& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionLoop) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional uint32 initializer = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_initializer(), target); + } + + // optional uint32 body = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_body(), target); + } + + // optional uint32 continuing = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_continuing(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionLoop) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionLoop::ByteSizeLong(const MessageLite& base) { + const InstructionLoop& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionLoop::ByteSizeLong() const { + const InstructionLoop& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionLoop) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + // optional uint32 initializer = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_initializer()); + } + // optional uint32 body = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_body()); + } + // optional uint32 continuing = 3; + if ((cached_has_bits & 0x00000004U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_continuing()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionLoop::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionLoop) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000007U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + _this->_impl_.initializer_ = from._impl_.initializer_; + } + if ((cached_has_bits & 0x00000002U) != 0) { + _this->_impl_.body_ = from._impl_.body_; + } + if ((cached_has_bits & 0x00000004U) != 0) { + _this->_impl_.continuing_ = from._impl_.continuing_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionLoop::CopyFrom(const InstructionLoop& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionLoop) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionLoop::InternalSwap(InstructionLoop* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.continuing_) + + sizeof(InstructionLoop::_impl_.continuing_) + - PROTOBUF_FIELD_OFFSET(InstructionLoop, _impl_.initializer_)>( + reinterpret_cast(&_impl_.initializer_), + reinterpret_cast(&other->_impl_.initializer_)); +} + +::google::protobuf::Metadata InstructionLoop::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionExitIf::_Internal { + public: +}; + +InstructionExitIf::InstructionExitIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionExitIf_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionExitIf) +} +InstructionExitIf::InstructionExitIf( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionExitIf& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionExitIf_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionExitIf* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionExitIf) +} + +inline void* PROTOBUF_NONNULL InstructionExitIf::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionExitIf(arena); +} +constexpr auto InstructionExitIf::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionExitIf), + alignof(InstructionExitIf)); +} +constexpr auto InstructionExitIf::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionExitIf_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionExitIf::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionExitIf::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionExitIf::ByteSizeLong, + &InstructionExitIf::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionExitIf, _impl_._cached_size_), + false, + }, + &InstructionExitIf::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionExitIf_class_data_ = + InstructionExitIf::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionExitIf::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionExitIf_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionExitIf_class_data_.tc_table); + return InstructionExitIf_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionExitIf::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionExitIf_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionExitIf>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionExitIf::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionExitSwitch::_Internal { + public: +}; + +InstructionExitSwitch::InstructionExitSwitch(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionExitSwitch_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionExitSwitch) +} +InstructionExitSwitch::InstructionExitSwitch( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionExitSwitch& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionExitSwitch_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionExitSwitch* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionExitSwitch) +} + +inline void* PROTOBUF_NONNULL InstructionExitSwitch::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionExitSwitch(arena); +} +constexpr auto InstructionExitSwitch::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionExitSwitch), + alignof(InstructionExitSwitch)); +} +constexpr auto InstructionExitSwitch::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionExitSwitch_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionExitSwitch::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionExitSwitch::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionExitSwitch::ByteSizeLong, + &InstructionExitSwitch::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionExitSwitch, _impl_._cached_size_), + false, + }, + &InstructionExitSwitch::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionExitSwitch_class_data_ = + InstructionExitSwitch::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionExitSwitch::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionExitSwitch_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionExitSwitch_class_data_.tc_table); + return InstructionExitSwitch_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionExitSwitch::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionExitSwitch_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionExitSwitch>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionExitSwitch::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionExitLoop::_Internal { + public: +}; + +InstructionExitLoop::InstructionExitLoop(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionExitLoop_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionExitLoop) +} +InstructionExitLoop::InstructionExitLoop( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionExitLoop& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionExitLoop_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionExitLoop* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionExitLoop) +} + +inline void* PROTOBUF_NONNULL InstructionExitLoop::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionExitLoop(arena); +} +constexpr auto InstructionExitLoop::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionExitLoop), + alignof(InstructionExitLoop)); +} +constexpr auto InstructionExitLoop::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionExitLoop_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionExitLoop::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionExitLoop::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionExitLoop::ByteSizeLong, + &InstructionExitLoop::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionExitLoop, _impl_._cached_size_), + false, + }, + &InstructionExitLoop::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionExitLoop_class_data_ = + InstructionExitLoop::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionExitLoop::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionExitLoop_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionExitLoop_class_data_.tc_table); + return InstructionExitLoop_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionExitLoop::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionExitLoop_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionExitLoop>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionExitLoop::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class SwitchCase::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_._has_bits_); +}; + +SwitchCase::SwitchCase(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SwitchCase_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.SwitchCase) +} +PROTOBUF_NDEBUG_INLINE SwitchCase::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::SwitchCase& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + selectors_{visibility, arena, from.selectors_}, + _selectors_cached_byte_size_{0} {} + +SwitchCase::SwitchCase( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const SwitchCase& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SwitchCase_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SwitchCase* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, block_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, block_), + offsetof(Impl_, is_default_) - + offsetof(Impl_, block_) + + sizeof(Impl_::is_default_)); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.SwitchCase) +} +PROTOBUF_NDEBUG_INLINE SwitchCase::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0}, + selectors_{visibility, arena}, + _selectors_cached_byte_size_{0} {} + +inline void SwitchCase::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, block_), + 0, + offsetof(Impl_, is_default_) - + offsetof(Impl_, block_) + + sizeof(Impl_::is_default_)); +} +SwitchCase::~SwitchCase() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.SwitchCase) + SharedDtor(*this); +} +inline void SwitchCase::SharedDtor(MessageLite& self) { + SwitchCase& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL SwitchCase::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) SwitchCase(arena); +} +constexpr auto SwitchCase::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.selectors_) + + decltype(SwitchCase::_impl_.selectors_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if constexpr (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(SwitchCase), alignof(SwitchCase), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&SwitchCase::PlacementNew_, + sizeof(SwitchCase), + alignof(SwitchCase)); + } +} +constexpr auto SwitchCase::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_SwitchCase_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &SwitchCase::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &SwitchCase::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &SwitchCase::ByteSizeLong, + &SwitchCase::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_._cached_size_), + false, + }, + &SwitchCase::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull SwitchCase_class_data_ = + SwitchCase::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +SwitchCase::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&SwitchCase_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(SwitchCase_class_data_.tc_table); + return SwitchCase_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 0, 2> +SwitchCase::_table_ = { + { + PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + SwitchCase_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::SwitchCase>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // uint32 block = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(SwitchCase, _impl_.block_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.block_)}}, + // repeated uint32 selectors = 2; + {::_pbi::TcParser::FastV32P1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.selectors_)}}, + // bool is_default = 3; + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 1, 0, PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.is_default_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 block = 1; + {PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.block_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // repeated uint32 selectors = 2; + {PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.selectors_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kPackedUInt32)}, + // bool is_default = 3; + {PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.is_default_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void SwitchCase::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.SwitchCase) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.selectors_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.block_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.is_default_) - + reinterpret_cast(&_impl_.block_)) + sizeof(_impl_.is_default_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL SwitchCase::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const SwitchCase& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL SwitchCase::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const SwitchCase& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.SwitchCase) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 block = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_block() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_block(), target); + } + } + + // repeated uint32 selectors = 2; + { + int byte_size = this_._impl_._selectors_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 2, this_._internal_selectors(), byte_size, target); + } + } + + // bool is_default = 3; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_is_default() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_is_default(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.SwitchCase) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t SwitchCase::ByteSizeLong(const MessageLite& base) { + const SwitchCase& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t SwitchCase::ByteSizeLong() const { + const SwitchCase& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.SwitchCase) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated uint32 selectors = 2; + { + total_size += + ::_pbi::WireFormatLite::UInt32SizeWithPackedTagSize( + this_._internal_selectors(), 1, + this_._impl_._selectors_cached_byte_size_); + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // uint32 block = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_block() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_block()); + } + } + // bool is_default = 3; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_is_default() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void SwitchCase::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.SwitchCase) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_selectors()->MergeFrom(from._internal_selectors()); + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_block() != 0) { + _this->_impl_.block_ = from._impl_.block_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_is_default() != 0) { + _this->_impl_.is_default_ = from._impl_.is_default_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void SwitchCase::CopyFrom(const SwitchCase& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.SwitchCase) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void SwitchCase::InternalSwap(SwitchCase* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.selectors_.InternalSwap(&other->_impl_.selectors_); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.is_default_) + + sizeof(SwitchCase::_impl_.is_default_) + - PROTOBUF_FIELD_OFFSET(SwitchCase, _impl_.block_)>( + reinterpret_cast(&_impl_.block_), + reinterpret_cast(&other->_impl_.block_)); +} + +::google::protobuf::Metadata SwitchCase::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class BindingPoint::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_._has_bits_); +}; + +BindingPoint::BindingPoint(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, BindingPoint_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.BindingPoint) +} +BindingPoint::BindingPoint( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const BindingPoint& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, BindingPoint_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE BindingPoint::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void BindingPoint::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, group_), + 0, + offsetof(Impl_, binding_) - + offsetof(Impl_, group_) + + sizeof(Impl_::binding_)); +} +BindingPoint::~BindingPoint() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.BindingPoint) + SharedDtor(*this); +} +inline void BindingPoint::SharedDtor(MessageLite& self) { + BindingPoint& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL BindingPoint::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) BindingPoint(arena); +} +constexpr auto BindingPoint::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(BindingPoint), + alignof(BindingPoint)); +} +constexpr auto BindingPoint::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_BindingPoint_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &BindingPoint::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &BindingPoint::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &BindingPoint::ByteSizeLong, + &BindingPoint::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_._cached_size_), + false, + }, + &BindingPoint::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull BindingPoint_class_data_ = + BindingPoint::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +BindingPoint::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&BindingPoint_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(BindingPoint_class_data_.tc_table); + return BindingPoint_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +BindingPoint::_table_ = { + { + PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + BindingPoint_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::BindingPoint>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 binding = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(BindingPoint, _impl_.binding_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_.binding_)}}, + // uint32 group = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(BindingPoint, _impl_.group_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_.group_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 group = 1; + {PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_.group_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // uint32 binding = 2; + {PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_.binding_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void BindingPoint::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.BindingPoint) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.group_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.binding_) - + reinterpret_cast(&_impl_.group_)) + sizeof(_impl_.binding_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL BindingPoint::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const BindingPoint& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL BindingPoint::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const BindingPoint& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.BindingPoint) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 group = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_group() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_group(), target); + } + } + + // uint32 binding = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002U) != 0) { + if (this_._internal_binding() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_binding(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.BindingPoint) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t BindingPoint::ByteSizeLong(const MessageLite& base) { + const BindingPoint& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t BindingPoint::ByteSizeLong() const { + const BindingPoint& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.BindingPoint) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // uint32 group = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_group() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_group()); + } + } + // uint32 binding = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + if (this_._internal_binding() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_binding()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void BindingPoint::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.BindingPoint) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_group() != 0) { + _this->_impl_.group_ = from._impl_.group_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + if (from._internal_binding() != 0) { + _this->_impl_.binding_ = from._impl_.binding_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void BindingPoint::CopyFrom(const BindingPoint& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.BindingPoint) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void BindingPoint::InternalSwap(BindingPoint* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_.binding_) + + sizeof(BindingPoint::_impl_.binding_) + - PROTOBUF_FIELD_OFFSET(BindingPoint, _impl_.group_)>( + reinterpret_cast(&_impl_.group_), + reinterpret_cast(&other->_impl_.group_)); +} + +::google::protobuf::Metadata BindingPoint::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionNextIteration::_Internal { + public: +}; + +InstructionNextIteration::InstructionNextIteration(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionNextIteration_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionNextIteration) +} +InstructionNextIteration::InstructionNextIteration( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionNextIteration& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionNextIteration_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionNextIteration* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionNextIteration) +} + +inline void* PROTOBUF_NONNULL InstructionNextIteration::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionNextIteration(arena); +} +constexpr auto InstructionNextIteration::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionNextIteration), + alignof(InstructionNextIteration)); +} +constexpr auto InstructionNextIteration::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionNextIteration_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionNextIteration::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionNextIteration::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionNextIteration::ByteSizeLong, + &InstructionNextIteration::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionNextIteration, _impl_._cached_size_), + false, + }, + &InstructionNextIteration::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionNextIteration_class_data_ = + InstructionNextIteration::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionNextIteration::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionNextIteration_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionNextIteration_class_data_.tc_table); + return InstructionNextIteration_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionNextIteration::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionNextIteration_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionNextIteration>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionNextIteration::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionContinue::_Internal { + public: +}; + +InstructionContinue::InstructionContinue(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionContinue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionContinue) +} +InstructionContinue::InstructionContinue( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionContinue& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionContinue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionContinue* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionContinue) +} + +inline void* PROTOBUF_NONNULL InstructionContinue::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionContinue(arena); +} +constexpr auto InstructionContinue::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionContinue), + alignof(InstructionContinue)); +} +constexpr auto InstructionContinue::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionContinue_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionContinue::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionContinue::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionContinue::ByteSizeLong, + &InstructionContinue::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionContinue, _impl_._cached_size_), + false, + }, + &InstructionContinue::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionContinue_class_data_ = + InstructionContinue::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionContinue::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionContinue_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionContinue_class_data_.tc_table); + return InstructionContinue_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionContinue::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionContinue_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionContinue>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionContinue::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionBreakIf::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InstructionBreakIf, _impl_._has_bits_); +}; + +InstructionBreakIf::InstructionBreakIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionBreakIf_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionBreakIf) +} +InstructionBreakIf::InstructionBreakIf( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionBreakIf& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, InstructionBreakIf_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE InstructionBreakIf::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void InstructionBreakIf::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.num_next_iter_values_ = {}; +} +InstructionBreakIf::~InstructionBreakIf() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.InstructionBreakIf) + SharedDtor(*this); +} +inline void InstructionBreakIf::SharedDtor(MessageLite& self) { + InstructionBreakIf& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL InstructionBreakIf::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionBreakIf(arena); +} +constexpr auto InstructionBreakIf::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionBreakIf), + alignof(InstructionBreakIf)); +} +constexpr auto InstructionBreakIf::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionBreakIf_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionBreakIf::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionBreakIf::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &InstructionBreakIf::ByteSizeLong, + &InstructionBreakIf::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionBreakIf, _impl_._cached_size_), + false, + }, + &InstructionBreakIf::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionBreakIf_class_data_ = + InstructionBreakIf::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionBreakIf::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionBreakIf_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionBreakIf_class_data_.tc_table); + return InstructionBreakIf_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> +InstructionBreakIf::_table_ = { + { + PROTOBUF_FIELD_OFFSET(InstructionBreakIf, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionBreakIf_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionBreakIf>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 num_next_iter_values = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(InstructionBreakIf, _impl_.num_next_iter_values_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(InstructionBreakIf, _impl_.num_next_iter_values_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 num_next_iter_values = 1; + {PROTOBUF_FIELD_OFFSET(InstructionBreakIf, _impl_.num_next_iter_values_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void InstructionBreakIf::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.InstructionBreakIf) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.num_next_iter_values_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InstructionBreakIf::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InstructionBreakIf& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InstructionBreakIf::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InstructionBreakIf& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.InstructionBreakIf) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // uint32 num_next_iter_values = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_num_next_iter_values() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_num_next_iter_values(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.InstructionBreakIf) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InstructionBreakIf::ByteSizeLong(const MessageLite& base) { + const InstructionBreakIf& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InstructionBreakIf::ByteSizeLong() const { + const InstructionBreakIf& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.InstructionBreakIf) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + { + // uint32 num_next_iter_values = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_num_next_iter_values() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_num_next_iter_values()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InstructionBreakIf::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.InstructionBreakIf) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_num_next_iter_values() != 0) { + _this->_impl_.num_next_iter_values_ = from._impl_.num_next_iter_values_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void InstructionBreakIf::CopyFrom(const InstructionBreakIf& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.InstructionBreakIf) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InstructionBreakIf::InternalSwap(InstructionBreakIf* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.num_next_iter_values_, other->_impl_.num_next_iter_values_); +} + +::google::protobuf::Metadata InstructionBreakIf::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class InstructionUnreachable::_Internal { + public: +}; + +InstructionUnreachable::InstructionUnreachable(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionUnreachable_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.InstructionUnreachable) +} +InstructionUnreachable::InstructionUnreachable( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InstructionUnreachable& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, InstructionUnreachable_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InstructionUnreachable* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.InstructionUnreachable) +} + +inline void* PROTOBUF_NONNULL InstructionUnreachable::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InstructionUnreachable(arena); +} +constexpr auto InstructionUnreachable::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(InstructionUnreachable), + alignof(InstructionUnreachable)); +} +constexpr auto InstructionUnreachable::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_InstructionUnreachable_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &InstructionUnreachable::MergeImpl, + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InstructionUnreachable::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &InstructionUnreachable::ByteSizeLong, + &InstructionUnreachable::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InstructionUnreachable, _impl_._cached_size_), + false, + }, + &InstructionUnreachable::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InstructionUnreachable_class_data_ = + InstructionUnreachable::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InstructionUnreachable::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InstructionUnreachable_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InstructionUnreachable_class_data_.tc_table); + return InstructionUnreachable_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 0, 0, 0, 2> +InstructionUnreachable::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 0, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967295, // skipmap + offsetof(decltype(_table_), field_names), // no field_entries + 0, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + InstructionUnreachable_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::InstructionUnreachable>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, // no field_entries, or aux_entries + {{ + }}, +}; + + + + + + + +::google::protobuf::Metadata InstructionUnreachable::GetMetadata() const { + return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class AttributesStructMember::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_._has_bits_); +}; + +AttributesStructMember::AttributesStructMember(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, AttributesStructMember_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.AttributesStructMember) +} +PROTOBUF_NDEBUG_INLINE AttributesStructMember::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::AttributesStructMember& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +AttributesStructMember::AttributesStructMember( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const AttributesStructMember& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, AttributesStructMember_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + AttributesStructMember* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.interpolation_ = ((cached_has_bits & 0x00000001U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.interpolation_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, location_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, location_), + offsetof(Impl_, invariant_) - + offsetof(Impl_, location_) + + sizeof(Impl_::invariant_)); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.AttributesStructMember) +} +PROTOBUF_NDEBUG_INLINE AttributesStructMember::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void AttributesStructMember::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, interpolation_), + 0, + offsetof(Impl_, invariant_) - + offsetof(Impl_, interpolation_) + + sizeof(Impl_::invariant_)); +} +AttributesStructMember::~AttributesStructMember() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.AttributesStructMember) + SharedDtor(*this); +} +inline void AttributesStructMember::SharedDtor(MessageLite& self) { + AttributesStructMember& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.interpolation_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL AttributesStructMember::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) AttributesStructMember(arena); +} +constexpr auto AttributesStructMember::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(AttributesStructMember), + alignof(AttributesStructMember)); +} +constexpr auto AttributesStructMember::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_AttributesStructMember_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &AttributesStructMember::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &AttributesStructMember::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &AttributesStructMember::ByteSizeLong, + &AttributesStructMember::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_._cached_size_), + false, + }, + &AttributesStructMember::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull AttributesStructMember_class_data_ = + AttributesStructMember::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +AttributesStructMember::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&AttributesStructMember_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(AttributesStructMember_class_data_.tc_table); + return AttributesStructMember_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<3, 6, 1, 0, 2> +AttributesStructMember::_table_ = { + { + PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967232, // skipmap + offsetof(decltype(_table_), field_entries), + 6, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + AttributesStructMember_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::AttributesStructMember>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional uint32 location = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesStructMember, _impl_.location_), 1>(), + {8, 1, 0, PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.location_)}}, + // optional uint32 blend_src = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesStructMember, _impl_.blend_src_), 2>(), + {16, 2, 0, PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.blend_src_)}}, + // optional uint32 color = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesStructMember, _impl_.color_), 3>(), + {24, 3, 0, PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.color_)}}, + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesStructMember, _impl_.builtin_), 4>(), + {32, 4, 0, PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.builtin_)}}, + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 5; + {::_pbi::TcParser::FastMtS1, + {42, 0, 0, PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.interpolation_)}}, + // bool invariant = 6; + {::_pbi::TcParser::SingularVarintNoZag1(), + {48, 5, 0, PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.invariant_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional uint32 location = 1; + {PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.location_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 blend_src = 2; + {PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.blend_src_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 color = 3; + {PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.color_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 4; + {PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.builtin_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 5; + {PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.interpolation_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool invariant = 6; + {PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.invariant_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Interpolation>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void AttributesStructMember::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.AttributesStructMember) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000001U) != 0) { + ABSL_DCHECK(_impl_.interpolation_ != nullptr); + _impl_.interpolation_->Clear(); + } + if ((cached_has_bits & 0x0000003eU) != 0) { + ::memset(&_impl_.location_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.invariant_) - + reinterpret_cast(&_impl_.location_)) + sizeof(_impl_.invariant_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL AttributesStructMember::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const AttributesStructMember& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL AttributesStructMember::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const AttributesStructMember& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.AttributesStructMember) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional uint32 location = 1; + if ((cached_has_bits & 0x00000002U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_location(), target); + } + + // optional uint32 blend_src = 2; + if ((cached_has_bits & 0x00000004U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_blend_src(), target); + } + + // optional uint32 color = 3; + if ((cached_has_bits & 0x00000008U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_color(), target); + } + + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 4; + if ((cached_has_bits & 0x00000010U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_builtin(), target); + } + + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 5; + if ((cached_has_bits & 0x00000001U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.interpolation_, this_._impl_.interpolation_->GetCachedSize(), target, + stream); + } + + // bool invariant = 6; + if ((cached_has_bits & 0x00000020U) != 0) { + if (this_._internal_invariant() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_invariant(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.AttributesStructMember) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t AttributesStructMember::ByteSizeLong(const MessageLite& base) { + const AttributesStructMember& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t AttributesStructMember::ByteSizeLong() const { + const AttributesStructMember& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.AttributesStructMember) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x0000003fU) != 0) { + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 5; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.interpolation_); + } + // optional uint32 location = 1; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_location()); + } + // optional uint32 blend_src = 2; + if ((cached_has_bits & 0x00000004U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_blend_src()); + } + // optional uint32 color = 3; + if ((cached_has_bits & 0x00000008U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_color()); + } + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 4; + if ((cached_has_bits & 0x00000010U) != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_builtin()); + } + // bool invariant = 6; + if ((cached_has_bits & 0x00000020U) != 0) { + if (this_._internal_invariant() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void AttributesStructMember::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.AttributesStructMember) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x0000003fU) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + ABSL_DCHECK(from._impl_.interpolation_ != nullptr); + if (_this->_impl_.interpolation_ == nullptr) { + _this->_impl_.interpolation_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.interpolation_); + } else { + _this->_impl_.interpolation_->MergeFrom(*from._impl_.interpolation_); + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + _this->_impl_.location_ = from._impl_.location_; + } + if ((cached_has_bits & 0x00000004U) != 0) { + _this->_impl_.blend_src_ = from._impl_.blend_src_; + } + if ((cached_has_bits & 0x00000008U) != 0) { + _this->_impl_.color_ = from._impl_.color_; + } + if ((cached_has_bits & 0x00000010U) != 0) { + _this->_impl_.builtin_ = from._impl_.builtin_; + } + if ((cached_has_bits & 0x00000020U) != 0) { + if (from._internal_invariant() != 0) { + _this->_impl_.invariant_ = from._impl_.invariant_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void AttributesStructMember::CopyFrom(const AttributesStructMember& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.AttributesStructMember) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void AttributesStructMember::InternalSwap(AttributesStructMember* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.invariant_) + + sizeof(AttributesStructMember::_impl_.invariant_) + - PROTOBUF_FIELD_OFFSET(AttributesStructMember, _impl_.interpolation_)>( + reinterpret_cast(&_impl_.interpolation_), + reinterpret_cast(&other->_impl_.interpolation_)); +} + +::google::protobuf::Metadata AttributesStructMember::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class AttributesFunctionParameter::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_._has_bits_); +}; + +AttributesFunctionParameter::AttributesFunctionParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, AttributesFunctionParameter_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.AttributesFunctionParameter) +} +PROTOBUF_NDEBUG_INLINE AttributesFunctionParameter::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::tint::core::ir::binary::pb::AttributesFunctionParameter& from_msg) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +AttributesFunctionParameter::AttributesFunctionParameter( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const AttributesFunctionParameter& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, AttributesFunctionParameter_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + AttributesFunctionParameter* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.interpolation_ = ((cached_has_bits & 0x00000001U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.interpolation_) + : nullptr; + _impl_.binding_point_ = ((cached_has_bits & 0x00000002U) != 0) + ? ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.binding_point_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, builtin_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, builtin_), + offsetof(Impl_, invariant_) - + offsetof(Impl_, builtin_) + + sizeof(Impl_::invariant_)); + + // @@protoc_insertion_point(copy_constructor:tint.core.ir.binary.pb.AttributesFunctionParameter) +} +PROTOBUF_NDEBUG_INLINE AttributesFunctionParameter::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void AttributesFunctionParameter::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, interpolation_), + 0, + offsetof(Impl_, invariant_) - + offsetof(Impl_, interpolation_) + + sizeof(Impl_::invariant_)); +} +AttributesFunctionParameter::~AttributesFunctionParameter() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.AttributesFunctionParameter) + SharedDtor(*this); +} +inline void AttributesFunctionParameter::SharedDtor(MessageLite& self) { + AttributesFunctionParameter& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.interpolation_; + delete this_._impl_.binding_point_; + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL AttributesFunctionParameter::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) AttributesFunctionParameter(arena); +} +constexpr auto AttributesFunctionParameter::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(AttributesFunctionParameter), + alignof(AttributesFunctionParameter)); +} +constexpr auto AttributesFunctionParameter::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_AttributesFunctionParameter_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &AttributesFunctionParameter::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &AttributesFunctionParameter::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &AttributesFunctionParameter::ByteSizeLong, + &AttributesFunctionParameter::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_._cached_size_), + false, + }, + &AttributesFunctionParameter::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull AttributesFunctionParameter_class_data_ = + AttributesFunctionParameter::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +AttributesFunctionParameter::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&AttributesFunctionParameter_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(AttributesFunctionParameter_class_data_.tc_table); + return AttributesFunctionParameter_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<3, 6, 2, 0, 2> +AttributesFunctionParameter::_table_ = { + { + PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967232, // skipmap + offsetof(decltype(_table_), field_entries), + 6, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + AttributesFunctionParameter_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::AttributesFunctionParameter>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesFunctionParameter, _impl_.builtin_), 2>(), + {8, 2, 0, PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.builtin_)}}, + // optional uint32 location = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesFunctionParameter, _impl_.location_), 3>(), + {16, 3, 0, PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.location_)}}, + // optional uint32 color = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AttributesFunctionParameter, _impl_.color_), 4>(), + {24, 4, 0, PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.color_)}}, + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 4; + {::_pbi::TcParser::FastMtS1, + {34, 0, 0, PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.interpolation_)}}, + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 5; + {::_pbi::TcParser::FastMtS1, + {42, 1, 1, PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.binding_point_)}}, + // bool invariant = 6; + {::_pbi::TcParser::SingularVarintNoZag1(), + {48, 5, 0, PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.invariant_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 1; + {PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.builtin_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // optional uint32 location = 2; + {PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.location_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 color = 3; + {PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.color_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 4; + {PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.interpolation_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 5; + {PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.binding_point_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool invariant = 6; + {PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.invariant_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Interpolation>()}, + {::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::BindingPoint>()}, + }}, + {{ + }}, +}; +PROTOBUF_NOINLINE void AttributesFunctionParameter::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.AttributesFunctionParameter) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + ABSL_DCHECK(_impl_.interpolation_ != nullptr); + _impl_.interpolation_->Clear(); + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(_impl_.binding_point_ != nullptr); + _impl_.binding_point_->Clear(); + } + } + if ((cached_has_bits & 0x0000003cU) != 0) { + ::memset(&_impl_.builtin_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.invariant_) - + reinterpret_cast(&_impl_.builtin_)) + sizeof(_impl_.invariant_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL AttributesFunctionParameter::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const AttributesFunctionParameter& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL AttributesFunctionParameter::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const AttributesFunctionParameter& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.AttributesFunctionParameter) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 1; + if ((cached_has_bits & 0x00000004U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_builtin(), target); + } + + // optional uint32 location = 2; + if ((cached_has_bits & 0x00000008U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 2, this_._internal_location(), target); + } + + // optional uint32 color = 3; + if ((cached_has_bits & 0x00000010U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_color(), target); + } + + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 4; + if ((cached_has_bits & 0x00000001U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.interpolation_, this_._impl_.interpolation_->GetCachedSize(), target, + stream); + } + + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 5; + if ((cached_has_bits & 0x00000002U) != 0) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.binding_point_, this_._impl_.binding_point_->GetCachedSize(), target, + stream); + } + + // bool invariant = 6; + if ((cached_has_bits & 0x00000020U) != 0) { + if (this_._internal_invariant() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_invariant(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.AttributesFunctionParameter) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t AttributesFunctionParameter::ByteSizeLong(const MessageLite& base) { + const AttributesFunctionParameter& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t AttributesFunctionParameter::ByteSizeLong() const { + const AttributesFunctionParameter& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.AttributesFunctionParameter) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x0000003fU) != 0) { + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 4; + if ((cached_has_bits & 0x00000001U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.interpolation_); + } + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 5; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.binding_point_); + } + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 1; + if ((cached_has_bits & 0x00000004U) != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_builtin()); + } + // optional uint32 location = 2; + if ((cached_has_bits & 0x00000008U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_location()); + } + // optional uint32 color = 3; + if ((cached_has_bits & 0x00000010U) != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_color()); + } + // bool invariant = 6; + if ((cached_has_bits & 0x00000020U) != 0) { + if (this_._internal_invariant() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void AttributesFunctionParameter::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.AttributesFunctionParameter) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x0000003fU) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + ABSL_DCHECK(from._impl_.interpolation_ != nullptr); + if (_this->_impl_.interpolation_ == nullptr) { + _this->_impl_.interpolation_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.interpolation_); + } else { + _this->_impl_.interpolation_->MergeFrom(*from._impl_.interpolation_); + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + ABSL_DCHECK(from._impl_.binding_point_ != nullptr); + if (_this->_impl_.binding_point_ == nullptr) { + _this->_impl_.binding_point_ = ::google::protobuf::Message::CopyConstruct(arena, *from._impl_.binding_point_); + } else { + _this->_impl_.binding_point_->MergeFrom(*from._impl_.binding_point_); + } + } + if ((cached_has_bits & 0x00000004U) != 0) { + _this->_impl_.builtin_ = from._impl_.builtin_; + } + if ((cached_has_bits & 0x00000008U) != 0) { + _this->_impl_.location_ = from._impl_.location_; + } + if ((cached_has_bits & 0x00000010U) != 0) { + _this->_impl_.color_ = from._impl_.color_; + } + if ((cached_has_bits & 0x00000020U) != 0) { + if (from._internal_invariant() != 0) { + _this->_impl_.invariant_ = from._impl_.invariant_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void AttributesFunctionParameter::CopyFrom(const AttributesFunctionParameter& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.AttributesFunctionParameter) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void AttributesFunctionParameter::InternalSwap(AttributesFunctionParameter* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.invariant_) + + sizeof(AttributesFunctionParameter::_impl_.invariant_) + - PROTOBUF_FIELD_OFFSET(AttributesFunctionParameter, _impl_.interpolation_)>( + reinterpret_cast(&_impl_.interpolation_), + reinterpret_cast(&other->_impl_.interpolation_)); +} + +::google::protobuf::Metadata AttributesFunctionParameter::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +class Interpolation::_Internal { + public: + using HasBits = + decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Interpolation, _impl_._has_bits_); +}; + +Interpolation::Interpolation(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Interpolation_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:tint.core.ir.binary.pb.Interpolation) +} +Interpolation::Interpolation( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Interpolation& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Interpolation_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE Interpolation::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : _cached_size_{0} {} + +inline void Interpolation::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, type_), + 0, + offsetof(Impl_, sampling_) - + offsetof(Impl_, type_) + + sizeof(Impl_::sampling_)); +} +Interpolation::~Interpolation() { + // @@protoc_insertion_point(destructor:tint.core.ir.binary.pb.Interpolation) + SharedDtor(*this); +} +inline void Interpolation::SharedDtor(MessageLite& self) { + Interpolation& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* PROTOBUF_NONNULL Interpolation::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Interpolation(arena); +} +constexpr auto Interpolation::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Interpolation), + alignof(Interpolation)); +} +constexpr auto Interpolation::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Interpolation_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Interpolation::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Interpolation::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Interpolation::ByteSizeLong, + &Interpolation::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Interpolation, _impl_._cached_size_), + false, + }, + &Interpolation::kDescriptorMethods, + &descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Interpolation_class_data_ = + Interpolation::InternalGenerateClassData_(); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Interpolation::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Interpolation_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Interpolation_class_data_.tc_table); + return Interpolation_class_data_.base(); +} +PROTOBUF_CONSTINIT_WITH_PTR PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 0, 0, 2> +Interpolation::_table_ = { + { + PROTOBUF_FIELD_OFFSET(Interpolation, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + Interpolation_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::tint::core::ir::binary::pb::Interpolation>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // optional .tint.core.ir.binary.pb.InterpolationSampling sampling = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Interpolation, _impl_.sampling_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(Interpolation, _impl_.sampling_)}}, + // .tint.core.ir.binary.pb.InterpolationType type = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Interpolation, _impl_.type_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(Interpolation, _impl_.type_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .tint.core.ir.binary.pb.InterpolationType type = 1; + {PROTOBUF_FIELD_OFFSET(Interpolation, _impl_.type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // optional .tint.core.ir.binary.pb.InterpolationSampling sampling = 2; + {PROTOBUF_FIELD_OFFSET(Interpolation, _impl_.sampling_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + // no aux_entries + {{ + }}, +}; +PROTOBUF_NOINLINE void Interpolation::Clear() { +// @@protoc_insertion_point(message_clear_start:tint.core.ir.binary.pb.Interpolation) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + ::memset(&_impl_.type_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.sampling_) - + reinterpret_cast(&_impl_.type_)) + sizeof(_impl_.sampling_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Interpolation::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Interpolation& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Interpolation::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Interpolation& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + this_.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:tint.core.ir.binary.pb.Interpolation) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .tint.core.ir.binary.pb.InterpolationType type = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_type(), target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .tint.core.ir.binary.pb.InterpolationSampling sampling = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_sampling(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:tint.core.ir.binary.pb.Interpolation) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Interpolation::ByteSizeLong(const MessageLite& base) { + const Interpolation& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Interpolation::ByteSizeLong() const { + const Interpolation& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:tint.core.ir.binary.pb.Interpolation) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + // .tint.core.ir.binary.pb.InterpolationType type = 1; + if ((cached_has_bits & 0x00000001U) != 0) { + if (this_._internal_type() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_type()); + } + } + // optional .tint.core.ir.binary.pb.InterpolationSampling sampling = 2; + if ((cached_has_bits & 0x00000002U) != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_sampling()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Interpolation::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenVerifyHasBitConsistency()) { + from.VerifyHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:tint.core.ir.binary.pb.Interpolation) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if ((cached_has_bits & 0x00000003U) != 0) { + if ((cached_has_bits & 0x00000001U) != 0) { + if (from._internal_type() != 0) { + _this->_impl_.type_ = from._impl_.type_; + } + } + if ((cached_has_bits & 0x00000002U) != 0) { + _this->_impl_.sampling_ = from._impl_.sampling_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Interpolation::CopyFrom(const Interpolation& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:tint.core.ir.binary.pb.Interpolation) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Interpolation::InternalSwap(Interpolation* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Interpolation, _impl_.sampling_) + + sizeof(Interpolation::_impl_.sampling_) + - PROTOBUF_FIELD_OFFSET(Interpolation, _impl_.type_)>( + reinterpret_cast(&_impl_.type_), + reinterpret_cast(&other->_impl_.type_)); +} + +::google::protobuf::Metadata Interpolation::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace pb +} // namespace binary +} // namespace ir +} // namespace core +} // namespace tint +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ [[maybe_unused]] = + (::_pbi::AddDescriptors(&descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto), + ::std::false_type{}); +#include "google/protobuf/port_undef.inc" diff --git a/3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.h b/3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.h new file mode 100644 index 000000000..111ab2044 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/protos/ir/ir.pb.h @@ -0,0 +1,23930 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: src/tint/utils/protos/ir/ir.proto +// Protobuf C++ Version: 6.32.0 + +#ifndef src_2ftint_2futils_2fprotos_2fir_2fir_2eproto_2epb_2eh +#define src_2ftint_2futils_2fprotos_2fir_2fir_2eproto_2epb_2eh + +#include +#include +#include +#include + +#include "google/protobuf/runtime_version.h" +#if PROTOBUF_VERSION != 6032000 +#error "Protobuf C++ gencode is built with an incompatible version of" +#error "Protobuf C++ headers/runtime. See" +#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" +#endif +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_bases.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/generated_enum_reflection.h" +#include "google/protobuf/unknown_field_set.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto + +namespace google { +namespace protobuf { +namespace internal { +template +::absl::string_view GetAnyMessageName(); +} // namespace internal +} // namespace protobuf +} // namespace google + +// Internal implementation detail -- do not use these members. +struct TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto { + static const ::uint32_t offsets[]; +}; +extern "C" { +extern const ::google::protobuf::internal::DescriptorTable descriptor_table_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +} // extern "C" +namespace tint { +namespace core { +namespace ir { +namespace binary { +namespace pb { +enum AccessControl : int; +extern const uint32_t AccessControl_internal_data_[]; +enum AddressSpace : int; +extern const uint32_t AddressSpace_internal_data_[]; +enum BinaryOp : int; +extern const uint32_t BinaryOp_internal_data_[]; +enum BuiltinFn : int; +extern const uint32_t BuiltinFn_internal_data_[]; +enum BuiltinValue : int; +extern const uint32_t BuiltinValue_internal_data_[]; +enum InterpolationSampling : int; +extern const uint32_t InterpolationSampling_internal_data_[]; +enum InterpolationType : int; +extern const uint32_t InterpolationType_internal_data_[]; +enum PipelineStage : int; +extern const uint32_t PipelineStage_internal_data_[]; +enum SamplerKind : int; +extern const uint32_t SamplerKind_internal_data_[]; +enum TexelFormat : int; +extern const uint32_t TexelFormat_internal_data_[]; +enum TextureDimension : int; +extern const uint32_t TextureDimension_internal_data_[]; +enum TypeBasic : int; +extern const uint32_t TypeBasic_internal_data_[]; +enum TypeBuiltinStruct : int; +extern const uint32_t TypeBuiltinStruct_internal_data_[]; +enum UnaryOp : int; +extern const uint32_t UnaryOp_internal_data_[]; +class AttributesFunctionParameter; +struct AttributesFunctionParameterDefaultTypeInternal; +extern AttributesFunctionParameterDefaultTypeInternal _AttributesFunctionParameter_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull AttributesFunctionParameter_class_data_; +class AttributesStructMember; +struct AttributesStructMemberDefaultTypeInternal; +extern AttributesStructMemberDefaultTypeInternal _AttributesStructMember_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull AttributesStructMember_class_data_; +class BindingPoint; +struct BindingPointDefaultTypeInternal; +extern BindingPointDefaultTypeInternal _BindingPoint_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull BindingPoint_class_data_; +class Block; +struct BlockDefaultTypeInternal; +extern BlockDefaultTypeInternal _Block_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Block_class_data_; +class BlockParameter; +struct BlockParameterDefaultTypeInternal; +extern BlockParameterDefaultTypeInternal _BlockParameter_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull BlockParameter_class_data_; +class ConstantValue; +struct ConstantValueDefaultTypeInternal; +extern ConstantValueDefaultTypeInternal _ConstantValue_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull ConstantValue_class_data_; +class ConstantValueComposite; +struct ConstantValueCompositeDefaultTypeInternal; +extern ConstantValueCompositeDefaultTypeInternal _ConstantValueComposite_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull ConstantValueComposite_class_data_; +class ConstantValueScalar; +struct ConstantValueScalarDefaultTypeInternal; +extern ConstantValueScalarDefaultTypeInternal _ConstantValueScalar_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull ConstantValueScalar_class_data_; +class ConstantValueSplat; +struct ConstantValueSplatDefaultTypeInternal; +extern ConstantValueSplatDefaultTypeInternal _ConstantValueSplat_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull ConstantValueSplat_class_data_; +class Function; +struct FunctionDefaultTypeInternal; +extern FunctionDefaultTypeInternal _Function_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Function_class_data_; +class FunctionParameter; +struct FunctionParameterDefaultTypeInternal; +extern FunctionParameterDefaultTypeInternal _FunctionParameter_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull FunctionParameter_class_data_; +class Instruction; +struct InstructionDefaultTypeInternal; +extern InstructionDefaultTypeInternal _Instruction_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Instruction_class_data_; +class InstructionAccess; +struct InstructionAccessDefaultTypeInternal; +extern InstructionAccessDefaultTypeInternal _InstructionAccess_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionAccess_class_data_; +class InstructionBinary; +struct InstructionBinaryDefaultTypeInternal; +extern InstructionBinaryDefaultTypeInternal _InstructionBinary_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionBinary_class_data_; +class InstructionBitcast; +struct InstructionBitcastDefaultTypeInternal; +extern InstructionBitcastDefaultTypeInternal _InstructionBitcast_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionBitcast_class_data_; +class InstructionBreakIf; +struct InstructionBreakIfDefaultTypeInternal; +extern InstructionBreakIfDefaultTypeInternal _InstructionBreakIf_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionBreakIf_class_data_; +class InstructionBuiltinCall; +struct InstructionBuiltinCallDefaultTypeInternal; +extern InstructionBuiltinCallDefaultTypeInternal _InstructionBuiltinCall_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionBuiltinCall_class_data_; +class InstructionConstruct; +struct InstructionConstructDefaultTypeInternal; +extern InstructionConstructDefaultTypeInternal _InstructionConstruct_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionConstruct_class_data_; +class InstructionContinue; +struct InstructionContinueDefaultTypeInternal; +extern InstructionContinueDefaultTypeInternal _InstructionContinue_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionContinue_class_data_; +class InstructionConvert; +struct InstructionConvertDefaultTypeInternal; +extern InstructionConvertDefaultTypeInternal _InstructionConvert_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionConvert_class_data_; +class InstructionDiscard; +struct InstructionDiscardDefaultTypeInternal; +extern InstructionDiscardDefaultTypeInternal _InstructionDiscard_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionDiscard_class_data_; +class InstructionExitIf; +struct InstructionExitIfDefaultTypeInternal; +extern InstructionExitIfDefaultTypeInternal _InstructionExitIf_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionExitIf_class_data_; +class InstructionExitLoop; +struct InstructionExitLoopDefaultTypeInternal; +extern InstructionExitLoopDefaultTypeInternal _InstructionExitLoop_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionExitLoop_class_data_; +class InstructionExitSwitch; +struct InstructionExitSwitchDefaultTypeInternal; +extern InstructionExitSwitchDefaultTypeInternal _InstructionExitSwitch_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionExitSwitch_class_data_; +class InstructionIf; +struct InstructionIfDefaultTypeInternal; +extern InstructionIfDefaultTypeInternal _InstructionIf_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionIf_class_data_; +class InstructionLet; +struct InstructionLetDefaultTypeInternal; +extern InstructionLetDefaultTypeInternal _InstructionLet_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionLet_class_data_; +class InstructionLoad; +struct InstructionLoadDefaultTypeInternal; +extern InstructionLoadDefaultTypeInternal _InstructionLoad_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionLoad_class_data_; +class InstructionLoadVectorElement; +struct InstructionLoadVectorElementDefaultTypeInternal; +extern InstructionLoadVectorElementDefaultTypeInternal _InstructionLoadVectorElement_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionLoadVectorElement_class_data_; +class InstructionLoop; +struct InstructionLoopDefaultTypeInternal; +extern InstructionLoopDefaultTypeInternal _InstructionLoop_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionLoop_class_data_; +class InstructionNextIteration; +struct InstructionNextIterationDefaultTypeInternal; +extern InstructionNextIterationDefaultTypeInternal _InstructionNextIteration_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionNextIteration_class_data_; +class InstructionResult; +struct InstructionResultDefaultTypeInternal; +extern InstructionResultDefaultTypeInternal _InstructionResult_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionResult_class_data_; +class InstructionReturn; +struct InstructionReturnDefaultTypeInternal; +extern InstructionReturnDefaultTypeInternal _InstructionReturn_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionReturn_class_data_; +class InstructionStore; +struct InstructionStoreDefaultTypeInternal; +extern InstructionStoreDefaultTypeInternal _InstructionStore_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionStore_class_data_; +class InstructionStoreVectorElement; +struct InstructionStoreVectorElementDefaultTypeInternal; +extern InstructionStoreVectorElementDefaultTypeInternal _InstructionStoreVectorElement_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionStoreVectorElement_class_data_; +class InstructionSwitch; +struct InstructionSwitchDefaultTypeInternal; +extern InstructionSwitchDefaultTypeInternal _InstructionSwitch_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionSwitch_class_data_; +class InstructionSwizzle; +struct InstructionSwizzleDefaultTypeInternal; +extern InstructionSwizzleDefaultTypeInternal _InstructionSwizzle_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionSwizzle_class_data_; +class InstructionUnary; +struct InstructionUnaryDefaultTypeInternal; +extern InstructionUnaryDefaultTypeInternal _InstructionUnary_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionUnary_class_data_; +class InstructionUnreachable; +struct InstructionUnreachableDefaultTypeInternal; +extern InstructionUnreachableDefaultTypeInternal _InstructionUnreachable_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionUnreachable_class_data_; +class InstructionUserCall; +struct InstructionUserCallDefaultTypeInternal; +extern InstructionUserCallDefaultTypeInternal _InstructionUserCall_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionUserCall_class_data_; +class InstructionVar; +struct InstructionVarDefaultTypeInternal; +extern InstructionVarDefaultTypeInternal _InstructionVar_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull InstructionVar_class_data_; +class Interpolation; +struct InterpolationDefaultTypeInternal; +extern InterpolationDefaultTypeInternal _Interpolation_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Interpolation_class_data_; +class Module; +struct ModuleDefaultTypeInternal; +extern ModuleDefaultTypeInternal _Module_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Module_class_data_; +class SwitchCase; +struct SwitchCaseDefaultTypeInternal; +extern SwitchCaseDefaultTypeInternal _SwitchCase_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull SwitchCase_class_data_; +class Type; +struct TypeDefaultTypeInternal; +extern TypeDefaultTypeInternal _Type_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Type_class_data_; +class TypeArray; +struct TypeArrayDefaultTypeInternal; +extern TypeArrayDefaultTypeInternal _TypeArray_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeArray_class_data_; +class TypeAtomic; +struct TypeAtomicDefaultTypeInternal; +extern TypeAtomicDefaultTypeInternal _TypeAtomic_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeAtomic_class_data_; +class TypeBindingArray; +struct TypeBindingArrayDefaultTypeInternal; +extern TypeBindingArrayDefaultTypeInternal _TypeBindingArray_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeBindingArray_class_data_; +class TypeBuffer; +struct TypeBufferDefaultTypeInternal; +extern TypeBufferDefaultTypeInternal _TypeBuffer_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeBuffer_class_data_; +class TypeDepthMultisampledTexture; +struct TypeDepthMultisampledTextureDefaultTypeInternal; +extern TypeDepthMultisampledTextureDefaultTypeInternal _TypeDepthMultisampledTexture_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeDepthMultisampledTexture_class_data_; +class TypeDepthTexture; +struct TypeDepthTextureDefaultTypeInternal; +extern TypeDepthTextureDefaultTypeInternal _TypeDepthTexture_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeDepthTexture_class_data_; +class TypeExternalTexture; +struct TypeExternalTextureDefaultTypeInternal; +extern TypeExternalTextureDefaultTypeInternal _TypeExternalTexture_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeExternalTexture_class_data_; +class TypeInputAttachment; +struct TypeInputAttachmentDefaultTypeInternal; +extern TypeInputAttachmentDefaultTypeInternal _TypeInputAttachment_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeInputAttachment_class_data_; +class TypeMatrix; +struct TypeMatrixDefaultTypeInternal; +extern TypeMatrixDefaultTypeInternal _TypeMatrix_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeMatrix_class_data_; +class TypeMultisampledTexture; +struct TypeMultisampledTextureDefaultTypeInternal; +extern TypeMultisampledTextureDefaultTypeInternal _TypeMultisampledTexture_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeMultisampledTexture_class_data_; +class TypePointer; +struct TypePointerDefaultTypeInternal; +extern TypePointerDefaultTypeInternal _TypePointer_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypePointer_class_data_; +class TypeResourceBinding; +struct TypeResourceBindingDefaultTypeInternal; +extern TypeResourceBindingDefaultTypeInternal _TypeResourceBinding_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeResourceBinding_class_data_; +class TypeSampledTexture; +struct TypeSampledTextureDefaultTypeInternal; +extern TypeSampledTextureDefaultTypeInternal _TypeSampledTexture_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeSampledTexture_class_data_; +class TypeSampler; +struct TypeSamplerDefaultTypeInternal; +extern TypeSamplerDefaultTypeInternal _TypeSampler_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeSampler_class_data_; +class TypeStorageTexture; +struct TypeStorageTextureDefaultTypeInternal; +extern TypeStorageTextureDefaultTypeInternal _TypeStorageTexture_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeStorageTexture_class_data_; +class TypeStruct; +struct TypeStructDefaultTypeInternal; +extern TypeStructDefaultTypeInternal _TypeStruct_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeStruct_class_data_; +class TypeStructMember; +struct TypeStructMemberDefaultTypeInternal; +extern TypeStructMemberDefaultTypeInternal _TypeStructMember_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeStructMember_class_data_; +class TypeSubgroupMatrix; +struct TypeSubgroupMatrixDefaultTypeInternal; +extern TypeSubgroupMatrixDefaultTypeInternal _TypeSubgroupMatrix_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeSubgroupMatrix_class_data_; +class TypeTexelBuffer; +struct TypeTexelBufferDefaultTypeInternal; +extern TypeTexelBufferDefaultTypeInternal _TypeTexelBuffer_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeTexelBuffer_class_data_; +class TypeVector; +struct TypeVectorDefaultTypeInternal; +extern TypeVectorDefaultTypeInternal _TypeVector_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull TypeVector_class_data_; +class Value; +struct ValueDefaultTypeInternal; +extern ValueDefaultTypeInternal _Value_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull Value_class_data_; +class WorkgroupSize; +struct WorkgroupSizeDefaultTypeInternal; +extern WorkgroupSizeDefaultTypeInternal _WorkgroupSize_default_instance_; +extern const ::google::protobuf::internal::ClassDataFull WorkgroupSize_class_data_; +} // namespace pb +} // namespace binary +} // namespace ir +} // namespace core +} // namespace tint +namespace google { +namespace protobuf { +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::AccessControl_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::AccessControl>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::AddressSpace_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::AddressSpace>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::BinaryOp_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::BinaryOp>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::BuiltinFn_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::BuiltinFn>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::BuiltinValue_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::BuiltinValue>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::InterpolationSampling_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::InterpolationSampling>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::InterpolationType_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::InterpolationType>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::PipelineStage_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::PipelineStage>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::SamplerKind_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::SamplerKind>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::TexelFormat_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::TexelFormat>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::TextureDimension_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::TextureDimension>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::TypeBasic_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::TypeBasic>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::TypeBuiltinStruct_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::TypeBuiltinStruct>; +template <> +internal::EnumTraitsT<::tint::core::ir::binary::pb::UnaryOp_internal_data_> + internal::EnumTraitsImpl::value<::tint::core::ir::binary::pb::UnaryOp>; +} // namespace protobuf +} // namespace google + +namespace tint { +namespace core { +namespace ir { +namespace binary { +namespace pb { +enum TypeBasic : int { + void_ = 0, + bool_ = 1, + i32 = 2, + u32 = 3, + f32 = 4, + f16 = 5, + i8 = 6, + u8 = 7, + TypeBasic_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + TypeBasic_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t TypeBasic_internal_data_[]; +inline constexpr TypeBasic TypeBasic_MIN = + static_cast(0); +inline constexpr TypeBasic TypeBasic_MAX = + static_cast(7); +inline bool TypeBasic_IsValid(int value) { + return 0 <= value && value <= 7; +} +inline constexpr int TypeBasic_ARRAYSIZE = 7 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TypeBasic_descriptor(); +template +const ::std::string& TypeBasic_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to TypeBasic_Name()."); + return TypeBasic_Name(static_cast(value)); +} +template <> +inline const ::std::string& TypeBasic_Name(TypeBasic value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool TypeBasic_Parse( + ::absl::string_view name, TypeBasic* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(TypeBasic_descriptor(), name, + value); +} +enum TypeBuiltinStruct : int { + AtomicCompareExchangeResultI32 = 0, + AtomicCompareExchangeResultU32 = 1, + FrexpResultF16 = 2, + FrexpResultF32 = 3, + FrexpResultVec2F16 = 4, + FrexpResultVec2F32 = 5, + FrexpResultVec3F16 = 6, + FrexpResultVec3F32 = 7, + FrexpResultVec4F16 = 8, + FrexpResultVec4F32 = 9, + ModfResultF16 = 10, + ModfResultF32 = 11, + ModfResultVec2F16 = 12, + ModfResultVec2F32 = 13, + ModfResultVec3F16 = 14, + ModfResultVec3F32 = 15, + ModfResultVec4F16 = 16, + ModfResultVec4F32 = 17, + TypeBuiltinStruct_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + TypeBuiltinStruct_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t TypeBuiltinStruct_internal_data_[]; +inline constexpr TypeBuiltinStruct TypeBuiltinStruct_MIN = + static_cast(0); +inline constexpr TypeBuiltinStruct TypeBuiltinStruct_MAX = + static_cast(17); +inline bool TypeBuiltinStruct_IsValid(int value) { + return 0 <= value && value <= 17; +} +inline constexpr int TypeBuiltinStruct_ARRAYSIZE = 17 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TypeBuiltinStruct_descriptor(); +template +const ::std::string& TypeBuiltinStruct_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to TypeBuiltinStruct_Name()."); + return TypeBuiltinStruct_Name(static_cast(value)); +} +template <> +inline const ::std::string& TypeBuiltinStruct_Name(TypeBuiltinStruct value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool TypeBuiltinStruct_Parse( + ::absl::string_view name, TypeBuiltinStruct* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(TypeBuiltinStruct_descriptor(), name, + value); +} +enum PipelineStage : int { + Compute = 0, + Fragment = 1, + Vertex = 2, + PipelineStage_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + PipelineStage_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t PipelineStage_internal_data_[]; +inline constexpr PipelineStage PipelineStage_MIN = + static_cast(0); +inline constexpr PipelineStage PipelineStage_MAX = + static_cast(2); +inline bool PipelineStage_IsValid(int value) { + return 0 <= value && value <= 2; +} +inline constexpr int PipelineStage_ARRAYSIZE = 2 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL PipelineStage_descriptor(); +template +const ::std::string& PipelineStage_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to PipelineStage_Name()."); + return PipelineStage_Name(static_cast(value)); +} +template <> +inline const ::std::string& PipelineStage_Name(PipelineStage value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool PipelineStage_Parse( + ::absl::string_view name, PipelineStage* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(PipelineStage_descriptor(), name, + value); +} +enum AddressSpace : int { + function = 0, + handle = 1, + pixel_local = 2, + private_ = 3, + immediate = 4, + storage = 5, + uniform = 6, + workgroup = 7, + AddressSpace_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + AddressSpace_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t AddressSpace_internal_data_[]; +inline constexpr AddressSpace AddressSpace_MIN = + static_cast(0); +inline constexpr AddressSpace AddressSpace_MAX = + static_cast(7); +inline bool AddressSpace_IsValid(int value) { + return 0 <= value && value <= 7; +} +inline constexpr int AddressSpace_ARRAYSIZE = 7 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL AddressSpace_descriptor(); +template +const ::std::string& AddressSpace_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to AddressSpace_Name()."); + return AddressSpace_Name(static_cast(value)); +} +template <> +inline const ::std::string& AddressSpace_Name(AddressSpace value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool AddressSpace_Parse( + ::absl::string_view name, AddressSpace* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(AddressSpace_descriptor(), name, + value); +} +enum AccessControl : int { + read = 0, + write = 1, + read_write = 2, + AccessControl_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + AccessControl_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t AccessControl_internal_data_[]; +inline constexpr AccessControl AccessControl_MIN = + static_cast(0); +inline constexpr AccessControl AccessControl_MAX = + static_cast(2); +inline bool AccessControl_IsValid(int value) { + return 0 <= value && value <= 2; +} +inline constexpr int AccessControl_ARRAYSIZE = 2 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL AccessControl_descriptor(); +template +const ::std::string& AccessControl_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to AccessControl_Name()."); + return AccessControl_Name(static_cast(value)); +} +template <> +inline const ::std::string& AccessControl_Name(AccessControl value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool AccessControl_Parse( + ::absl::string_view name, AccessControl* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(AccessControl_descriptor(), name, + value); +} +enum UnaryOp : int { + complement = 0, + negation = 1, + address_of = 2, + indirection = 3, + not_ = 4, + UnaryOp_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + UnaryOp_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t UnaryOp_internal_data_[]; +inline constexpr UnaryOp UnaryOp_MIN = + static_cast(0); +inline constexpr UnaryOp UnaryOp_MAX = + static_cast(4); +inline bool UnaryOp_IsValid(int value) { + return 0 <= value && value <= 4; +} +inline constexpr int UnaryOp_ARRAYSIZE = 4 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL UnaryOp_descriptor(); +template +const ::std::string& UnaryOp_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to UnaryOp_Name()."); + return UnaryOp_Name(static_cast(value)); +} +template <> +inline const ::std::string& UnaryOp_Name(UnaryOp value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool UnaryOp_Parse( + ::absl::string_view name, UnaryOp* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(UnaryOp_descriptor(), name, + value); +} +enum BinaryOp : int { + add_ = 0, + subtract = 1, + multiply = 2, + divide = 3, + modulo = 4, + and_ = 5, + or_ = 6, + xor_ = 7, + equal = 8, + not_equal = 9, + less_than = 10, + greater_than = 11, + less_than_equal = 12, + greater_than_equal = 13, + shift_left = 14, + shift_right = 15, + logical_and = 16, + logical_or = 17, + BinaryOp_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + BinaryOp_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t BinaryOp_internal_data_[]; +inline constexpr BinaryOp BinaryOp_MIN = + static_cast(0); +inline constexpr BinaryOp BinaryOp_MAX = + static_cast(17); +inline bool BinaryOp_IsValid(int value) { + return 0 <= value && value <= 17; +} +inline constexpr int BinaryOp_ARRAYSIZE = 17 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL BinaryOp_descriptor(); +template +const ::std::string& BinaryOp_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to BinaryOp_Name()."); + return BinaryOp_Name(static_cast(value)); +} +template <> +inline const ::std::string& BinaryOp_Name(BinaryOp value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool BinaryOp_Parse( + ::absl::string_view name, BinaryOp* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(BinaryOp_descriptor(), name, + value); +} +enum TextureDimension : int { + _1d = 0, + _2d = 1, + _2d_array = 2, + _3d = 3, + cube = 4, + cube_array = 5, + TextureDimension_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + TextureDimension_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t TextureDimension_internal_data_[]; +inline constexpr TextureDimension TextureDimension_MIN = + static_cast(0); +inline constexpr TextureDimension TextureDimension_MAX = + static_cast(5); +inline bool TextureDimension_IsValid(int value) { + return 0 <= value && value <= 5; +} +inline constexpr int TextureDimension_ARRAYSIZE = 5 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TextureDimension_descriptor(); +template +const ::std::string& TextureDimension_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to TextureDimension_Name()."); + return TextureDimension_Name(static_cast(value)); +} +template <> +inline const ::std::string& TextureDimension_Name(TextureDimension value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool TextureDimension_Parse( + ::absl::string_view name, TextureDimension* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(TextureDimension_descriptor(), name, + value); +} +enum TexelFormat : int { + bgra8_unorm = 0, + r8_unorm = 1, + r32_float = 2, + r32_sint = 3, + r32_uint = 4, + rg32_float = 5, + rg32_sint = 6, + rg32_uint = 7, + rgba16_float = 8, + rgba16_sint = 9, + rgba16_uint = 10, + rgba32_float = 11, + rgba32_sint = 12, + rgba32_uint = 13, + rgba8_sint = 14, + rgba8_snorm = 15, + rgba8_uint = 16, + rgba8_unorm = 17, + r8_snorm = 18, + r8_uint = 19, + r8_sint = 20, + rg8_unorm = 21, + rg8_snorm = 22, + rg8_uint = 23, + rg8_sint = 24, + r16_uint = 25, + r16_sint = 26, + r16_float = 27, + rg16_uint = 28, + rg16_sint = 29, + rg16_float = 30, + rgb10a2_uint = 31, + rgb10a2_unorm = 32, + rg11b10_ufloat = 33, + r16_unorm = 34, + r16_snorm = 35, + rg16_unorm = 36, + rg16_snorm = 37, + rgba16_unorm = 38, + rgba16_snorm = 39, + TexelFormat_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + TexelFormat_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t TexelFormat_internal_data_[]; +inline constexpr TexelFormat TexelFormat_MIN = + static_cast(0); +inline constexpr TexelFormat TexelFormat_MAX = + static_cast(39); +inline bool TexelFormat_IsValid(int value) { + return 0 <= value && value <= 39; +} +inline constexpr int TexelFormat_ARRAYSIZE = 39 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL TexelFormat_descriptor(); +template +const ::std::string& TexelFormat_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to TexelFormat_Name()."); + return TexelFormat_Name(static_cast(value)); +} +template <> +inline const ::std::string& TexelFormat_Name(TexelFormat value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool TexelFormat_Parse( + ::absl::string_view name, TexelFormat* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(TexelFormat_descriptor(), name, + value); +} +enum SamplerKind : int { + sampler = 0, + comparison = 1, + SamplerKind_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + SamplerKind_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t SamplerKind_internal_data_[]; +inline constexpr SamplerKind SamplerKind_MIN = + static_cast(0); +inline constexpr SamplerKind SamplerKind_MAX = + static_cast(1); +inline bool SamplerKind_IsValid(int value) { + return 0 <= value && value <= 1; +} +inline constexpr int SamplerKind_ARRAYSIZE = 1 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL SamplerKind_descriptor(); +template +const ::std::string& SamplerKind_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to SamplerKind_Name()."); + return SamplerKind_Name(static_cast(value)); +} +template <> +inline const ::std::string& SamplerKind_Name(SamplerKind value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool SamplerKind_Parse( + ::absl::string_view name, SamplerKind* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(SamplerKind_descriptor(), name, + value); +} +enum InterpolationType : int { + flat = 0, + linear = 1, + perspective = 2, + InterpolationType_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + InterpolationType_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t InterpolationType_internal_data_[]; +inline constexpr InterpolationType InterpolationType_MIN = + static_cast(0); +inline constexpr InterpolationType InterpolationType_MAX = + static_cast(2); +inline bool InterpolationType_IsValid(int value) { + return 0 <= value && value <= 2; +} +inline constexpr int InterpolationType_ARRAYSIZE = 2 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL InterpolationType_descriptor(); +template +const ::std::string& InterpolationType_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to InterpolationType_Name()."); + return InterpolationType_Name(static_cast(value)); +} +template <> +inline const ::std::string& InterpolationType_Name(InterpolationType value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool InterpolationType_Parse( + ::absl::string_view name, InterpolationType* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(InterpolationType_descriptor(), name, + value); +} +enum InterpolationSampling : int { + center = 0, + centroid = 1, + sample = 2, + first = 3, + either = 4, + InterpolationSampling_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + InterpolationSampling_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t InterpolationSampling_internal_data_[]; +inline constexpr InterpolationSampling InterpolationSampling_MIN = + static_cast(0); +inline constexpr InterpolationSampling InterpolationSampling_MAX = + static_cast(4); +inline bool InterpolationSampling_IsValid(int value) { + return 0 <= value && value <= 4; +} +inline constexpr int InterpolationSampling_ARRAYSIZE = 4 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL InterpolationSampling_descriptor(); +template +const ::std::string& InterpolationSampling_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to InterpolationSampling_Name()."); + return InterpolationSampling_Name(static_cast(value)); +} +template <> +inline const ::std::string& InterpolationSampling_Name(InterpolationSampling value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool InterpolationSampling_Parse( + ::absl::string_view name, InterpolationSampling* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(InterpolationSampling_descriptor(), name, + value); +} +enum BuiltinValue : int { + point_size = 0, + frag_depth = 1, + front_facing = 2, + global_invocation_id = 3, + instance_index = 4, + local_invocation_id = 5, + local_invocation_index = 6, + num_workgroups = 7, + position = 8, + sample_index = 9, + sample_mask = 10, + subgroup_invocation_id = 11, + subgroup_size = 12, + vertex_index = 13, + workgroup_id = 14, + clip_distances = 15, + cull_distance = 16, + subgroup_id = 17, + primitive_index = 18, + barycentric_coord = 19, + num_subgroups = 20, + BuiltinValue_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + BuiltinValue_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t BuiltinValue_internal_data_[]; +inline constexpr BuiltinValue BuiltinValue_MIN = + static_cast(0); +inline constexpr BuiltinValue BuiltinValue_MAX = + static_cast(20); +inline bool BuiltinValue_IsValid(int value) { + return 0 <= value && value <= 20; +} +inline constexpr int BuiltinValue_ARRAYSIZE = 20 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL BuiltinValue_descriptor(); +template +const ::std::string& BuiltinValue_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to BuiltinValue_Name()."); + return BuiltinValue_Name(static_cast(value)); +} +template <> +inline const ::std::string& BuiltinValue_Name(BuiltinValue value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool BuiltinValue_Parse( + ::absl::string_view name, BuiltinValue* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(BuiltinValue_descriptor(), name, + value); +} +enum BuiltinFn : int { + abs = 0, + acos = 1, + acosh = 2, + all = 3, + any = 4, + array_length = 5, + asin = 6, + asinh = 7, + atan = 8, + atan2 = 9, + atanh = 10, + ceil = 11, + clamp = 12, + cos = 13, + cosh = 14, + count_leading_zeros = 15, + count_one_bits = 16, + count_trailing_zeros = 17, + cross = 18, + degrees = 19, + determinant = 20, + distance = 21, + dot = 22, + dot4i8_packed = 23, + dot4u8_packed = 24, + dpdx = 25, + dpdx_coarse = 26, + dpdx_fine = 27, + dpdy = 28, + dpdy_coarse = 29, + dpdy_fine = 30, + exp = 31, + exp2 = 32, + extract_bits = 33, + face_forward = 34, + first_leading_bit = 35, + first_trailing_bit = 36, + floor = 37, + fma = 38, + fract = 39, + frexp = 40, + fwidth = 41, + fwidth_coarse = 42, + fwidth_fine = 43, + insert_bits = 44, + inverse_sqrt = 45, + ldexp = 46, + length = 47, + log = 48, + log2 = 49, + max = 50, + min = 51, + mix = 52, + modf = 53, + normalize = 54, + pack2x16_float = 55, + pack2x16_snorm = 56, + pack2x16_unorm = 57, + pack4x8_snorm = 58, + pack4x8_unorm = 59, + pack4xi8 = 60, + pack4xu8 = 61, + pack4xi8_clamp = 62, + pack4xu8_clamp = 63, + pow = 64, + quantize_to_f16 = 65, + radians = 66, + reflect = 67, + refract = 68, + reverse_bits = 69, + round = 70, + saturate = 71, + select = 72, + sign = 73, + sin = 74, + sinh = 75, + smoothstep = 76, + sqrt = 77, + step = 78, + storage_barrier = 79, + tan = 80, + tanh = 81, + transpose = 82, + trunc = 83, + unpack2x16_float = 84, + unpack2x16_snorm = 85, + unpack2x16_unorm = 86, + unpack4x8_snorm = 87, + unpack4x8_unorm = 88, + unpack4xi8 = 89, + unpack4xu8 = 90, + workgroup_barrier = 91, + texture_barrier = 92, + texture_dimensions = 93, + texture_gather = 94, + texture_gather_compare = 95, + texture_num_layers = 96, + texture_num_levels = 97, + texture_num_samples = 98, + texture_sample = 99, + texture_sample_bias = 100, + texture_sample_compare = 101, + texture_sample_compare_level = 102, + texture_sample_grad = 103, + texture_sample_level = 104, + texture_sample_base_clamp_to_edge = 105, + texture_store = 106, + texture_load = 107, + atomic_load = 108, + atomic_store = 109, + atomic_add = 110, + atomic_sub = 111, + atomic_max = 112, + atomic_min = 113, + atomic_and = 114, + atomic_or = 115, + atomic_xor = 116, + atomic_exchange = 117, + atomic_compare_exchange_weak = 118, + subgroup_ballot = 119, + subgroup_broadcast = 120, + input_attachment_load = 121, + subgroup_add = 122, + subgroup_exclusive_add = 123, + subgroup_mul = 124, + subgroup_exclusive_mul = 125, + subgroup_and = 126, + subgroup_or = 127, + subgroup_xor = 128, + subgroup_min = 129, + subgroup_max = 130, + subgroup_any = 131, + subgroup_all = 132, + subgroup_elect = 133, + subgroup_broadcast_first = 134, + subgroup_shuffle = 135, + subgroup_shuffle_xor = 136, + subgroup_shuffle_up = 137, + subgroup_shuffle_down = 138, + quad_broadcast = 139, + quad_swap_x = 140, + quad_swap_y = 141, + quad_swap_diagonal = 142, + subgroup_inclusive_add = 143, + subgroup_inclusive_mul = 144, + subgroup_matrix_load = 145, + subgroup_matrix_store = 146, + subgroup_matrix_multiply = 147, + subgroup_matrix_multiply_accumulate = 148, + print = 149, + subgroup_matrix_scalar_add = 152, + subgroup_matrix_scalar_multiply = 153, + subgroup_matrix_scalar_subtract = 154, + has_resource = 155, + get_resource = 156, + buffer_view = 157, + buffer_length = 158, + BuiltinFn_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + BuiltinFn_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t BuiltinFn_internal_data_[]; +inline constexpr BuiltinFn BuiltinFn_MIN = + static_cast(0); +inline constexpr BuiltinFn BuiltinFn_MAX = + static_cast(158); +inline bool BuiltinFn_IsValid(int value) { + return ::google::protobuf::internal::ValidateEnum(value, BuiltinFn_internal_data_); +} +inline constexpr int BuiltinFn_ARRAYSIZE = 158 + 1; +const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL BuiltinFn_descriptor(); +template +const ::std::string& BuiltinFn_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to BuiltinFn_Name()."); + return BuiltinFn_Name(static_cast(value)); +} +template <> +inline const ::std::string& BuiltinFn_Name(BuiltinFn value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +inline bool BuiltinFn_Parse( + ::absl::string_view name, BuiltinFn* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(BuiltinFn_descriptor(), name, + value); +} + +// =================================================================== + + +// ------------------------------------------------------------------- + +class WorkgroupSize final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.WorkgroupSize) */ { + public: + inline WorkgroupSize() : WorkgroupSize(nullptr) {} + ~WorkgroupSize() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(WorkgroupSize* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(WorkgroupSize)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR WorkgroupSize(::google::protobuf::internal::ConstantInitialized); + + inline WorkgroupSize(const WorkgroupSize& from) : WorkgroupSize(nullptr, from) {} + inline WorkgroupSize(WorkgroupSize&& from) noexcept + : WorkgroupSize(nullptr, ::std::move(from)) {} + inline WorkgroupSize& operator=(const WorkgroupSize& from) { + CopyFrom(from); + return *this; + } + inline WorkgroupSize& operator=(WorkgroupSize&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const WorkgroupSize& default_instance() { + return *reinterpret_cast( + &_WorkgroupSize_default_instance_); + } + static constexpr int kIndexInFileMessages = 31; + friend void swap(WorkgroupSize& a, WorkgroupSize& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(WorkgroupSize* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(WorkgroupSize* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + WorkgroupSize* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const WorkgroupSize& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const WorkgroupSize& from) { WorkgroupSize::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(WorkgroupSize* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.WorkgroupSize"; } + + protected: + explicit WorkgroupSize(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + WorkgroupSize(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const WorkgroupSize& from); + WorkgroupSize( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, WorkgroupSize&& from) noexcept + : WorkgroupSize(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kXFieldNumber = 1, + kYFieldNumber = 2, + kZFieldNumber = 3, + }; + // uint32 x = 1; + void clear_x() ; + ::uint32_t x() const; + void set_x(::uint32_t value); + + private: + ::uint32_t _internal_x() const; + void _internal_set_x(::uint32_t value); + + public: + // uint32 y = 2; + void clear_y() ; + ::uint32_t y() const; + void set_y(::uint32_t value); + + private: + ::uint32_t _internal_y() const; + void _internal_set_y(::uint32_t value); + + public: + // uint32 z = 3; + void clear_z() ; + ::uint32_t z() const; + void set_z(::uint32_t value); + + private: + ::uint32_t _internal_z() const; + void _internal_set_z(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.WorkgroupSize) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const WorkgroupSize& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t x_; + ::uint32_t y_; + ::uint32_t z_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull WorkgroupSize_class_data_; +// ------------------------------------------------------------------- + +class TypeVector final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeVector) */ { + public: + inline TypeVector() : TypeVector(nullptr) {} + ~TypeVector() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeVector* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeVector)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeVector(::google::protobuf::internal::ConstantInitialized); + + inline TypeVector(const TypeVector& from) : TypeVector(nullptr, from) {} + inline TypeVector(TypeVector&& from) noexcept + : TypeVector(nullptr, ::std::move(from)) {} + inline TypeVector& operator=(const TypeVector& from) { + CopyFrom(from); + return *this; + } + inline TypeVector& operator=(TypeVector&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeVector& default_instance() { + return *reinterpret_cast( + &_TypeVector_default_instance_); + } + static constexpr int kIndexInFileMessages = 2; + friend void swap(TypeVector& a, TypeVector& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeVector* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeVector* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeVector* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeVector& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeVector& from) { TypeVector::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeVector* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeVector"; } + + protected: + explicit TypeVector(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeVector(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeVector& from); + TypeVector( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeVector&& from) noexcept + : TypeVector(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kWidthFieldNumber = 1, + kElementTypeFieldNumber = 2, + }; + // uint32 width = 1; + void clear_width() ; + ::uint32_t width() const; + void set_width(::uint32_t value); + + private: + ::uint32_t _internal_width() const; + void _internal_set_width(::uint32_t value); + + public: + // uint32 element_type = 2; + void clear_element_type() ; + ::uint32_t element_type() const; + void set_element_type(::uint32_t value); + + private: + ::uint32_t _internal_element_type() const; + void _internal_set_element_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeVector) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeVector& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t width_; + ::uint32_t element_type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeVector_class_data_; +// ------------------------------------------------------------------- + +class TypeTexelBuffer final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeTexelBuffer) */ { + public: + inline TypeTexelBuffer() : TypeTexelBuffer(nullptr) {} + ~TypeTexelBuffer() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeTexelBuffer* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeTexelBuffer)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeTexelBuffer(::google::protobuf::internal::ConstantInitialized); + + inline TypeTexelBuffer(const TypeTexelBuffer& from) : TypeTexelBuffer(nullptr, from) {} + inline TypeTexelBuffer(TypeTexelBuffer&& from) noexcept + : TypeTexelBuffer(nullptr, ::std::move(from)) {} + inline TypeTexelBuffer& operator=(const TypeTexelBuffer& from) { + CopyFrom(from); + return *this; + } + inline TypeTexelBuffer& operator=(TypeTexelBuffer&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeTexelBuffer& default_instance() { + return *reinterpret_cast( + &_TypeTexelBuffer_default_instance_); + } + static constexpr int kIndexInFileMessages = 21; + friend void swap(TypeTexelBuffer& a, TypeTexelBuffer& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeTexelBuffer* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeTexelBuffer* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeTexelBuffer* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeTexelBuffer& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeTexelBuffer& from) { TypeTexelBuffer::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeTexelBuffer* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeTexelBuffer"; } + + protected: + explicit TypeTexelBuffer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeTexelBuffer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeTexelBuffer& from); + TypeTexelBuffer( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeTexelBuffer&& from) noexcept + : TypeTexelBuffer(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kTexelFormatFieldNumber = 1, + kAccessFieldNumber = 2, + }; + // .tint.core.ir.binary.pb.TexelFormat texel_format = 1; + void clear_texel_format() ; + ::tint::core::ir::binary::pb::TexelFormat texel_format() const; + void set_texel_format(::tint::core::ir::binary::pb::TexelFormat value); + + private: + ::tint::core::ir::binary::pb::TexelFormat _internal_texel_format() const; + void _internal_set_texel_format(::tint::core::ir::binary::pb::TexelFormat value); + + public: + // .tint.core.ir.binary.pb.AccessControl access = 2; + void clear_access() ; + ::tint::core::ir::binary::pb::AccessControl access() const; + void set_access(::tint::core::ir::binary::pb::AccessControl value); + + private: + ::tint::core::ir::binary::pb::AccessControl _internal_access() const; + void _internal_set_access(::tint::core::ir::binary::pb::AccessControl value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeTexelBuffer) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeTexelBuffer& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int texel_format_; + int access_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeTexelBuffer_class_data_; +// ------------------------------------------------------------------- + +class TypeSubgroupMatrix final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeSubgroupMatrix) */ { + public: + inline TypeSubgroupMatrix() : TypeSubgroupMatrix(nullptr) {} + ~TypeSubgroupMatrix() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeSubgroupMatrix* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeSubgroupMatrix)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeSubgroupMatrix(::google::protobuf::internal::ConstantInitialized); + + inline TypeSubgroupMatrix(const TypeSubgroupMatrix& from) : TypeSubgroupMatrix(nullptr, from) {} + inline TypeSubgroupMatrix(TypeSubgroupMatrix&& from) noexcept + : TypeSubgroupMatrix(nullptr, ::std::move(from)) {} + inline TypeSubgroupMatrix& operator=(const TypeSubgroupMatrix& from) { + CopyFrom(from); + return *this; + } + inline TypeSubgroupMatrix& operator=(TypeSubgroupMatrix&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeSubgroupMatrix& default_instance() { + return *reinterpret_cast( + &_TypeSubgroupMatrix_default_instance_); + } + static constexpr int kIndexInFileMessages = 19; + friend void swap(TypeSubgroupMatrix& a, TypeSubgroupMatrix& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeSubgroupMatrix* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeSubgroupMatrix* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeSubgroupMatrix* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeSubgroupMatrix& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeSubgroupMatrix& from) { TypeSubgroupMatrix::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeSubgroupMatrix* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeSubgroupMatrix"; } + + protected: + explicit TypeSubgroupMatrix(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeSubgroupMatrix(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeSubgroupMatrix& from); + TypeSubgroupMatrix( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeSubgroupMatrix&& from) noexcept + : TypeSubgroupMatrix(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kSubTypeFieldNumber = 1, + kRowsFieldNumber = 2, + kColumnsFieldNumber = 3, + }; + // uint32 sub_type = 1; + void clear_sub_type() ; + ::uint32_t sub_type() const; + void set_sub_type(::uint32_t value); + + private: + ::uint32_t _internal_sub_type() const; + void _internal_set_sub_type(::uint32_t value); + + public: + // uint32 rows = 2; + void clear_rows() ; + ::uint32_t rows() const; + void set_rows(::uint32_t value); + + private: + ::uint32_t _internal_rows() const; + void _internal_set_rows(::uint32_t value); + + public: + // uint32 columns = 3; + void clear_columns() ; + ::uint32_t columns() const; + void set_columns(::uint32_t value); + + private: + ::uint32_t _internal_columns() const; + void _internal_set_columns(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeSubgroupMatrix) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeSubgroupMatrix& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t sub_type_; + ::uint32_t rows_; + ::uint32_t columns_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeSubgroupMatrix_class_data_; +// ------------------------------------------------------------------- + +class TypeStorageTexture final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeStorageTexture) */ { + public: + inline TypeStorageTexture() : TypeStorageTexture(nullptr) {} + ~TypeStorageTexture() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeStorageTexture* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeStorageTexture)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeStorageTexture(::google::protobuf::internal::ConstantInitialized); + + inline TypeStorageTexture(const TypeStorageTexture& from) : TypeStorageTexture(nullptr, from) {} + inline TypeStorageTexture(TypeStorageTexture&& from) noexcept + : TypeStorageTexture(nullptr, ::std::move(from)) {} + inline TypeStorageTexture& operator=(const TypeStorageTexture& from) { + CopyFrom(from); + return *this; + } + inline TypeStorageTexture& operator=(TypeStorageTexture&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeStorageTexture& default_instance() { + return *reinterpret_cast( + &_TypeStorageTexture_default_instance_); + } + static constexpr int kIndexInFileMessages = 14; + friend void swap(TypeStorageTexture& a, TypeStorageTexture& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeStorageTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeStorageTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeStorageTexture* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeStorageTexture& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeStorageTexture& from) { TypeStorageTexture::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeStorageTexture* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeStorageTexture"; } + + protected: + explicit TypeStorageTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeStorageTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeStorageTexture& from); + TypeStorageTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeStorageTexture&& from) noexcept + : TypeStorageTexture(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDimensionFieldNumber = 1, + kTexelFormatFieldNumber = 2, + kAccessFieldNumber = 3, + }; + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + void clear_dimension() ; + ::tint::core::ir::binary::pb::TextureDimension dimension() const; + void set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + private: + ::tint::core::ir::binary::pb::TextureDimension _internal_dimension() const; + void _internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + public: + // .tint.core.ir.binary.pb.TexelFormat texel_format = 2; + void clear_texel_format() ; + ::tint::core::ir::binary::pb::TexelFormat texel_format() const; + void set_texel_format(::tint::core::ir::binary::pb::TexelFormat value); + + private: + ::tint::core::ir::binary::pb::TexelFormat _internal_texel_format() const; + void _internal_set_texel_format(::tint::core::ir::binary::pb::TexelFormat value); + + public: + // .tint.core.ir.binary.pb.AccessControl access = 3; + void clear_access() ; + ::tint::core::ir::binary::pb::AccessControl access() const; + void set_access(::tint::core::ir::binary::pb::AccessControl value); + + private: + ::tint::core::ir::binary::pb::AccessControl _internal_access() const; + void _internal_set_access(::tint::core::ir::binary::pb::AccessControl value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeStorageTexture) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeStorageTexture& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int dimension_; + int texel_format_; + int access_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeStorageTexture_class_data_; +// ------------------------------------------------------------------- + +class TypeSampler final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeSampler) */ { + public: + inline TypeSampler() : TypeSampler(nullptr) {} + ~TypeSampler() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeSampler* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeSampler)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeSampler(::google::protobuf::internal::ConstantInitialized); + + inline TypeSampler(const TypeSampler& from) : TypeSampler(nullptr, from) {} + inline TypeSampler(TypeSampler&& from) noexcept + : TypeSampler(nullptr, ::std::move(from)) {} + inline TypeSampler& operator=(const TypeSampler& from) { + CopyFrom(from); + return *this; + } + inline TypeSampler& operator=(TypeSampler&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeSampler& default_instance() { + return *reinterpret_cast( + &_TypeSampler_default_instance_); + } + static constexpr int kIndexInFileMessages = 17; + friend void swap(TypeSampler& a, TypeSampler& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeSampler* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeSampler* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeSampler* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeSampler& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeSampler& from) { TypeSampler::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeSampler* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeSampler"; } + + protected: + explicit TypeSampler(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeSampler(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeSampler& from); + TypeSampler( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeSampler&& from) noexcept + : TypeSampler(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kKindFieldNumber = 1, + }; + // .tint.core.ir.binary.pb.SamplerKind kind = 1; + void clear_kind() ; + ::tint::core::ir::binary::pb::SamplerKind kind() const; + void set_kind(::tint::core::ir::binary::pb::SamplerKind value); + + private: + ::tint::core::ir::binary::pb::SamplerKind _internal_kind() const; + void _internal_set_kind(::tint::core::ir::binary::pb::SamplerKind value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeSampler) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeSampler& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int kind_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeSampler_class_data_; +// ------------------------------------------------------------------- + +class TypeSampledTexture final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeSampledTexture) */ { + public: + inline TypeSampledTexture() : TypeSampledTexture(nullptr) {} + ~TypeSampledTexture() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeSampledTexture* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeSampledTexture)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeSampledTexture(::google::protobuf::internal::ConstantInitialized); + + inline TypeSampledTexture(const TypeSampledTexture& from) : TypeSampledTexture(nullptr, from) {} + inline TypeSampledTexture(TypeSampledTexture&& from) noexcept + : TypeSampledTexture(nullptr, ::std::move(from)) {} + inline TypeSampledTexture& operator=(const TypeSampledTexture& from) { + CopyFrom(from); + return *this; + } + inline TypeSampledTexture& operator=(TypeSampledTexture&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeSampledTexture& default_instance() { + return *reinterpret_cast( + &_TypeSampledTexture_default_instance_); + } + static constexpr int kIndexInFileMessages = 11; + friend void swap(TypeSampledTexture& a, TypeSampledTexture& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeSampledTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeSampledTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeSampledTexture* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeSampledTexture& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeSampledTexture& from) { TypeSampledTexture::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeSampledTexture* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeSampledTexture"; } + + protected: + explicit TypeSampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeSampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeSampledTexture& from); + TypeSampledTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeSampledTexture&& from) noexcept + : TypeSampledTexture(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDimensionFieldNumber = 1, + kSubTypeFieldNumber = 2, + }; + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + void clear_dimension() ; + ::tint::core::ir::binary::pb::TextureDimension dimension() const; + void set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + private: + ::tint::core::ir::binary::pb::TextureDimension _internal_dimension() const; + void _internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + public: + // uint32 sub_type = 2; + void clear_sub_type() ; + ::uint32_t sub_type() const; + void set_sub_type(::uint32_t value); + + private: + ::uint32_t _internal_sub_type() const; + void _internal_set_sub_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeSampledTexture) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeSampledTexture& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int dimension_; + ::uint32_t sub_type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeSampledTexture_class_data_; +// ------------------------------------------------------------------- + +class TypeResourceBinding final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeResourceBinding) */ { + public: + inline TypeResourceBinding() : TypeResourceBinding(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeResourceBinding* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeResourceBinding)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeResourceBinding(::google::protobuf::internal::ConstantInitialized); + + inline TypeResourceBinding(const TypeResourceBinding& from) : TypeResourceBinding(nullptr, from) {} + inline TypeResourceBinding(TypeResourceBinding&& from) noexcept + : TypeResourceBinding(nullptr, ::std::move(from)) {} + inline TypeResourceBinding& operator=(const TypeResourceBinding& from) { + CopyFrom(from); + return *this; + } + inline TypeResourceBinding& operator=(TypeResourceBinding&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeResourceBinding& default_instance() { + return *reinterpret_cast( + &_TypeResourceBinding_default_instance_); + } + static constexpr int kIndexInFileMessages = 15; + friend void swap(TypeResourceBinding& a, TypeResourceBinding& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeResourceBinding* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeResourceBinding* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeResourceBinding* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const TypeResourceBinding& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const TypeResourceBinding& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeResourceBinding"; } + + protected: + explicit TypeResourceBinding(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeResourceBinding(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeResourceBinding& from); + TypeResourceBinding( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeResourceBinding&& from) noexcept + : TypeResourceBinding(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeResourceBinding) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeResourceBinding_class_data_; +// ------------------------------------------------------------------- + +class TypePointer final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypePointer) */ { + public: + inline TypePointer() : TypePointer(nullptr) {} + ~TypePointer() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypePointer* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypePointer)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypePointer(::google::protobuf::internal::ConstantInitialized); + + inline TypePointer(const TypePointer& from) : TypePointer(nullptr, from) {} + inline TypePointer(TypePointer&& from) noexcept + : TypePointer(nullptr, ::std::move(from)) {} + inline TypePointer& operator=(const TypePointer& from) { + CopyFrom(from); + return *this; + } + inline TypePointer& operator=(TypePointer&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypePointer& default_instance() { + return *reinterpret_cast( + &_TypePointer_default_instance_); + } + static constexpr int kIndexInFileMessages = 6; + friend void swap(TypePointer& a, TypePointer& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypePointer* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypePointer* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypePointer* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypePointer& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypePointer& from) { TypePointer::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypePointer* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypePointer"; } + + protected: + explicit TypePointer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypePointer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypePointer& from); + TypePointer( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypePointer&& from) noexcept + : TypePointer(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAddressSpaceFieldNumber = 1, + kStoreTypeFieldNumber = 2, + kAccessFieldNumber = 3, + }; + // .tint.core.ir.binary.pb.AddressSpace address_space = 1; + void clear_address_space() ; + ::tint::core::ir::binary::pb::AddressSpace address_space() const; + void set_address_space(::tint::core::ir::binary::pb::AddressSpace value); + + private: + ::tint::core::ir::binary::pb::AddressSpace _internal_address_space() const; + void _internal_set_address_space(::tint::core::ir::binary::pb::AddressSpace value); + + public: + // uint32 store_type = 2; + void clear_store_type() ; + ::uint32_t store_type() const; + void set_store_type(::uint32_t value); + + private: + ::uint32_t _internal_store_type() const; + void _internal_set_store_type(::uint32_t value); + + public: + // .tint.core.ir.binary.pb.AccessControl access = 3; + void clear_access() ; + ::tint::core::ir::binary::pb::AccessControl access() const; + void set_access(::tint::core::ir::binary::pb::AccessControl value); + + private: + ::tint::core::ir::binary::pb::AccessControl _internal_access() const; + void _internal_set_access(::tint::core::ir::binary::pb::AccessControl value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypePointer) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypePointer& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int address_space_; + ::uint32_t store_type_; + int access_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypePointer_class_data_; +// ------------------------------------------------------------------- + +class TypeMultisampledTexture final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeMultisampledTexture) */ { + public: + inline TypeMultisampledTexture() : TypeMultisampledTexture(nullptr) {} + ~TypeMultisampledTexture() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeMultisampledTexture* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeMultisampledTexture)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeMultisampledTexture(::google::protobuf::internal::ConstantInitialized); + + inline TypeMultisampledTexture(const TypeMultisampledTexture& from) : TypeMultisampledTexture(nullptr, from) {} + inline TypeMultisampledTexture(TypeMultisampledTexture&& from) noexcept + : TypeMultisampledTexture(nullptr, ::std::move(from)) {} + inline TypeMultisampledTexture& operator=(const TypeMultisampledTexture& from) { + CopyFrom(from); + return *this; + } + inline TypeMultisampledTexture& operator=(TypeMultisampledTexture&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeMultisampledTexture& default_instance() { + return *reinterpret_cast( + &_TypeMultisampledTexture_default_instance_); + } + static constexpr int kIndexInFileMessages = 12; + friend void swap(TypeMultisampledTexture& a, TypeMultisampledTexture& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeMultisampledTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeMultisampledTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeMultisampledTexture* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeMultisampledTexture& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeMultisampledTexture& from) { TypeMultisampledTexture::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeMultisampledTexture* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeMultisampledTexture"; } + + protected: + explicit TypeMultisampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeMultisampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeMultisampledTexture& from); + TypeMultisampledTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeMultisampledTexture&& from) noexcept + : TypeMultisampledTexture(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDimensionFieldNumber = 1, + kSubTypeFieldNumber = 2, + }; + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + void clear_dimension() ; + ::tint::core::ir::binary::pb::TextureDimension dimension() const; + void set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + private: + ::tint::core::ir::binary::pb::TextureDimension _internal_dimension() const; + void _internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + public: + // uint32 sub_type = 2; + void clear_sub_type() ; + ::uint32_t sub_type() const; + void set_sub_type(::uint32_t value); + + private: + ::uint32_t _internal_sub_type() const; + void _internal_set_sub_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeMultisampledTexture) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeMultisampledTexture& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int dimension_; + ::uint32_t sub_type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeMultisampledTexture_class_data_; +// ------------------------------------------------------------------- + +class TypeMatrix final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeMatrix) */ { + public: + inline TypeMatrix() : TypeMatrix(nullptr) {} + ~TypeMatrix() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeMatrix* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeMatrix)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeMatrix(::google::protobuf::internal::ConstantInitialized); + + inline TypeMatrix(const TypeMatrix& from) : TypeMatrix(nullptr, from) {} + inline TypeMatrix(TypeMatrix&& from) noexcept + : TypeMatrix(nullptr, ::std::move(from)) {} + inline TypeMatrix& operator=(const TypeMatrix& from) { + CopyFrom(from); + return *this; + } + inline TypeMatrix& operator=(TypeMatrix&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeMatrix& default_instance() { + return *reinterpret_cast( + &_TypeMatrix_default_instance_); + } + static constexpr int kIndexInFileMessages = 3; + friend void swap(TypeMatrix& a, TypeMatrix& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeMatrix* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeMatrix* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeMatrix* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeMatrix& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeMatrix& from) { TypeMatrix::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeMatrix* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeMatrix"; } + + protected: + explicit TypeMatrix(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeMatrix(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeMatrix& from); + TypeMatrix( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeMatrix&& from) noexcept + : TypeMatrix(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kNumColumnsFieldNumber = 1, + kNumRowsFieldNumber = 2, + kElementTypeFieldNumber = 3, + }; + // uint32 num_columns = 1; + void clear_num_columns() ; + ::uint32_t num_columns() const; + void set_num_columns(::uint32_t value); + + private: + ::uint32_t _internal_num_columns() const; + void _internal_set_num_columns(::uint32_t value); + + public: + // uint32 num_rows = 2; + void clear_num_rows() ; + ::uint32_t num_rows() const; + void set_num_rows(::uint32_t value); + + private: + ::uint32_t _internal_num_rows() const; + void _internal_set_num_rows(::uint32_t value); + + public: + // uint32 element_type = 3; + void clear_element_type() ; + ::uint32_t element_type() const; + void set_element_type(::uint32_t value); + + private: + ::uint32_t _internal_element_type() const; + void _internal_set_element_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeMatrix) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeMatrix& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t num_columns_; + ::uint32_t num_rows_; + ::uint32_t element_type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeMatrix_class_data_; +// ------------------------------------------------------------------- + +class TypeInputAttachment final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeInputAttachment) */ { + public: + inline TypeInputAttachment() : TypeInputAttachment(nullptr) {} + ~TypeInputAttachment() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeInputAttachment* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeInputAttachment)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeInputAttachment(::google::protobuf::internal::ConstantInitialized); + + inline TypeInputAttachment(const TypeInputAttachment& from) : TypeInputAttachment(nullptr, from) {} + inline TypeInputAttachment(TypeInputAttachment&& from) noexcept + : TypeInputAttachment(nullptr, ::std::move(from)) {} + inline TypeInputAttachment& operator=(const TypeInputAttachment& from) { + CopyFrom(from); + return *this; + } + inline TypeInputAttachment& operator=(TypeInputAttachment&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeInputAttachment& default_instance() { + return *reinterpret_cast( + &_TypeInputAttachment_default_instance_); + } + static constexpr int kIndexInFileMessages = 18; + friend void swap(TypeInputAttachment& a, TypeInputAttachment& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeInputAttachment* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeInputAttachment* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeInputAttachment* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeInputAttachment& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeInputAttachment& from) { TypeInputAttachment::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeInputAttachment* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeInputAttachment"; } + + protected: + explicit TypeInputAttachment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeInputAttachment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeInputAttachment& from); + TypeInputAttachment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeInputAttachment&& from) noexcept + : TypeInputAttachment(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kSubTypeFieldNumber = 1, + }; + // uint32 sub_type = 1; + void clear_sub_type() ; + ::uint32_t sub_type() const; + void set_sub_type(::uint32_t value); + + private: + ::uint32_t _internal_sub_type() const; + void _internal_set_sub_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeInputAttachment) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeInputAttachment& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t sub_type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeInputAttachment_class_data_; +// ------------------------------------------------------------------- + +class TypeExternalTexture final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeExternalTexture) */ { + public: + inline TypeExternalTexture() : TypeExternalTexture(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeExternalTexture* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeExternalTexture)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeExternalTexture(::google::protobuf::internal::ConstantInitialized); + + inline TypeExternalTexture(const TypeExternalTexture& from) : TypeExternalTexture(nullptr, from) {} + inline TypeExternalTexture(TypeExternalTexture&& from) noexcept + : TypeExternalTexture(nullptr, ::std::move(from)) {} + inline TypeExternalTexture& operator=(const TypeExternalTexture& from) { + CopyFrom(from); + return *this; + } + inline TypeExternalTexture& operator=(TypeExternalTexture&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeExternalTexture& default_instance() { + return *reinterpret_cast( + &_TypeExternalTexture_default_instance_); + } + static constexpr int kIndexInFileMessages = 16; + friend void swap(TypeExternalTexture& a, TypeExternalTexture& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeExternalTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeExternalTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeExternalTexture* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const TypeExternalTexture& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const TypeExternalTexture& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeExternalTexture"; } + + protected: + explicit TypeExternalTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeExternalTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeExternalTexture& from); + TypeExternalTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeExternalTexture&& from) noexcept + : TypeExternalTexture(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeExternalTexture) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeExternalTexture_class_data_; +// ------------------------------------------------------------------- + +class TypeDepthTexture final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeDepthTexture) */ { + public: + inline TypeDepthTexture() : TypeDepthTexture(nullptr) {} + ~TypeDepthTexture() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeDepthTexture* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeDepthTexture)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeDepthTexture(::google::protobuf::internal::ConstantInitialized); + + inline TypeDepthTexture(const TypeDepthTexture& from) : TypeDepthTexture(nullptr, from) {} + inline TypeDepthTexture(TypeDepthTexture&& from) noexcept + : TypeDepthTexture(nullptr, ::std::move(from)) {} + inline TypeDepthTexture& operator=(const TypeDepthTexture& from) { + CopyFrom(from); + return *this; + } + inline TypeDepthTexture& operator=(TypeDepthTexture&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeDepthTexture& default_instance() { + return *reinterpret_cast( + &_TypeDepthTexture_default_instance_); + } + static constexpr int kIndexInFileMessages = 10; + friend void swap(TypeDepthTexture& a, TypeDepthTexture& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeDepthTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeDepthTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeDepthTexture* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeDepthTexture& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeDepthTexture& from) { TypeDepthTexture::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeDepthTexture* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeDepthTexture"; } + + protected: + explicit TypeDepthTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeDepthTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeDepthTexture& from); + TypeDepthTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeDepthTexture&& from) noexcept + : TypeDepthTexture(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDimensionFieldNumber = 1, + }; + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + void clear_dimension() ; + ::tint::core::ir::binary::pb::TextureDimension dimension() const; + void set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + private: + ::tint::core::ir::binary::pb::TextureDimension _internal_dimension() const; + void _internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeDepthTexture) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeDepthTexture& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int dimension_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeDepthTexture_class_data_; +// ------------------------------------------------------------------- + +class TypeDepthMultisampledTexture final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) */ { + public: + inline TypeDepthMultisampledTexture() : TypeDepthMultisampledTexture(nullptr) {} + ~TypeDepthMultisampledTexture() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeDepthMultisampledTexture* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeDepthMultisampledTexture)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeDepthMultisampledTexture(::google::protobuf::internal::ConstantInitialized); + + inline TypeDepthMultisampledTexture(const TypeDepthMultisampledTexture& from) : TypeDepthMultisampledTexture(nullptr, from) {} + inline TypeDepthMultisampledTexture(TypeDepthMultisampledTexture&& from) noexcept + : TypeDepthMultisampledTexture(nullptr, ::std::move(from)) {} + inline TypeDepthMultisampledTexture& operator=(const TypeDepthMultisampledTexture& from) { + CopyFrom(from); + return *this; + } + inline TypeDepthMultisampledTexture& operator=(TypeDepthMultisampledTexture&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeDepthMultisampledTexture& default_instance() { + return *reinterpret_cast( + &_TypeDepthMultisampledTexture_default_instance_); + } + static constexpr int kIndexInFileMessages = 13; + friend void swap(TypeDepthMultisampledTexture& a, TypeDepthMultisampledTexture& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeDepthMultisampledTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeDepthMultisampledTexture* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeDepthMultisampledTexture* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeDepthMultisampledTexture& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeDepthMultisampledTexture& from) { TypeDepthMultisampledTexture::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeDepthMultisampledTexture* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeDepthMultisampledTexture"; } + + protected: + explicit TypeDepthMultisampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeDepthMultisampledTexture(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeDepthMultisampledTexture& from); + TypeDepthMultisampledTexture( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeDepthMultisampledTexture&& from) noexcept + : TypeDepthMultisampledTexture(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDimensionFieldNumber = 1, + }; + // .tint.core.ir.binary.pb.TextureDimension dimension = 1; + void clear_dimension() ; + ::tint::core::ir::binary::pb::TextureDimension dimension() const; + void set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + private: + ::tint::core::ir::binary::pb::TextureDimension _internal_dimension() const; + void _internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeDepthMultisampledTexture) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeDepthMultisampledTexture& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int dimension_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeDepthMultisampledTexture_class_data_; +// ------------------------------------------------------------------- + +class TypeBuffer final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeBuffer) */ { + public: + inline TypeBuffer() : TypeBuffer(nullptr) {} + ~TypeBuffer() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeBuffer* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeBuffer)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeBuffer(::google::protobuf::internal::ConstantInitialized); + + inline TypeBuffer(const TypeBuffer& from) : TypeBuffer(nullptr, from) {} + inline TypeBuffer(TypeBuffer&& from) noexcept + : TypeBuffer(nullptr, ::std::move(from)) {} + inline TypeBuffer& operator=(const TypeBuffer& from) { + CopyFrom(from); + return *this; + } + inline TypeBuffer& operator=(TypeBuffer&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeBuffer& default_instance() { + return *reinterpret_cast( + &_TypeBuffer_default_instance_); + } + static constexpr int kIndexInFileMessages = 20; + friend void swap(TypeBuffer& a, TypeBuffer& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeBuffer* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeBuffer* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeBuffer* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeBuffer& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeBuffer& from) { TypeBuffer::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeBuffer* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeBuffer"; } + + protected: + explicit TypeBuffer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeBuffer(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeBuffer& from); + TypeBuffer( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeBuffer&& from) noexcept + : TypeBuffer(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kCountFieldNumber = 1, + }; + // uint32 count = 1; + void clear_count() ; + ::uint32_t count() const; + void set_count(::uint32_t value); + + private: + ::uint32_t _internal_count() const; + void _internal_set_count(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeBuffer) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeBuffer& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t count_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeBuffer_class_data_; +// ------------------------------------------------------------------- + +class TypeBindingArray final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeBindingArray) */ { + public: + inline TypeBindingArray() : TypeBindingArray(nullptr) {} + ~TypeBindingArray() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeBindingArray* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeBindingArray)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeBindingArray(::google::protobuf::internal::ConstantInitialized); + + inline TypeBindingArray(const TypeBindingArray& from) : TypeBindingArray(nullptr, from) {} + inline TypeBindingArray(TypeBindingArray&& from) noexcept + : TypeBindingArray(nullptr, ::std::move(from)) {} + inline TypeBindingArray& operator=(const TypeBindingArray& from) { + CopyFrom(from); + return *this; + } + inline TypeBindingArray& operator=(TypeBindingArray&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeBindingArray& default_instance() { + return *reinterpret_cast( + &_TypeBindingArray_default_instance_); + } + static constexpr int kIndexInFileMessages = 5; + friend void swap(TypeBindingArray& a, TypeBindingArray& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeBindingArray* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeBindingArray* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeBindingArray* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeBindingArray& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeBindingArray& from) { TypeBindingArray::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeBindingArray* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeBindingArray"; } + + protected: + explicit TypeBindingArray(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeBindingArray(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeBindingArray& from); + TypeBindingArray( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeBindingArray&& from) noexcept + : TypeBindingArray(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kElementFieldNumber = 1, + kCountFieldNumber = 2, + }; + // uint32 element = 1; + void clear_element() ; + ::uint32_t element() const; + void set_element(::uint32_t value); + + private: + ::uint32_t _internal_element() const; + void _internal_set_element(::uint32_t value); + + public: + // uint32 count = 2; + void clear_count() ; + ::uint32_t count() const; + void set_count(::uint32_t value); + + private: + ::uint32_t _internal_count() const; + void _internal_set_count(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeBindingArray) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeBindingArray& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t element_; + ::uint32_t count_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeBindingArray_class_data_; +// ------------------------------------------------------------------- + +class TypeAtomic final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeAtomic) */ { + public: + inline TypeAtomic() : TypeAtomic(nullptr) {} + ~TypeAtomic() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeAtomic* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeAtomic)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeAtomic(::google::protobuf::internal::ConstantInitialized); + + inline TypeAtomic(const TypeAtomic& from) : TypeAtomic(nullptr, from) {} + inline TypeAtomic(TypeAtomic&& from) noexcept + : TypeAtomic(nullptr, ::std::move(from)) {} + inline TypeAtomic& operator=(const TypeAtomic& from) { + CopyFrom(from); + return *this; + } + inline TypeAtomic& operator=(TypeAtomic&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeAtomic& default_instance() { + return *reinterpret_cast( + &_TypeAtomic_default_instance_); + } + static constexpr int kIndexInFileMessages = 9; + friend void swap(TypeAtomic& a, TypeAtomic& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeAtomic* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeAtomic* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeAtomic* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeAtomic& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeAtomic& from) { TypeAtomic::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeAtomic* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeAtomic"; } + + protected: + explicit TypeAtomic(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeAtomic(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeAtomic& from); + TypeAtomic( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeAtomic&& from) noexcept + : TypeAtomic(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kTypeFieldNumber = 1, + }; + // uint32 type = 1; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeAtomic) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeAtomic& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeAtomic_class_data_; +// ------------------------------------------------------------------- + +class TypeArray final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeArray) */ { + public: + inline TypeArray() : TypeArray(nullptr) {} + ~TypeArray() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeArray* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeArray)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeArray(::google::protobuf::internal::ConstantInitialized); + + inline TypeArray(const TypeArray& from) : TypeArray(nullptr, from) {} + inline TypeArray(TypeArray&& from) noexcept + : TypeArray(nullptr, ::std::move(from)) {} + inline TypeArray& operator=(const TypeArray& from) { + CopyFrom(from); + return *this; + } + inline TypeArray& operator=(TypeArray&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeArray& default_instance() { + return *reinterpret_cast( + &_TypeArray_default_instance_); + } + static constexpr int kIndexInFileMessages = 4; + friend void swap(TypeArray& a, TypeArray& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeArray* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeArray* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeArray* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeArray& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeArray& from) { TypeArray::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeArray* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeArray"; } + + protected: + explicit TypeArray(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeArray(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeArray& from); + TypeArray( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeArray&& from) noexcept + : TypeArray(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kElementFieldNumber = 1, + kCountFieldNumber = 3, + }; + // uint32 element = 1; + void clear_element() ; + ::uint32_t element() const; + void set_element(::uint32_t value); + + private: + ::uint32_t _internal_element() const; + void _internal_set_element(::uint32_t value); + + public: + // uint32 count = 3; + void clear_count() ; + ::uint32_t count() const; + void set_count(::uint32_t value); + + private: + ::uint32_t _internal_count() const; + void _internal_set_count(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeArray) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeArray& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t element_; + ::uint32_t count_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeArray_class_data_; +// ------------------------------------------------------------------- + +class SwitchCase final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.SwitchCase) */ { + public: + inline SwitchCase() : SwitchCase(nullptr) {} + ~SwitchCase() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(SwitchCase* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(SwitchCase)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR SwitchCase(::google::protobuf::internal::ConstantInitialized); + + inline SwitchCase(const SwitchCase& from) : SwitchCase(nullptr, from) {} + inline SwitchCase(SwitchCase&& from) noexcept + : SwitchCase(nullptr, ::std::move(from)) {} + inline SwitchCase& operator=(const SwitchCase& from) { + CopyFrom(from); + return *this; + } + inline SwitchCase& operator=(SwitchCase&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SwitchCase& default_instance() { + return *reinterpret_cast( + &_SwitchCase_default_instance_); + } + static constexpr int kIndexInFileMessages = 57; + friend void swap(SwitchCase& a, SwitchCase& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(SwitchCase* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SwitchCase* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SwitchCase* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const SwitchCase& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const SwitchCase& from) { SwitchCase::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(SwitchCase* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.SwitchCase"; } + + protected: + explicit SwitchCase(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + SwitchCase(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const SwitchCase& from); + SwitchCase( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, SwitchCase&& from) noexcept + : SwitchCase(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kSelectorsFieldNumber = 2, + kBlockFieldNumber = 1, + kIsDefaultFieldNumber = 3, + }; + // repeated uint32 selectors = 2; + int selectors_size() const; + private: + int _internal_selectors_size() const; + + public: + void clear_selectors() ; + ::uint32_t selectors(int index) const; + void set_selectors(int index, ::uint32_t value); + void add_selectors(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& selectors() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_selectors(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_selectors() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_selectors(); + + public: + // uint32 block = 1; + void clear_block() ; + ::uint32_t block() const; + void set_block(::uint32_t value); + + private: + ::uint32_t _internal_block() const; + void _internal_set_block(::uint32_t value); + + public: + // bool is_default = 3; + void clear_is_default() ; + bool is_default() const; + void set_is_default(bool value); + + private: + bool _internal_is_default() const; + void _internal_set_is_default(bool value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.SwitchCase) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const SwitchCase& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedField<::uint32_t> selectors_; + ::google::protobuf::internal::CachedSize _selectors_cached_byte_size_; + ::uint32_t block_; + bool is_default_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull SwitchCase_class_data_; +// ------------------------------------------------------------------- + +class Interpolation final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Interpolation) */ { + public: + inline Interpolation() : Interpolation(nullptr) {} + ~Interpolation() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Interpolation* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Interpolation)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Interpolation(::google::protobuf::internal::ConstantInitialized); + + inline Interpolation(const Interpolation& from) : Interpolation(nullptr, from) {} + inline Interpolation(Interpolation&& from) noexcept + : Interpolation(nullptr, ::std::move(from)) {} + inline Interpolation& operator=(const Interpolation& from) { + CopyFrom(from); + return *this; + } + inline Interpolation& operator=(Interpolation&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Interpolation& default_instance() { + return *reinterpret_cast( + &_Interpolation_default_instance_); + } + static constexpr int kIndexInFileMessages = 65; + friend void swap(Interpolation& a, Interpolation& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Interpolation* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Interpolation* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Interpolation* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Interpolation& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Interpolation& from) { Interpolation::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Interpolation* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Interpolation"; } + + protected: + explicit Interpolation(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Interpolation(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Interpolation& from); + Interpolation( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Interpolation&& from) noexcept + : Interpolation(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kTypeFieldNumber = 1, + kSamplingFieldNumber = 2, + }; + // .tint.core.ir.binary.pb.InterpolationType type = 1; + void clear_type() ; + ::tint::core::ir::binary::pb::InterpolationType type() const; + void set_type(::tint::core::ir::binary::pb::InterpolationType value); + + private: + ::tint::core::ir::binary::pb::InterpolationType _internal_type() const; + void _internal_set_type(::tint::core::ir::binary::pb::InterpolationType value); + + public: + // optional .tint.core.ir.binary.pb.InterpolationSampling sampling = 2; + bool has_sampling() const; + void clear_sampling() ; + ::tint::core::ir::binary::pb::InterpolationSampling sampling() const; + void set_sampling(::tint::core::ir::binary::pb::InterpolationSampling value); + + private: + ::tint::core::ir::binary::pb::InterpolationSampling _internal_sampling() const; + void _internal_set_sampling(::tint::core::ir::binary::pb::InterpolationSampling value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Interpolation) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Interpolation& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int type_; + int sampling_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Interpolation_class_data_; +// ------------------------------------------------------------------- + +class InstructionUserCall final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionUserCall) */ { + public: + inline InstructionUserCall() : InstructionUserCall(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionUserCall* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionUserCall)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionUserCall(::google::protobuf::internal::ConstantInitialized); + + inline InstructionUserCall(const InstructionUserCall& from) : InstructionUserCall(nullptr, from) {} + inline InstructionUserCall(InstructionUserCall&& from) noexcept + : InstructionUserCall(nullptr, ::std::move(from)) {} + inline InstructionUserCall& operator=(const InstructionUserCall& from) { + CopyFrom(from); + return *this; + } + inline InstructionUserCall& operator=(InstructionUserCall&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionUserCall& default_instance() { + return *reinterpret_cast( + &_InstructionUserCall_default_instance_); + } + static constexpr int kIndexInFileMessages = 44; + friend void swap(InstructionUserCall& a, InstructionUserCall& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionUserCall* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionUserCall* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionUserCall* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionUserCall& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionUserCall& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionUserCall"; } + + protected: + explicit InstructionUserCall(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionUserCall(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionUserCall& from); + InstructionUserCall( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionUserCall&& from) noexcept + : InstructionUserCall(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionUserCall) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionUserCall_class_data_; +// ------------------------------------------------------------------- + +class InstructionUnreachable final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionUnreachable) */ { + public: + inline InstructionUnreachable() : InstructionUnreachable(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionUnreachable* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionUnreachable)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionUnreachable(::google::protobuf::internal::ConstantInitialized); + + inline InstructionUnreachable(const InstructionUnreachable& from) : InstructionUnreachable(nullptr, from) {} + inline InstructionUnreachable(InstructionUnreachable&& from) noexcept + : InstructionUnreachable(nullptr, ::std::move(from)) {} + inline InstructionUnreachable& operator=(const InstructionUnreachable& from) { + CopyFrom(from); + return *this; + } + inline InstructionUnreachable& operator=(InstructionUnreachable&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionUnreachable& default_instance() { + return *reinterpret_cast( + &_InstructionUnreachable_default_instance_); + } + static constexpr int kIndexInFileMessages = 62; + friend void swap(InstructionUnreachable& a, InstructionUnreachable& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionUnreachable* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionUnreachable* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionUnreachable* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionUnreachable& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionUnreachable& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionUnreachable"; } + + protected: + explicit InstructionUnreachable(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionUnreachable(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionUnreachable& from); + InstructionUnreachable( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionUnreachable&& from) noexcept + : InstructionUnreachable(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionUnreachable) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionUnreachable_class_data_; +// ------------------------------------------------------------------- + +class InstructionUnary final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionUnary) */ { + public: + inline InstructionUnary() : InstructionUnary(nullptr) {} + ~InstructionUnary() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionUnary* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionUnary)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionUnary(::google::protobuf::internal::ConstantInitialized); + + inline InstructionUnary(const InstructionUnary& from) : InstructionUnary(nullptr, from) {} + inline InstructionUnary(InstructionUnary&& from) noexcept + : InstructionUnary(nullptr, ::std::move(from)) {} + inline InstructionUnary& operator=(const InstructionUnary& from) { + CopyFrom(from); + return *this; + } + inline InstructionUnary& operator=(InstructionUnary&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionUnary& default_instance() { + return *reinterpret_cast( + &_InstructionUnary_default_instance_); + } + static constexpr int kIndexInFileMessages = 35; + friend void swap(InstructionUnary& a, InstructionUnary& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionUnary* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionUnary* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionUnary* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionUnary& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionUnary& from) { InstructionUnary::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionUnary* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionUnary"; } + + protected: + explicit InstructionUnary(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionUnary(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionUnary& from); + InstructionUnary( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionUnary&& from) noexcept + : InstructionUnary(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kOpFieldNumber = 1, + }; + // .tint.core.ir.binary.pb.UnaryOp op = 1; + void clear_op() ; + ::tint::core::ir::binary::pb::UnaryOp op() const; + void set_op(::tint::core::ir::binary::pb::UnaryOp value); + + private: + ::tint::core::ir::binary::pb::UnaryOp _internal_op() const; + void _internal_set_op(::tint::core::ir::binary::pb::UnaryOp value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionUnary) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionUnary& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int op_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionUnary_class_data_; +// ------------------------------------------------------------------- + +class InstructionSwizzle final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionSwizzle) */ { + public: + inline InstructionSwizzle() : InstructionSwizzle(nullptr) {} + ~InstructionSwizzle() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionSwizzle* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionSwizzle)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionSwizzle(::google::protobuf::internal::ConstantInitialized); + + inline InstructionSwizzle(const InstructionSwizzle& from) : InstructionSwizzle(nullptr, from) {} + inline InstructionSwizzle(InstructionSwizzle&& from) noexcept + : InstructionSwizzle(nullptr, ::std::move(from)) {} + inline InstructionSwizzle& operator=(const InstructionSwizzle& from) { + CopyFrom(from); + return *this; + } + inline InstructionSwizzle& operator=(InstructionSwizzle&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionSwizzle& default_instance() { + return *reinterpret_cast( + &_InstructionSwizzle_default_instance_); + } + static constexpr int kIndexInFileMessages = 50; + friend void swap(InstructionSwizzle& a, InstructionSwizzle& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionSwizzle* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionSwizzle* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionSwizzle* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionSwizzle& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionSwizzle& from) { InstructionSwizzle::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionSwizzle* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionSwizzle"; } + + protected: + explicit InstructionSwizzle(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionSwizzle(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionSwizzle& from); + InstructionSwizzle( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionSwizzle&& from) noexcept + : InstructionSwizzle(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kIndicesFieldNumber = 1, + }; + // repeated uint32 indices = 1; + int indices_size() const; + private: + int _internal_indices_size() const; + + public: + void clear_indices() ; + ::uint32_t indices(int index) const; + void set_indices(int index, ::uint32_t value); + void add_indices(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& indices() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_indices(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_indices() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_indices(); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionSwizzle) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionSwizzle& from_msg); + ::google::protobuf::RepeatedField<::uint32_t> indices_; + ::google::protobuf::internal::CachedSize _indices_cached_byte_size_; + ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionSwizzle_class_data_; +// ------------------------------------------------------------------- + +class InstructionStoreVectorElement final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionStoreVectorElement) */ { + public: + inline InstructionStoreVectorElement() : InstructionStoreVectorElement(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionStoreVectorElement* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionStoreVectorElement)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionStoreVectorElement(::google::protobuf::internal::ConstantInitialized); + + inline InstructionStoreVectorElement(const InstructionStoreVectorElement& from) : InstructionStoreVectorElement(nullptr, from) {} + inline InstructionStoreVectorElement(InstructionStoreVectorElement&& from) noexcept + : InstructionStoreVectorElement(nullptr, ::std::move(from)) {} + inline InstructionStoreVectorElement& operator=(const InstructionStoreVectorElement& from) { + CopyFrom(from); + return *this; + } + inline InstructionStoreVectorElement& operator=(InstructionStoreVectorElement&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionStoreVectorElement& default_instance() { + return *reinterpret_cast( + &_InstructionStoreVectorElement_default_instance_); + } + static constexpr int kIndexInFileMessages = 49; + friend void swap(InstructionStoreVectorElement& a, InstructionStoreVectorElement& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionStoreVectorElement* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionStoreVectorElement* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionStoreVectorElement* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionStoreVectorElement& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionStoreVectorElement& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionStoreVectorElement"; } + + protected: + explicit InstructionStoreVectorElement(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionStoreVectorElement(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionStoreVectorElement& from); + InstructionStoreVectorElement( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionStoreVectorElement&& from) noexcept + : InstructionStoreVectorElement(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionStoreVectorElement) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionStoreVectorElement_class_data_; +// ------------------------------------------------------------------- + +class InstructionStore final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionStore) */ { + public: + inline InstructionStore() : InstructionStore(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionStore* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionStore)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionStore(::google::protobuf::internal::ConstantInitialized); + + inline InstructionStore(const InstructionStore& from) : InstructionStore(nullptr, from) {} + inline InstructionStore(InstructionStore&& from) noexcept + : InstructionStore(nullptr, ::std::move(from)) {} + inline InstructionStore& operator=(const InstructionStore& from) { + CopyFrom(from); + return *this; + } + inline InstructionStore& operator=(InstructionStore&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionStore& default_instance() { + return *reinterpret_cast( + &_InstructionStore_default_instance_); + } + static constexpr int kIndexInFileMessages = 47; + friend void swap(InstructionStore& a, InstructionStore& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionStore* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionStore* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionStore* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionStore& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionStore& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionStore"; } + + protected: + explicit InstructionStore(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionStore(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionStore& from); + InstructionStore( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionStore&& from) noexcept + : InstructionStore(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionStore) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionStore_class_data_; +// ------------------------------------------------------------------- + +class InstructionReturn final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionReturn) */ { + public: + inline InstructionReturn() : InstructionReturn(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionReturn* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionReturn)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionReturn(::google::protobuf::internal::ConstantInitialized); + + inline InstructionReturn(const InstructionReturn& from) : InstructionReturn(nullptr, from) {} + inline InstructionReturn(InstructionReturn&& from) noexcept + : InstructionReturn(nullptr, ::std::move(from)) {} + inline InstructionReturn& operator=(const InstructionReturn& from) { + CopyFrom(from); + return *this; + } + inline InstructionReturn& operator=(InstructionReturn&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionReturn& default_instance() { + return *reinterpret_cast( + &_InstructionReturn_default_instance_); + } + static constexpr int kIndexInFileMessages = 34; + friend void swap(InstructionReturn& a, InstructionReturn& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionReturn* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionReturn* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionReturn* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionReturn& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionReturn& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionReturn"; } + + protected: + explicit InstructionReturn(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionReturn(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionReturn& from); + InstructionReturn( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionReturn&& from) noexcept + : InstructionReturn(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionReturn) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionReturn_class_data_; +// ------------------------------------------------------------------- + +class InstructionResult final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionResult) */ { + public: + inline InstructionResult() : InstructionResult(nullptr) {} + ~InstructionResult() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionResult* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionResult)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionResult(::google::protobuf::internal::ConstantInitialized); + + inline InstructionResult(const InstructionResult& from) : InstructionResult(nullptr, from) {} + inline InstructionResult(InstructionResult&& from) noexcept + : InstructionResult(nullptr, ::std::move(from)) {} + inline InstructionResult& operator=(const InstructionResult& from) { + CopyFrom(from); + return *this; + } + inline InstructionResult& operator=(InstructionResult&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionResult& default_instance() { + return *reinterpret_cast( + &_InstructionResult_default_instance_); + } + static constexpr int kIndexInFileMessages = 23; + friend void swap(InstructionResult& a, InstructionResult& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionResult* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionResult* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionResult* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionResult& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionResult& from) { InstructionResult::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionResult* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionResult"; } + + protected: + explicit InstructionResult(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionResult(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionResult& from); + InstructionResult( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionResult&& from) noexcept + : InstructionResult(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 2, + kTypeFieldNumber = 1, + }; + // optional string name = 2; + bool has_name() const; + void clear_name() ; + const ::std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_name(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name(); + void set_allocated_name(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_name() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_name(); + + public: + // uint32 type = 1; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionResult) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 53, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionResult& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::uint32_t type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionResult_class_data_; +// ------------------------------------------------------------------- + +class InstructionNextIteration final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionNextIteration) */ { + public: + inline InstructionNextIteration() : InstructionNextIteration(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionNextIteration* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionNextIteration)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionNextIteration(::google::protobuf::internal::ConstantInitialized); + + inline InstructionNextIteration(const InstructionNextIteration& from) : InstructionNextIteration(nullptr, from) {} + inline InstructionNextIteration(InstructionNextIteration&& from) noexcept + : InstructionNextIteration(nullptr, ::std::move(from)) {} + inline InstructionNextIteration& operator=(const InstructionNextIteration& from) { + CopyFrom(from); + return *this; + } + inline InstructionNextIteration& operator=(InstructionNextIteration&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionNextIteration& default_instance() { + return *reinterpret_cast( + &_InstructionNextIteration_default_instance_); + } + static constexpr int kIndexInFileMessages = 59; + friend void swap(InstructionNextIteration& a, InstructionNextIteration& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionNextIteration* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionNextIteration* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionNextIteration* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionNextIteration& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionNextIteration& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionNextIteration"; } + + protected: + explicit InstructionNextIteration(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionNextIteration(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionNextIteration& from); + InstructionNextIteration( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionNextIteration&& from) noexcept + : InstructionNextIteration(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionNextIteration) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionNextIteration_class_data_; +// ------------------------------------------------------------------- + +class InstructionLoop final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionLoop) */ { + public: + inline InstructionLoop() : InstructionLoop(nullptr) {} + ~InstructionLoop() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionLoop* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionLoop)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionLoop(::google::protobuf::internal::ConstantInitialized); + + inline InstructionLoop(const InstructionLoop& from) : InstructionLoop(nullptr, from) {} + inline InstructionLoop(InstructionLoop&& from) noexcept + : InstructionLoop(nullptr, ::std::move(from)) {} + inline InstructionLoop& operator=(const InstructionLoop& from) { + CopyFrom(from); + return *this; + } + inline InstructionLoop& operator=(InstructionLoop&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionLoop& default_instance() { + return *reinterpret_cast( + &_InstructionLoop_default_instance_); + } + static constexpr int kIndexInFileMessages = 53; + friend void swap(InstructionLoop& a, InstructionLoop& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionLoop* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionLoop* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionLoop* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionLoop& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionLoop& from) { InstructionLoop::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionLoop* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionLoop"; } + + protected: + explicit InstructionLoop(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionLoop(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionLoop& from); + InstructionLoop( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionLoop&& from) noexcept + : InstructionLoop(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kInitializerFieldNumber = 1, + kBodyFieldNumber = 2, + kContinuingFieldNumber = 3, + }; + // optional uint32 initializer = 1; + bool has_initializer() const; + void clear_initializer() ; + ::uint32_t initializer() const; + void set_initializer(::uint32_t value); + + private: + ::uint32_t _internal_initializer() const; + void _internal_set_initializer(::uint32_t value); + + public: + // optional uint32 body = 2; + bool has_body() const; + void clear_body() ; + ::uint32_t body() const; + void set_body(::uint32_t value); + + private: + ::uint32_t _internal_body() const; + void _internal_set_body(::uint32_t value); + + public: + // optional uint32 continuing = 3; + bool has_continuing() const; + void clear_continuing() ; + ::uint32_t continuing() const; + void set_continuing(::uint32_t value); + + private: + ::uint32_t _internal_continuing() const; + void _internal_set_continuing(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionLoop) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionLoop& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t initializer_; + ::uint32_t body_; + ::uint32_t continuing_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionLoop_class_data_; +// ------------------------------------------------------------------- + +class InstructionLoadVectorElement final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionLoadVectorElement) */ { + public: + inline InstructionLoadVectorElement() : InstructionLoadVectorElement(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionLoadVectorElement* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionLoadVectorElement)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionLoadVectorElement(::google::protobuf::internal::ConstantInitialized); + + inline InstructionLoadVectorElement(const InstructionLoadVectorElement& from) : InstructionLoadVectorElement(nullptr, from) {} + inline InstructionLoadVectorElement(InstructionLoadVectorElement&& from) noexcept + : InstructionLoadVectorElement(nullptr, ::std::move(from)) {} + inline InstructionLoadVectorElement& operator=(const InstructionLoadVectorElement& from) { + CopyFrom(from); + return *this; + } + inline InstructionLoadVectorElement& operator=(InstructionLoadVectorElement&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionLoadVectorElement& default_instance() { + return *reinterpret_cast( + &_InstructionLoadVectorElement_default_instance_); + } + static constexpr int kIndexInFileMessages = 48; + friend void swap(InstructionLoadVectorElement& a, InstructionLoadVectorElement& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionLoadVectorElement* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionLoadVectorElement* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionLoadVectorElement* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionLoadVectorElement& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionLoadVectorElement& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionLoadVectorElement"; } + + protected: + explicit InstructionLoadVectorElement(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionLoadVectorElement(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionLoadVectorElement& from); + InstructionLoadVectorElement( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionLoadVectorElement&& from) noexcept + : InstructionLoadVectorElement(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionLoadVectorElement) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionLoadVectorElement_class_data_; +// ------------------------------------------------------------------- + +class InstructionLoad final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionLoad) */ { + public: + inline InstructionLoad() : InstructionLoad(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionLoad* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionLoad)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionLoad(::google::protobuf::internal::ConstantInitialized); + + inline InstructionLoad(const InstructionLoad& from) : InstructionLoad(nullptr, from) {} + inline InstructionLoad(InstructionLoad&& from) noexcept + : InstructionLoad(nullptr, ::std::move(from)) {} + inline InstructionLoad& operator=(const InstructionLoad& from) { + CopyFrom(from); + return *this; + } + inline InstructionLoad& operator=(InstructionLoad&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionLoad& default_instance() { + return *reinterpret_cast( + &_InstructionLoad_default_instance_); + } + static constexpr int kIndexInFileMessages = 46; + friend void swap(InstructionLoad& a, InstructionLoad& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionLoad* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionLoad* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionLoad* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionLoad& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionLoad& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionLoad"; } + + protected: + explicit InstructionLoad(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionLoad(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionLoad& from); + InstructionLoad( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionLoad&& from) noexcept + : InstructionLoad(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionLoad) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionLoad_class_data_; +// ------------------------------------------------------------------- + +class InstructionLet final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionLet) */ { + public: + inline InstructionLet() : InstructionLet(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionLet* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionLet)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionLet(::google::protobuf::internal::ConstantInitialized); + + inline InstructionLet(const InstructionLet& from) : InstructionLet(nullptr, from) {} + inline InstructionLet(InstructionLet&& from) noexcept + : InstructionLet(nullptr, ::std::move(from)) {} + inline InstructionLet& operator=(const InstructionLet& from) { + CopyFrom(from); + return *this; + } + inline InstructionLet& operator=(InstructionLet&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionLet& default_instance() { + return *reinterpret_cast( + &_InstructionLet_default_instance_); + } + static constexpr int kIndexInFileMessages = 40; + friend void swap(InstructionLet& a, InstructionLet& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionLet* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionLet* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionLet* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionLet& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionLet& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionLet"; } + + protected: + explicit InstructionLet(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionLet(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionLet& from); + InstructionLet( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionLet&& from) noexcept + : InstructionLet(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionLet) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionLet_class_data_; +// ------------------------------------------------------------------- + +class InstructionIf final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionIf) */ { + public: + inline InstructionIf() : InstructionIf(nullptr) {} + ~InstructionIf() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionIf* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionIf)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionIf(::google::protobuf::internal::ConstantInitialized); + + inline InstructionIf(const InstructionIf& from) : InstructionIf(nullptr, from) {} + inline InstructionIf(InstructionIf&& from) noexcept + : InstructionIf(nullptr, ::std::move(from)) {} + inline InstructionIf& operator=(const InstructionIf& from) { + CopyFrom(from); + return *this; + } + inline InstructionIf& operator=(InstructionIf&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionIf& default_instance() { + return *reinterpret_cast( + &_InstructionIf_default_instance_); + } + static constexpr int kIndexInFileMessages = 51; + friend void swap(InstructionIf& a, InstructionIf& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionIf* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionIf* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionIf* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionIf& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionIf& from) { InstructionIf::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionIf* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionIf"; } + + protected: + explicit InstructionIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionIf& from); + InstructionIf( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionIf&& from) noexcept + : InstructionIf(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kTrueFieldNumber = 1, + kFalseFieldNumber = 2, + }; + // optional uint32 true = 1; + bool has_true_() const; + void clear_true_() ; + ::uint32_t true_() const; + void set_true_(::uint32_t value); + + private: + ::uint32_t _internal_true_() const; + void _internal_set_true_(::uint32_t value); + + public: + // optional uint32 false = 2; + bool has_false_() const; + void clear_false_() ; + ::uint32_t false_() const; + void set_false_(::uint32_t value); + + private: + ::uint32_t _internal_false_() const; + void _internal_set_false_(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionIf) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionIf& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t true__; + ::uint32_t false__; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionIf_class_data_; +// ------------------------------------------------------------------- + +class InstructionExitSwitch final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionExitSwitch) */ { + public: + inline InstructionExitSwitch() : InstructionExitSwitch(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionExitSwitch* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionExitSwitch)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionExitSwitch(::google::protobuf::internal::ConstantInitialized); + + inline InstructionExitSwitch(const InstructionExitSwitch& from) : InstructionExitSwitch(nullptr, from) {} + inline InstructionExitSwitch(InstructionExitSwitch&& from) noexcept + : InstructionExitSwitch(nullptr, ::std::move(from)) {} + inline InstructionExitSwitch& operator=(const InstructionExitSwitch& from) { + CopyFrom(from); + return *this; + } + inline InstructionExitSwitch& operator=(InstructionExitSwitch&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionExitSwitch& default_instance() { + return *reinterpret_cast( + &_InstructionExitSwitch_default_instance_); + } + static constexpr int kIndexInFileMessages = 55; + friend void swap(InstructionExitSwitch& a, InstructionExitSwitch& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionExitSwitch* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionExitSwitch* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionExitSwitch* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionExitSwitch& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionExitSwitch& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionExitSwitch"; } + + protected: + explicit InstructionExitSwitch(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionExitSwitch(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionExitSwitch& from); + InstructionExitSwitch( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionExitSwitch&& from) noexcept + : InstructionExitSwitch(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionExitSwitch) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionExitSwitch_class_data_; +// ------------------------------------------------------------------- + +class InstructionExitLoop final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionExitLoop) */ { + public: + inline InstructionExitLoop() : InstructionExitLoop(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionExitLoop* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionExitLoop)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionExitLoop(::google::protobuf::internal::ConstantInitialized); + + inline InstructionExitLoop(const InstructionExitLoop& from) : InstructionExitLoop(nullptr, from) {} + inline InstructionExitLoop(InstructionExitLoop&& from) noexcept + : InstructionExitLoop(nullptr, ::std::move(from)) {} + inline InstructionExitLoop& operator=(const InstructionExitLoop& from) { + CopyFrom(from); + return *this; + } + inline InstructionExitLoop& operator=(InstructionExitLoop&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionExitLoop& default_instance() { + return *reinterpret_cast( + &_InstructionExitLoop_default_instance_); + } + static constexpr int kIndexInFileMessages = 56; + friend void swap(InstructionExitLoop& a, InstructionExitLoop& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionExitLoop* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionExitLoop* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionExitLoop* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionExitLoop& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionExitLoop& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionExitLoop"; } + + protected: + explicit InstructionExitLoop(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionExitLoop(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionExitLoop& from); + InstructionExitLoop( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionExitLoop&& from) noexcept + : InstructionExitLoop(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionExitLoop) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionExitLoop_class_data_; +// ------------------------------------------------------------------- + +class InstructionExitIf final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionExitIf) */ { + public: + inline InstructionExitIf() : InstructionExitIf(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionExitIf* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionExitIf)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionExitIf(::google::protobuf::internal::ConstantInitialized); + + inline InstructionExitIf(const InstructionExitIf& from) : InstructionExitIf(nullptr, from) {} + inline InstructionExitIf(InstructionExitIf&& from) noexcept + : InstructionExitIf(nullptr, ::std::move(from)) {} + inline InstructionExitIf& operator=(const InstructionExitIf& from) { + CopyFrom(from); + return *this; + } + inline InstructionExitIf& operator=(InstructionExitIf&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionExitIf& default_instance() { + return *reinterpret_cast( + &_InstructionExitIf_default_instance_); + } + static constexpr int kIndexInFileMessages = 54; + friend void swap(InstructionExitIf& a, InstructionExitIf& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionExitIf* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionExitIf* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionExitIf* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionExitIf& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionExitIf& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionExitIf"; } + + protected: + explicit InstructionExitIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionExitIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionExitIf& from); + InstructionExitIf( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionExitIf&& from) noexcept + : InstructionExitIf(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionExitIf) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionExitIf_class_data_; +// ------------------------------------------------------------------- + +class InstructionDiscard final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionDiscard) */ { + public: + inline InstructionDiscard() : InstructionDiscard(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionDiscard* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionDiscard)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionDiscard(::google::protobuf::internal::ConstantInitialized); + + inline InstructionDiscard(const InstructionDiscard& from) : InstructionDiscard(nullptr, from) {} + inline InstructionDiscard(InstructionDiscard&& from) noexcept + : InstructionDiscard(nullptr, ::std::move(from)) {} + inline InstructionDiscard& operator=(const InstructionDiscard& from) { + CopyFrom(from); + return *this; + } + inline InstructionDiscard& operator=(InstructionDiscard&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionDiscard& default_instance() { + return *reinterpret_cast( + &_InstructionDiscard_default_instance_); + } + static constexpr int kIndexInFileMessages = 39; + friend void swap(InstructionDiscard& a, InstructionDiscard& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionDiscard* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionDiscard* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionDiscard* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionDiscard& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionDiscard& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionDiscard"; } + + protected: + explicit InstructionDiscard(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionDiscard(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionDiscard& from); + InstructionDiscard( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionDiscard&& from) noexcept + : InstructionDiscard(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionDiscard) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionDiscard_class_data_; +// ------------------------------------------------------------------- + +class InstructionConvert final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionConvert) */ { + public: + inline InstructionConvert() : InstructionConvert(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionConvert* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionConvert)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionConvert(::google::protobuf::internal::ConstantInitialized); + + inline InstructionConvert(const InstructionConvert& from) : InstructionConvert(nullptr, from) {} + inline InstructionConvert(InstructionConvert&& from) noexcept + : InstructionConvert(nullptr, ::std::move(from)) {} + inline InstructionConvert& operator=(const InstructionConvert& from) { + CopyFrom(from); + return *this; + } + inline InstructionConvert& operator=(InstructionConvert&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionConvert& default_instance() { + return *reinterpret_cast( + &_InstructionConvert_default_instance_); + } + static constexpr int kIndexInFileMessages = 42; + friend void swap(InstructionConvert& a, InstructionConvert& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionConvert* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionConvert* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionConvert* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionConvert& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionConvert& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionConvert"; } + + protected: + explicit InstructionConvert(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionConvert(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionConvert& from); + InstructionConvert( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionConvert&& from) noexcept + : InstructionConvert(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionConvert) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionConvert_class_data_; +// ------------------------------------------------------------------- + +class InstructionContinue final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionContinue) */ { + public: + inline InstructionContinue() : InstructionContinue(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionContinue* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionContinue)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionContinue(::google::protobuf::internal::ConstantInitialized); + + inline InstructionContinue(const InstructionContinue& from) : InstructionContinue(nullptr, from) {} + inline InstructionContinue(InstructionContinue&& from) noexcept + : InstructionContinue(nullptr, ::std::move(from)) {} + inline InstructionContinue& operator=(const InstructionContinue& from) { + CopyFrom(from); + return *this; + } + inline InstructionContinue& operator=(InstructionContinue&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionContinue& default_instance() { + return *reinterpret_cast( + &_InstructionContinue_default_instance_); + } + static constexpr int kIndexInFileMessages = 60; + friend void swap(InstructionContinue& a, InstructionContinue& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionContinue* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionContinue* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionContinue* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionContinue& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionContinue& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionContinue"; } + + protected: + explicit InstructionContinue(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionContinue(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionContinue& from); + InstructionContinue( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionContinue&& from) noexcept + : InstructionContinue(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionContinue) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionContinue_class_data_; +// ------------------------------------------------------------------- + +class InstructionConstruct final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionConstruct) */ { + public: + inline InstructionConstruct() : InstructionConstruct(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionConstruct* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionConstruct)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionConstruct(::google::protobuf::internal::ConstantInitialized); + + inline InstructionConstruct(const InstructionConstruct& from) : InstructionConstruct(nullptr, from) {} + inline InstructionConstruct(InstructionConstruct&& from) noexcept + : InstructionConstruct(nullptr, ::std::move(from)) {} + inline InstructionConstruct& operator=(const InstructionConstruct& from) { + CopyFrom(from); + return *this; + } + inline InstructionConstruct& operator=(InstructionConstruct&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionConstruct& default_instance() { + return *reinterpret_cast( + &_InstructionConstruct_default_instance_); + } + static constexpr int kIndexInFileMessages = 38; + friend void swap(InstructionConstruct& a, InstructionConstruct& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionConstruct* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionConstruct* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionConstruct* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionConstruct& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionConstruct& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionConstruct"; } + + protected: + explicit InstructionConstruct(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionConstruct(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionConstruct& from); + InstructionConstruct( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionConstruct&& from) noexcept + : InstructionConstruct(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionConstruct) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionConstruct_class_data_; +// ------------------------------------------------------------------- + +class InstructionBuiltinCall final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionBuiltinCall) */ { + public: + inline InstructionBuiltinCall() : InstructionBuiltinCall(nullptr) {} + ~InstructionBuiltinCall() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionBuiltinCall* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionBuiltinCall)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionBuiltinCall(::google::protobuf::internal::ConstantInitialized); + + inline InstructionBuiltinCall(const InstructionBuiltinCall& from) : InstructionBuiltinCall(nullptr, from) {} + inline InstructionBuiltinCall(InstructionBuiltinCall&& from) noexcept + : InstructionBuiltinCall(nullptr, ::std::move(from)) {} + inline InstructionBuiltinCall& operator=(const InstructionBuiltinCall& from) { + CopyFrom(from); + return *this; + } + inline InstructionBuiltinCall& operator=(InstructionBuiltinCall&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionBuiltinCall& default_instance() { + return *reinterpret_cast( + &_InstructionBuiltinCall_default_instance_); + } + static constexpr int kIndexInFileMessages = 45; + friend void swap(InstructionBuiltinCall& a, InstructionBuiltinCall& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionBuiltinCall* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionBuiltinCall* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionBuiltinCall* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionBuiltinCall& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionBuiltinCall& from) { InstructionBuiltinCall::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionBuiltinCall* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionBuiltinCall"; } + + protected: + explicit InstructionBuiltinCall(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionBuiltinCall(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionBuiltinCall& from); + InstructionBuiltinCall( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionBuiltinCall&& from) noexcept + : InstructionBuiltinCall(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExplicitTemplateParamsFieldNumber = 2, + kBuiltinFieldNumber = 1, + }; + // repeated uint32 explicit_template_params = 2; + int explicit_template_params_size() const; + private: + int _internal_explicit_template_params_size() const; + + public: + void clear_explicit_template_params() ; + ::uint32_t explicit_template_params(int index) const; + void set_explicit_template_params(int index, ::uint32_t value); + void add_explicit_template_params(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& explicit_template_params() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_explicit_template_params(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_explicit_template_params() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_explicit_template_params(); + + public: + // .tint.core.ir.binary.pb.BuiltinFn builtin = 1; + void clear_builtin() ; + ::tint::core::ir::binary::pb::BuiltinFn builtin() const; + void set_builtin(::tint::core::ir::binary::pb::BuiltinFn value); + + private: + ::tint::core::ir::binary::pb::BuiltinFn _internal_builtin() const; + void _internal_set_builtin(::tint::core::ir::binary::pb::BuiltinFn value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionBuiltinCall) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionBuiltinCall& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedField<::uint32_t> explicit_template_params_; + ::google::protobuf::internal::CachedSize _explicit_template_params_cached_byte_size_; + int builtin_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionBuiltinCall_class_data_; +// ------------------------------------------------------------------- + +class InstructionBreakIf final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionBreakIf) */ { + public: + inline InstructionBreakIf() : InstructionBreakIf(nullptr) {} + ~InstructionBreakIf() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionBreakIf* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionBreakIf)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionBreakIf(::google::protobuf::internal::ConstantInitialized); + + inline InstructionBreakIf(const InstructionBreakIf& from) : InstructionBreakIf(nullptr, from) {} + inline InstructionBreakIf(InstructionBreakIf&& from) noexcept + : InstructionBreakIf(nullptr, ::std::move(from)) {} + inline InstructionBreakIf& operator=(const InstructionBreakIf& from) { + CopyFrom(from); + return *this; + } + inline InstructionBreakIf& operator=(InstructionBreakIf&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionBreakIf& default_instance() { + return *reinterpret_cast( + &_InstructionBreakIf_default_instance_); + } + static constexpr int kIndexInFileMessages = 61; + friend void swap(InstructionBreakIf& a, InstructionBreakIf& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionBreakIf* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionBreakIf* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionBreakIf* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionBreakIf& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionBreakIf& from) { InstructionBreakIf::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionBreakIf* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionBreakIf"; } + + protected: + explicit InstructionBreakIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionBreakIf(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionBreakIf& from); + InstructionBreakIf( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionBreakIf&& from) noexcept + : InstructionBreakIf(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kNumNextIterValuesFieldNumber = 1, + }; + // uint32 num_next_iter_values = 1; + void clear_num_next_iter_values() ; + ::uint32_t num_next_iter_values() const; + void set_num_next_iter_values(::uint32_t value); + + private: + ::uint32_t _internal_num_next_iter_values() const; + void _internal_set_num_next_iter_values(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionBreakIf) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionBreakIf& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t num_next_iter_values_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionBreakIf_class_data_; +// ------------------------------------------------------------------- + +class InstructionBitcast final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionBitcast) */ { + public: + inline InstructionBitcast() : InstructionBitcast(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionBitcast* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionBitcast)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionBitcast(::google::protobuf::internal::ConstantInitialized); + + inline InstructionBitcast(const InstructionBitcast& from) : InstructionBitcast(nullptr, from) {} + inline InstructionBitcast(InstructionBitcast&& from) noexcept + : InstructionBitcast(nullptr, ::std::move(from)) {} + inline InstructionBitcast& operator=(const InstructionBitcast& from) { + CopyFrom(from); + return *this; + } + inline InstructionBitcast& operator=(InstructionBitcast&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionBitcast& default_instance() { + return *reinterpret_cast( + &_InstructionBitcast_default_instance_); + } + static constexpr int kIndexInFileMessages = 37; + friend void swap(InstructionBitcast& a, InstructionBitcast& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionBitcast* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionBitcast* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionBitcast* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionBitcast& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionBitcast& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionBitcast"; } + + protected: + explicit InstructionBitcast(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionBitcast(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionBitcast& from); + InstructionBitcast( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionBitcast&& from) noexcept + : InstructionBitcast(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionBitcast) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionBitcast_class_data_; +// ------------------------------------------------------------------- + +class InstructionBinary final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionBinary) */ { + public: + inline InstructionBinary() : InstructionBinary(nullptr) {} + ~InstructionBinary() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionBinary* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionBinary)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionBinary(::google::protobuf::internal::ConstantInitialized); + + inline InstructionBinary(const InstructionBinary& from) : InstructionBinary(nullptr, from) {} + inline InstructionBinary(InstructionBinary&& from) noexcept + : InstructionBinary(nullptr, ::std::move(from)) {} + inline InstructionBinary& operator=(const InstructionBinary& from) { + CopyFrom(from); + return *this; + } + inline InstructionBinary& operator=(InstructionBinary&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionBinary& default_instance() { + return *reinterpret_cast( + &_InstructionBinary_default_instance_); + } + static constexpr int kIndexInFileMessages = 36; + friend void swap(InstructionBinary& a, InstructionBinary& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionBinary* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionBinary* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionBinary* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionBinary& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionBinary& from) { InstructionBinary::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionBinary* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionBinary"; } + + protected: + explicit InstructionBinary(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionBinary(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionBinary& from); + InstructionBinary( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionBinary&& from) noexcept + : InstructionBinary(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kOpFieldNumber = 1, + }; + // .tint.core.ir.binary.pb.BinaryOp op = 1; + void clear_op() ; + ::tint::core::ir::binary::pb::BinaryOp op() const; + void set_op(::tint::core::ir::binary::pb::BinaryOp value); + + private: + ::tint::core::ir::binary::pb::BinaryOp _internal_op() const; + void _internal_set_op(::tint::core::ir::binary::pb::BinaryOp value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionBinary) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionBinary& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + int op_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionBinary_class_data_; +// ------------------------------------------------------------------- + +class InstructionAccess final : public ::google::protobuf::internal::ZeroFieldsBase +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionAccess) */ { + public: + inline InstructionAccess() : InstructionAccess(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionAccess* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionAccess)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionAccess(::google::protobuf::internal::ConstantInitialized); + + inline InstructionAccess(const InstructionAccess& from) : InstructionAccess(nullptr, from) {} + inline InstructionAccess(InstructionAccess&& from) noexcept + : InstructionAccess(nullptr, ::std::move(from)) {} + inline InstructionAccess& operator=(const InstructionAccess& from) { + CopyFrom(from); + return *this; + } + inline InstructionAccess& operator=(InstructionAccess&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionAccess& default_instance() { + return *reinterpret_cast( + &_InstructionAccess_default_instance_); + } + static constexpr int kIndexInFileMessages = 43; + friend void swap(InstructionAccess& a, InstructionAccess& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionAccess* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionAccess* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionAccess* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const InstructionAccess& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const InstructionAccess& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + + public: + bool IsInitialized() const { + return true; + } + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionAccess"; } + + protected: + explicit InstructionAccess(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionAccess(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionAccess& from); + InstructionAccess( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionAccess&& from) noexcept + : InstructionAccess(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionAccess) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 0, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionAccess_class_data_; +// ------------------------------------------------------------------- + +class ConstantValueSplat final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.ConstantValueSplat) */ { + public: + inline ConstantValueSplat() : ConstantValueSplat(nullptr) {} + ~ConstantValueSplat() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ConstantValueSplat* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ConstantValueSplat)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR ConstantValueSplat(::google::protobuf::internal::ConstantInitialized); + + inline ConstantValueSplat(const ConstantValueSplat& from) : ConstantValueSplat(nullptr, from) {} + inline ConstantValueSplat(ConstantValueSplat&& from) noexcept + : ConstantValueSplat(nullptr, ::std::move(from)) {} + inline ConstantValueSplat& operator=(const ConstantValueSplat& from) { + CopyFrom(from); + return *this; + } + inline ConstantValueSplat& operator=(ConstantValueSplat&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ConstantValueSplat& default_instance() { + return *reinterpret_cast( + &_ConstantValueSplat_default_instance_); + } + static constexpr int kIndexInFileMessages = 29; + friend void swap(ConstantValueSplat& a, ConstantValueSplat& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(ConstantValueSplat* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ConstantValueSplat* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ConstantValueSplat* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const ConstantValueSplat& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const ConstantValueSplat& from) { ConstantValueSplat::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ConstantValueSplat* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.ConstantValueSplat"; } + + protected: + explicit ConstantValueSplat(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ConstantValueSplat(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ConstantValueSplat& from); + ConstantValueSplat( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ConstantValueSplat&& from) noexcept + : ConstantValueSplat(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kTypeFieldNumber = 1, + kElementsFieldNumber = 2, + kCountFieldNumber = 3, + }; + // uint32 type = 1; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // uint32 elements = 2; + void clear_elements() ; + ::uint32_t elements() const; + void set_elements(::uint32_t value); + + private: + ::uint32_t _internal_elements() const; + void _internal_set_elements(::uint32_t value); + + public: + // uint32 count = 3; + void clear_count() ; + ::uint32_t count() const; + void set_count(::uint32_t value); + + private: + ::uint32_t _internal_count() const; + void _internal_set_count(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.ConstantValueSplat) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ConstantValueSplat& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t type_; + ::uint32_t elements_; + ::uint32_t count_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull ConstantValueSplat_class_data_; +// ------------------------------------------------------------------- + +class ConstantValueScalar final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.ConstantValueScalar) */ { + public: + inline ConstantValueScalar() : ConstantValueScalar(nullptr) {} + ~ConstantValueScalar() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ConstantValueScalar* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ConstantValueScalar)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR ConstantValueScalar(::google::protobuf::internal::ConstantInitialized); + + inline ConstantValueScalar(const ConstantValueScalar& from) : ConstantValueScalar(nullptr, from) {} + inline ConstantValueScalar(ConstantValueScalar&& from) noexcept + : ConstantValueScalar(nullptr, ::std::move(from)) {} + inline ConstantValueScalar& operator=(const ConstantValueScalar& from) { + CopyFrom(from); + return *this; + } + inline ConstantValueScalar& operator=(ConstantValueScalar&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ConstantValueScalar& default_instance() { + return *reinterpret_cast( + &_ConstantValueScalar_default_instance_); + } + enum KindCase { + kBool = 1, + kI32 = 2, + kU32 = 3, + kF32 = 4, + kF16 = 5, + KIND_NOT_SET = 0, + }; + static constexpr int kIndexInFileMessages = 27; + friend void swap(ConstantValueScalar& a, ConstantValueScalar& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(ConstantValueScalar* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ConstantValueScalar* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ConstantValueScalar* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const ConstantValueScalar& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const ConstantValueScalar& from) { ConstantValueScalar::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ConstantValueScalar* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.ConstantValueScalar"; } + + protected: + explicit ConstantValueScalar(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ConstantValueScalar(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ConstantValueScalar& from); + ConstantValueScalar( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ConstantValueScalar&& from) noexcept + : ConstantValueScalar(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kBoolFieldNumber = 1, + kI32FieldNumber = 2, + kU32FieldNumber = 3, + kF32FieldNumber = 4, + kF16FieldNumber = 5, + }; + // bool bool = 1; + bool has_bool_() const; + void clear_bool_() ; + bool bool_() const; + void set_bool_(bool value); + + private: + bool _internal_bool_() const; + void _internal_set_bool_(bool value); + + public: + // int32 i32 = 2; + bool has_i32() const; + void clear_i32() ; + ::int32_t i32() const; + void set_i32(::int32_t value); + + private: + ::int32_t _internal_i32() const; + void _internal_set_i32(::int32_t value); + + public: + // uint32 u32 = 3; + bool has_u32() const; + void clear_u32() ; + ::uint32_t u32() const; + void set_u32(::uint32_t value); + + private: + ::uint32_t _internal_u32() const; + void _internal_set_u32(::uint32_t value); + + public: + // float f32 = 4; + bool has_f32() const; + void clear_f32() ; + float f32() const; + void set_f32(float value); + + private: + float _internal_f32() const; + void _internal_set_f32(float value); + + public: + // float f16 = 5; + bool has_f16() const; + void clear_f16() ; + float f16() const; + void set_f16(float value); + + private: + float _internal_f16() const; + void _internal_set_f16(float value); + + public: + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.ConstantValueScalar) + private: + class _Internal; + void set_has_bool_(); + void set_has_i32(); + void set_has_u32(); + void set_has_f32(); + void set_has_f16(); + inline bool has_kind() const; + inline void clear_has_kind(); + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 5, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ConstantValueScalar& from_msg); + union KindUnion { + constexpr KindUnion() : _constinit_{} {} + ::google::protobuf::internal::ConstantInitialized _constinit_; + bool bool__; + ::int32_t i32_; + ::uint32_t u32_; + float f32_; + float f16_; + } kind_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t _oneof_case_[1]; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull ConstantValueScalar_class_data_; +// ------------------------------------------------------------------- + +class ConstantValueComposite final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.ConstantValueComposite) */ { + public: + inline ConstantValueComposite() : ConstantValueComposite(nullptr) {} + ~ConstantValueComposite() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ConstantValueComposite* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ConstantValueComposite)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR ConstantValueComposite(::google::protobuf::internal::ConstantInitialized); + + inline ConstantValueComposite(const ConstantValueComposite& from) : ConstantValueComposite(nullptr, from) {} + inline ConstantValueComposite(ConstantValueComposite&& from) noexcept + : ConstantValueComposite(nullptr, ::std::move(from)) {} + inline ConstantValueComposite& operator=(const ConstantValueComposite& from) { + CopyFrom(from); + return *this; + } + inline ConstantValueComposite& operator=(ConstantValueComposite&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ConstantValueComposite& default_instance() { + return *reinterpret_cast( + &_ConstantValueComposite_default_instance_); + } + static constexpr int kIndexInFileMessages = 28; + friend void swap(ConstantValueComposite& a, ConstantValueComposite& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(ConstantValueComposite* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ConstantValueComposite* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ConstantValueComposite* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const ConstantValueComposite& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const ConstantValueComposite& from) { ConstantValueComposite::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ConstantValueComposite* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.ConstantValueComposite"; } + + protected: + explicit ConstantValueComposite(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ConstantValueComposite(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ConstantValueComposite& from); + ConstantValueComposite( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ConstantValueComposite&& from) noexcept + : ConstantValueComposite(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kElementsFieldNumber = 2, + kTypeFieldNumber = 1, + }; + // repeated uint32 elements = 2; + int elements_size() const; + private: + int _internal_elements_size() const; + + public: + void clear_elements() ; + ::uint32_t elements(int index) const; + void set_elements(int index, ::uint32_t value); + void add_elements(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& elements() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_elements(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_elements() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_elements(); + + public: + // uint32 type = 1; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.ConstantValueComposite) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ConstantValueComposite& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedField<::uint32_t> elements_; + ::google::protobuf::internal::CachedSize _elements_cached_byte_size_; + ::uint32_t type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull ConstantValueComposite_class_data_; +// ------------------------------------------------------------------- + +class BlockParameter final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.BlockParameter) */ { + public: + inline BlockParameter() : BlockParameter(nullptr) {} + ~BlockParameter() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(BlockParameter* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(BlockParameter)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR BlockParameter(::google::protobuf::internal::ConstantInitialized); + + inline BlockParameter(const BlockParameter& from) : BlockParameter(nullptr, from) {} + inline BlockParameter(BlockParameter&& from) noexcept + : BlockParameter(nullptr, ::std::move(from)) {} + inline BlockParameter& operator=(const BlockParameter& from) { + CopyFrom(from); + return *this; + } + inline BlockParameter& operator=(BlockParameter&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const BlockParameter& default_instance() { + return *reinterpret_cast( + &_BlockParameter_default_instance_); + } + static constexpr int kIndexInFileMessages = 25; + friend void swap(BlockParameter& a, BlockParameter& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(BlockParameter* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(BlockParameter* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + BlockParameter* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const BlockParameter& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const BlockParameter& from) { BlockParameter::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(BlockParameter* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.BlockParameter"; } + + protected: + explicit BlockParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + BlockParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const BlockParameter& from); + BlockParameter( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, BlockParameter&& from) noexcept + : BlockParameter(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 2, + kTypeFieldNumber = 1, + }; + // optional string name = 2; + bool has_name() const; + void clear_name() ; + const ::std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_name(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name(); + void set_allocated_name(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_name() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_name(); + + public: + // uint32 type = 1; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.BlockParameter) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 50, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const BlockParameter& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::uint32_t type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull BlockParameter_class_data_; +// ------------------------------------------------------------------- + +class BindingPoint final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.BindingPoint) */ { + public: + inline BindingPoint() : BindingPoint(nullptr) {} + ~BindingPoint() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(BindingPoint* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(BindingPoint)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR BindingPoint(::google::protobuf::internal::ConstantInitialized); + + inline BindingPoint(const BindingPoint& from) : BindingPoint(nullptr, from) {} + inline BindingPoint(BindingPoint&& from) noexcept + : BindingPoint(nullptr, ::std::move(from)) {} + inline BindingPoint& operator=(const BindingPoint& from) { + CopyFrom(from); + return *this; + } + inline BindingPoint& operator=(BindingPoint&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const BindingPoint& default_instance() { + return *reinterpret_cast( + &_BindingPoint_default_instance_); + } + static constexpr int kIndexInFileMessages = 58; + friend void swap(BindingPoint& a, BindingPoint& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(BindingPoint* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(BindingPoint* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + BindingPoint* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const BindingPoint& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const BindingPoint& from) { BindingPoint::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(BindingPoint* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.BindingPoint"; } + + protected: + explicit BindingPoint(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + BindingPoint(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const BindingPoint& from); + BindingPoint( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, BindingPoint&& from) noexcept + : BindingPoint(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kGroupFieldNumber = 1, + kBindingFieldNumber = 2, + }; + // uint32 group = 1; + void clear_group() ; + ::uint32_t group() const; + void set_group(::uint32_t value); + + private: + ::uint32_t _internal_group() const; + void _internal_set_group(::uint32_t value); + + public: + // uint32 binding = 2; + void clear_binding() ; + ::uint32_t binding() const; + void set_binding(::uint32_t value); + + private: + ::uint32_t _internal_binding() const; + void _internal_set_binding(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.BindingPoint) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 0, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const BindingPoint& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t group_; + ::uint32_t binding_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull BindingPoint_class_data_; +// ------------------------------------------------------------------- + +class InstructionVar final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionVar) */ { + public: + inline InstructionVar() : InstructionVar(nullptr) {} + ~InstructionVar() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionVar* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionVar)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionVar(::google::protobuf::internal::ConstantInitialized); + + inline InstructionVar(const InstructionVar& from) : InstructionVar(nullptr, from) {} + inline InstructionVar(InstructionVar&& from) noexcept + : InstructionVar(nullptr, ::std::move(from)) {} + inline InstructionVar& operator=(const InstructionVar& from) { + CopyFrom(from); + return *this; + } + inline InstructionVar& operator=(InstructionVar&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionVar& default_instance() { + return *reinterpret_cast( + &_InstructionVar_default_instance_); + } + static constexpr int kIndexInFileMessages = 41; + friend void swap(InstructionVar& a, InstructionVar& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionVar* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionVar* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionVar* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionVar& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionVar& from) { InstructionVar::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionVar* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionVar"; } + + protected: + explicit InstructionVar(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionVar(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionVar& from); + InstructionVar( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionVar&& from) noexcept + : InstructionVar(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kBindingPointFieldNumber = 1, + kInputAttachmentIndexFieldNumber = 2, + }; + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 1; + bool has_binding_point() const; + void clear_binding_point() ; + const ::tint::core::ir::binary::pb::BindingPoint& binding_point() const; + [[nodiscard]] ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE release_binding_point(); + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL mutable_binding_point(); + void set_allocated_binding_point(::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_binding_point(::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE unsafe_arena_release_binding_point(); + + private: + const ::tint::core::ir::binary::pb::BindingPoint& _internal_binding_point() const; + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL _internal_mutable_binding_point(); + + public: + // optional uint32 input_attachment_index = 2; + bool has_input_attachment_index() const; + void clear_input_attachment_index() ; + ::uint32_t input_attachment_index() const; + void set_input_attachment_index(::uint32_t value); + + private: + ::uint32_t _internal_input_attachment_index() const; + void _internal_set_input_attachment_index(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionVar) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 1, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionVar& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE binding_point_; + ::uint32_t input_attachment_index_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionVar_class_data_; +// ------------------------------------------------------------------- + +class InstructionSwitch final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.InstructionSwitch) */ { + public: + inline InstructionSwitch() : InstructionSwitch(nullptr) {} + ~InstructionSwitch() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InstructionSwitch* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InstructionSwitch)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR InstructionSwitch(::google::protobuf::internal::ConstantInitialized); + + inline InstructionSwitch(const InstructionSwitch& from) : InstructionSwitch(nullptr, from) {} + inline InstructionSwitch(InstructionSwitch&& from) noexcept + : InstructionSwitch(nullptr, ::std::move(from)) {} + inline InstructionSwitch& operator=(const InstructionSwitch& from) { + CopyFrom(from); + return *this; + } + inline InstructionSwitch& operator=(InstructionSwitch&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InstructionSwitch& default_instance() { + return *reinterpret_cast( + &_InstructionSwitch_default_instance_); + } + static constexpr int kIndexInFileMessages = 52; + friend void swap(InstructionSwitch& a, InstructionSwitch& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(InstructionSwitch* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InstructionSwitch* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InstructionSwitch* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const InstructionSwitch& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const InstructionSwitch& from) { InstructionSwitch::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InstructionSwitch* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.InstructionSwitch"; } + + protected: + explicit InstructionSwitch(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InstructionSwitch(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InstructionSwitch& from); + InstructionSwitch( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InstructionSwitch&& from) noexcept + : InstructionSwitch(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kCasesFieldNumber = 1, + }; + // repeated .tint.core.ir.binary.pb.SwitchCase cases = 1; + int cases_size() const; + private: + int _internal_cases_size() const; + + public: + void clear_cases() ; + ::tint::core::ir::binary::pb::SwitchCase* PROTOBUF_NONNULL mutable_cases(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>* PROTOBUF_NONNULL mutable_cases(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>& _internal_cases() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>* PROTOBUF_NONNULL _internal_mutable_cases(); + public: + const ::tint::core::ir::binary::pb::SwitchCase& cases(int index) const; + ::tint::core::ir::binary::pb::SwitchCase* PROTOBUF_NONNULL add_cases(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>& cases() const; + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.InstructionSwitch) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 1, + 1, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InstructionSwitch& from_msg); + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::SwitchCase > cases_; + ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull InstructionSwitch_class_data_; +// ------------------------------------------------------------------- + +class Function final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Function) */ { + public: + inline Function() : Function(nullptr) {} + ~Function() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Function* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Function)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Function(::google::protobuf::internal::ConstantInitialized); + + inline Function(const Function& from) : Function(nullptr, from) {} + inline Function(Function&& from) noexcept + : Function(nullptr, ::std::move(from)) {} + inline Function& operator=(const Function& from) { + CopyFrom(from); + return *this; + } + inline Function& operator=(Function&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Function& default_instance() { + return *reinterpret_cast( + &_Function_default_instance_); + } + static constexpr int kIndexInFileMessages = 30; + friend void swap(Function& a, Function& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Function* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Function* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Function* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Function& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Function& from) { Function::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Function* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Function"; } + + protected: + explicit Function(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Function(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Function& from); + Function( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Function&& from) noexcept + : Function(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kParametersFieldNumber = 6, + kNameFieldNumber = 3, + kWorkgroupSizeFieldNumber = 5, + kReturnInterpolationFieldNumber = 8, + kReturnTypeFieldNumber = 1, + kBlockFieldNumber = 2, + kPipelineStageFieldNumber = 4, + kReturnLocationFieldNumber = 7, + kReturnBuiltinFieldNumber = 9, + kReturnInvariantFieldNumber = 10, + kSubgroupSizeFieldNumber = 11, + }; + // repeated uint32 parameters = 6; + int parameters_size() const; + private: + int _internal_parameters_size() const; + + public: + void clear_parameters() ; + ::uint32_t parameters(int index) const; + void set_parameters(int index, ::uint32_t value); + void add_parameters(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& parameters() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_parameters(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_parameters() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_parameters(); + + public: + // optional string name = 3; + bool has_name() const; + void clear_name() ; + const ::std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_name(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name(); + void set_allocated_name(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_name() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_name(); + + public: + // optional .tint.core.ir.binary.pb.WorkgroupSize workgroup_size = 5; + bool has_workgroup_size() const; + void clear_workgroup_size() ; + const ::tint::core::ir::binary::pb::WorkgroupSize& workgroup_size() const; + [[nodiscard]] ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE release_workgroup_size(); + ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NONNULL mutable_workgroup_size(); + void set_allocated_workgroup_size(::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_workgroup_size(::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE unsafe_arena_release_workgroup_size(); + + private: + const ::tint::core::ir::binary::pb::WorkgroupSize& _internal_workgroup_size() const; + ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NONNULL _internal_mutable_workgroup_size(); + + public: + // optional .tint.core.ir.binary.pb.Interpolation return_interpolation = 8; + bool has_return_interpolation() const; + void clear_return_interpolation() ; + const ::tint::core::ir::binary::pb::Interpolation& return_interpolation() const; + [[nodiscard]] ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE release_return_interpolation(); + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL mutable_return_interpolation(); + void set_allocated_return_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_return_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE unsafe_arena_release_return_interpolation(); + + private: + const ::tint::core::ir::binary::pb::Interpolation& _internal_return_interpolation() const; + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL _internal_mutable_return_interpolation(); + + public: + // uint32 return_type = 1; + void clear_return_type() ; + ::uint32_t return_type() const; + void set_return_type(::uint32_t value); + + private: + ::uint32_t _internal_return_type() const; + void _internal_set_return_type(::uint32_t value); + + public: + // uint32 block = 2; + void clear_block() ; + ::uint32_t block() const; + void set_block(::uint32_t value); + + private: + ::uint32_t _internal_block() const; + void _internal_set_block(::uint32_t value); + + public: + // optional .tint.core.ir.binary.pb.PipelineStage pipeline_stage = 4; + bool has_pipeline_stage() const; + void clear_pipeline_stage() ; + ::tint::core::ir::binary::pb::PipelineStage pipeline_stage() const; + void set_pipeline_stage(::tint::core::ir::binary::pb::PipelineStage value); + + private: + ::tint::core::ir::binary::pb::PipelineStage _internal_pipeline_stage() const; + void _internal_set_pipeline_stage(::tint::core::ir::binary::pb::PipelineStage value); + + public: + // optional uint32 return_location = 7; + bool has_return_location() const; + void clear_return_location() ; + ::uint32_t return_location() const; + void set_return_location(::uint32_t value); + + private: + ::uint32_t _internal_return_location() const; + void _internal_set_return_location(::uint32_t value); + + public: + // optional .tint.core.ir.binary.pb.BuiltinValue return_builtin = 9; + bool has_return_builtin() const; + void clear_return_builtin() ; + ::tint::core::ir::binary::pb::BuiltinValue return_builtin() const; + void set_return_builtin(::tint::core::ir::binary::pb::BuiltinValue value); + + private: + ::tint::core::ir::binary::pb::BuiltinValue _internal_return_builtin() const; + void _internal_set_return_builtin(::tint::core::ir::binary::pb::BuiltinValue value); + + public: + // bool return_invariant = 10; + void clear_return_invariant() ; + bool return_invariant() const; + void set_return_invariant(bool value); + + private: + bool _internal_return_invariant() const; + void _internal_set_return_invariant(bool value); + + public: + // optional uint32 subgroup_size = 11; + bool has_subgroup_size() const; + void clear_subgroup_size() ; + ::uint32_t subgroup_size() const; + void set_subgroup_size(::uint32_t value); + + private: + ::uint32_t _internal_subgroup_size() const; + void _internal_set_subgroup_size(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Function) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<4, 11, + 2, 52, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Function& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedField<::uint32_t> parameters_; + ::google::protobuf::internal::CachedSize _parameters_cached_byte_size_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE workgroup_size_; + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE return_interpolation_; + ::uint32_t return_type_; + ::uint32_t block_; + int pipeline_stage_; + ::uint32_t return_location_; + int return_builtin_; + bool return_invariant_; + ::uint32_t subgroup_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Function_class_data_; +// ------------------------------------------------------------------- + +class ConstantValue final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.ConstantValue) */ { + public: + inline ConstantValue() : ConstantValue(nullptr) {} + ~ConstantValue() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ConstantValue* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ConstantValue)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR ConstantValue(::google::protobuf::internal::ConstantInitialized); + + inline ConstantValue(const ConstantValue& from) : ConstantValue(nullptr, from) {} + inline ConstantValue(ConstantValue&& from) noexcept + : ConstantValue(nullptr, ::std::move(from)) {} + inline ConstantValue& operator=(const ConstantValue& from) { + CopyFrom(from); + return *this; + } + inline ConstantValue& operator=(ConstantValue&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ConstantValue& default_instance() { + return *reinterpret_cast( + &_ConstantValue_default_instance_); + } + enum KindCase { + kScalar = 1, + kComposite = 2, + kSplat = 3, + KIND_NOT_SET = 0, + }; + static constexpr int kIndexInFileMessages = 26; + friend void swap(ConstantValue& a, ConstantValue& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(ConstantValue* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ConstantValue* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ConstantValue* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const ConstantValue& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const ConstantValue& from) { ConstantValue::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ConstantValue* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.ConstantValue"; } + + protected: + explicit ConstantValue(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ConstantValue(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ConstantValue& from); + ConstantValue( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ConstantValue&& from) noexcept + : ConstantValue(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kScalarFieldNumber = 1, + kCompositeFieldNumber = 2, + kSplatFieldNumber = 3, + }; + // .tint.core.ir.binary.pb.ConstantValueScalar scalar = 1; + bool has_scalar() const; + private: + bool _internal_has_scalar() const; + + public: + void clear_scalar() ; + const ::tint::core::ir::binary::pb::ConstantValueScalar& scalar() const; + [[nodiscard]] ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE release_scalar(); + ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NONNULL mutable_scalar(); + void set_allocated_scalar(::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_scalar(::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE unsafe_arena_release_scalar(); + + private: + const ::tint::core::ir::binary::pb::ConstantValueScalar& _internal_scalar() const; + ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NONNULL _internal_mutable_scalar(); + + public: + // .tint.core.ir.binary.pb.ConstantValueComposite composite = 2; + bool has_composite() const; + private: + bool _internal_has_composite() const; + + public: + void clear_composite() ; + const ::tint::core::ir::binary::pb::ConstantValueComposite& composite() const; + [[nodiscard]] ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE release_composite(); + ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NONNULL mutable_composite(); + void set_allocated_composite(::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_composite(::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE unsafe_arena_release_composite(); + + private: + const ::tint::core::ir::binary::pb::ConstantValueComposite& _internal_composite() const; + ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NONNULL _internal_mutable_composite(); + + public: + // .tint.core.ir.binary.pb.ConstantValueSplat splat = 3; + bool has_splat() const; + private: + bool _internal_has_splat() const; + + public: + void clear_splat() ; + const ::tint::core::ir::binary::pb::ConstantValueSplat& splat() const; + [[nodiscard]] ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE release_splat(); + ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NONNULL mutable_splat(); + void set_allocated_splat(::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_splat(::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE unsafe_arena_release_splat(); + + private: + const ::tint::core::ir::binary::pb::ConstantValueSplat& _internal_splat() const; + ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NONNULL _internal_mutable_splat(); + + public: + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.ConstantValue) + private: + class _Internal; + void set_has_scalar(); + void set_has_composite(); + void set_has_splat(); + inline bool has_kind() const; + inline void clear_has_kind(); + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 3, + 3, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ConstantValue& from_msg); + union KindUnion { + constexpr KindUnion() : _constinit_{} {} + ::google::protobuf::internal::ConstantInitialized _constinit_; + ::google::protobuf::Message* PROTOBUF_NULLABLE scalar_; + ::google::protobuf::Message* PROTOBUF_NULLABLE composite_; + ::google::protobuf::Message* PROTOBUF_NULLABLE splat_; + } kind_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t _oneof_case_[1]; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull ConstantValue_class_data_; +// ------------------------------------------------------------------- + +class AttributesStructMember final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.AttributesStructMember) */ { + public: + inline AttributesStructMember() : AttributesStructMember(nullptr) {} + ~AttributesStructMember() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(AttributesStructMember* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(AttributesStructMember)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR AttributesStructMember(::google::protobuf::internal::ConstantInitialized); + + inline AttributesStructMember(const AttributesStructMember& from) : AttributesStructMember(nullptr, from) {} + inline AttributesStructMember(AttributesStructMember&& from) noexcept + : AttributesStructMember(nullptr, ::std::move(from)) {} + inline AttributesStructMember& operator=(const AttributesStructMember& from) { + CopyFrom(from); + return *this; + } + inline AttributesStructMember& operator=(AttributesStructMember&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const AttributesStructMember& default_instance() { + return *reinterpret_cast( + &_AttributesStructMember_default_instance_); + } + static constexpr int kIndexInFileMessages = 63; + friend void swap(AttributesStructMember& a, AttributesStructMember& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(AttributesStructMember* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AttributesStructMember* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + AttributesStructMember* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const AttributesStructMember& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const AttributesStructMember& from) { AttributesStructMember::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(AttributesStructMember* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.AttributesStructMember"; } + + protected: + explicit AttributesStructMember(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + AttributesStructMember(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const AttributesStructMember& from); + AttributesStructMember( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, AttributesStructMember&& from) noexcept + : AttributesStructMember(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kInterpolationFieldNumber = 5, + kLocationFieldNumber = 1, + kBlendSrcFieldNumber = 2, + kColorFieldNumber = 3, + kBuiltinFieldNumber = 4, + kInvariantFieldNumber = 6, + }; + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 5; + bool has_interpolation() const; + void clear_interpolation() ; + const ::tint::core::ir::binary::pb::Interpolation& interpolation() const; + [[nodiscard]] ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE release_interpolation(); + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL mutable_interpolation(); + void set_allocated_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE unsafe_arena_release_interpolation(); + + private: + const ::tint::core::ir::binary::pb::Interpolation& _internal_interpolation() const; + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL _internal_mutable_interpolation(); + + public: + // optional uint32 location = 1; + bool has_location() const; + void clear_location() ; + ::uint32_t location() const; + void set_location(::uint32_t value); + + private: + ::uint32_t _internal_location() const; + void _internal_set_location(::uint32_t value); + + public: + // optional uint32 blend_src = 2; + bool has_blend_src() const; + void clear_blend_src() ; + ::uint32_t blend_src() const; + void set_blend_src(::uint32_t value); + + private: + ::uint32_t _internal_blend_src() const; + void _internal_set_blend_src(::uint32_t value); + + public: + // optional uint32 color = 3; + bool has_color() const; + void clear_color() ; + ::uint32_t color() const; + void set_color(::uint32_t value); + + private: + ::uint32_t _internal_color() const; + void _internal_set_color(::uint32_t value); + + public: + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 4; + bool has_builtin() const; + void clear_builtin() ; + ::tint::core::ir::binary::pb::BuiltinValue builtin() const; + void set_builtin(::tint::core::ir::binary::pb::BuiltinValue value); + + private: + ::tint::core::ir::binary::pb::BuiltinValue _internal_builtin() const; + void _internal_set_builtin(::tint::core::ir::binary::pb::BuiltinValue value); + + public: + // bool invariant = 6; + void clear_invariant() ; + bool invariant() const; + void set_invariant(bool value); + + private: + bool _internal_invariant() const; + void _internal_set_invariant(bool value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.AttributesStructMember) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<3, 6, + 1, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const AttributesStructMember& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE interpolation_; + ::uint32_t location_; + ::uint32_t blend_src_; + ::uint32_t color_; + int builtin_; + bool invariant_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull AttributesStructMember_class_data_; +// ------------------------------------------------------------------- + +class AttributesFunctionParameter final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.AttributesFunctionParameter) */ { + public: + inline AttributesFunctionParameter() : AttributesFunctionParameter(nullptr) {} + ~AttributesFunctionParameter() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(AttributesFunctionParameter* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(AttributesFunctionParameter)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR AttributesFunctionParameter(::google::protobuf::internal::ConstantInitialized); + + inline AttributesFunctionParameter(const AttributesFunctionParameter& from) : AttributesFunctionParameter(nullptr, from) {} + inline AttributesFunctionParameter(AttributesFunctionParameter&& from) noexcept + : AttributesFunctionParameter(nullptr, ::std::move(from)) {} + inline AttributesFunctionParameter& operator=(const AttributesFunctionParameter& from) { + CopyFrom(from); + return *this; + } + inline AttributesFunctionParameter& operator=(AttributesFunctionParameter&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const AttributesFunctionParameter& default_instance() { + return *reinterpret_cast( + &_AttributesFunctionParameter_default_instance_); + } + static constexpr int kIndexInFileMessages = 64; + friend void swap(AttributesFunctionParameter& a, AttributesFunctionParameter& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(AttributesFunctionParameter* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AttributesFunctionParameter* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + AttributesFunctionParameter* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const AttributesFunctionParameter& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const AttributesFunctionParameter& from) { AttributesFunctionParameter::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(AttributesFunctionParameter* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.AttributesFunctionParameter"; } + + protected: + explicit AttributesFunctionParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + AttributesFunctionParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const AttributesFunctionParameter& from); + AttributesFunctionParameter( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, AttributesFunctionParameter&& from) noexcept + : AttributesFunctionParameter(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kInterpolationFieldNumber = 4, + kBindingPointFieldNumber = 5, + kBuiltinFieldNumber = 1, + kLocationFieldNumber = 2, + kColorFieldNumber = 3, + kInvariantFieldNumber = 6, + }; + // optional .tint.core.ir.binary.pb.Interpolation interpolation = 4; + bool has_interpolation() const; + void clear_interpolation() ; + const ::tint::core::ir::binary::pb::Interpolation& interpolation() const; + [[nodiscard]] ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE release_interpolation(); + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL mutable_interpolation(); + void set_allocated_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE unsafe_arena_release_interpolation(); + + private: + const ::tint::core::ir::binary::pb::Interpolation& _internal_interpolation() const; + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL _internal_mutable_interpolation(); + + public: + // optional .tint.core.ir.binary.pb.BindingPoint binding_point = 5; + bool has_binding_point() const; + void clear_binding_point() ; + const ::tint::core::ir::binary::pb::BindingPoint& binding_point() const; + [[nodiscard]] ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE release_binding_point(); + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL mutable_binding_point(); + void set_allocated_binding_point(::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_binding_point(::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE unsafe_arena_release_binding_point(); + + private: + const ::tint::core::ir::binary::pb::BindingPoint& _internal_binding_point() const; + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL _internal_mutable_binding_point(); + + public: + // optional .tint.core.ir.binary.pb.BuiltinValue builtin = 1; + bool has_builtin() const; + void clear_builtin() ; + ::tint::core::ir::binary::pb::BuiltinValue builtin() const; + void set_builtin(::tint::core::ir::binary::pb::BuiltinValue value); + + private: + ::tint::core::ir::binary::pb::BuiltinValue _internal_builtin() const; + void _internal_set_builtin(::tint::core::ir::binary::pb::BuiltinValue value); + + public: + // optional uint32 location = 2; + bool has_location() const; + void clear_location() ; + ::uint32_t location() const; + void set_location(::uint32_t value); + + private: + ::uint32_t _internal_location() const; + void _internal_set_location(::uint32_t value); + + public: + // optional uint32 color = 3; + bool has_color() const; + void clear_color() ; + ::uint32_t color() const; + void set_color(::uint32_t value); + + private: + ::uint32_t _internal_color() const; + void _internal_set_color(::uint32_t value); + + public: + // bool invariant = 6; + void clear_invariant() ; + bool invariant() const; + void set_invariant(bool value); + + private: + bool _internal_invariant() const; + void _internal_set_invariant(bool value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.AttributesFunctionParameter) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<3, 6, + 2, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const AttributesFunctionParameter& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE interpolation_; + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE binding_point_; + int builtin_; + ::uint32_t location_; + ::uint32_t color_; + bool invariant_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull AttributesFunctionParameter_class_data_; +// ------------------------------------------------------------------- + +class TypeStructMember final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeStructMember) */ { + public: + inline TypeStructMember() : TypeStructMember(nullptr) {} + ~TypeStructMember() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeStructMember* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeStructMember)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeStructMember(::google::protobuf::internal::ConstantInitialized); + + inline TypeStructMember(const TypeStructMember& from) : TypeStructMember(nullptr, from) {} + inline TypeStructMember(TypeStructMember&& from) noexcept + : TypeStructMember(nullptr, ::std::move(from)) {} + inline TypeStructMember& operator=(const TypeStructMember& from) { + CopyFrom(from); + return *this; + } + inline TypeStructMember& operator=(TypeStructMember&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeStructMember& default_instance() { + return *reinterpret_cast( + &_TypeStructMember_default_instance_); + } + static constexpr int kIndexInFileMessages = 8; + friend void swap(TypeStructMember& a, TypeStructMember& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeStructMember* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeStructMember* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeStructMember* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeStructMember& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeStructMember& from) { TypeStructMember::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeStructMember* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeStructMember"; } + + protected: + explicit TypeStructMember(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeStructMember(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeStructMember& from); + TypeStructMember( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeStructMember&& from) noexcept + : TypeStructMember(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 1, + kAttributesFieldNumber = 5, + kTypeFieldNumber = 2, + kSizeFieldNumber = 3, + kAlignFieldNumber = 4, + }; + // string name = 1; + void clear_name() ; + const ::std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_name(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name(); + void set_allocated_name(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_name() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_name(); + + public: + // optional .tint.core.ir.binary.pb.AttributesStructMember attributes = 5; + bool has_attributes() const; + void clear_attributes() ; + const ::tint::core::ir::binary::pb::AttributesStructMember& attributes() const; + [[nodiscard]] ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE release_attributes(); + ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NONNULL mutable_attributes(); + void set_allocated_attributes(::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_attributes(::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE unsafe_arena_release_attributes(); + + private: + const ::tint::core::ir::binary::pb::AttributesStructMember& _internal_attributes() const; + ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NONNULL _internal_mutable_attributes(); + + public: + // uint32 type = 2; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // uint32 size = 3; + void clear_size() ; + ::uint32_t size() const; + void set_size(::uint32_t value); + + private: + ::uint32_t _internal_size() const; + void _internal_set_size(::uint32_t value); + + public: + // uint32 align = 4; + void clear_align() ; + ::uint32_t align() const; + void set_align(::uint32_t value); + + private: + ::uint32_t _internal_align() const; + void _internal_set_align(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeStructMember) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<3, 5, + 1, 52, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeStructMember& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE attributes_; + ::uint32_t type_; + ::uint32_t size_; + ::uint32_t align_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeStructMember_class_data_; +// ------------------------------------------------------------------- + +class Instruction final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Instruction) */ { + public: + inline Instruction() : Instruction(nullptr) {} + ~Instruction() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Instruction* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Instruction)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Instruction(::google::protobuf::internal::ConstantInitialized); + + inline Instruction(const Instruction& from) : Instruction(nullptr, from) {} + inline Instruction(Instruction&& from) noexcept + : Instruction(nullptr, ::std::move(from)) {} + inline Instruction& operator=(const Instruction& from) { + CopyFrom(from); + return *this; + } + inline Instruction& operator=(Instruction&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Instruction& default_instance() { + return *reinterpret_cast( + &_Instruction_default_instance_); + } + enum KindCase { + kReturn = 3, + kUnary = 4, + kBinary = 5, + kDiscard = 6, + kLet = 7, + kVar = 8, + kBitcast = 9, + kConstruct = 10, + kConvert = 11, + kAccess = 12, + kUserCall = 13, + kBuiltinCall = 14, + kLoad = 15, + kStore = 16, + kLoadVectorElement = 17, + kStoreVectorElement = 18, + kSwizzle = 19, + kIf = 20, + kSwitch = 21, + kLoop = 22, + kExitIf = 23, + kExitSwitch = 24, + kExitLoop = 25, + kNextIteration = 26, + kContinue = 27, + kBreakIf = 28, + kUnreachable = 29, + KIND_NOT_SET = 0, + }; + static constexpr int kIndexInFileMessages = 33; + friend void swap(Instruction& a, Instruction& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Instruction* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Instruction* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Instruction* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Instruction& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Instruction& from) { Instruction::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Instruction* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Instruction"; } + + protected: + explicit Instruction(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Instruction(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Instruction& from); + Instruction( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Instruction&& from) noexcept + : Instruction(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kOperandsFieldNumber = 1, + kResultsFieldNumber = 2, + kReturnFieldNumber = 3, + kUnaryFieldNumber = 4, + kBinaryFieldNumber = 5, + kDiscardFieldNumber = 6, + kLetFieldNumber = 7, + kVarFieldNumber = 8, + kBitcastFieldNumber = 9, + kConstructFieldNumber = 10, + kConvertFieldNumber = 11, + kAccessFieldNumber = 12, + kUserCallFieldNumber = 13, + kBuiltinCallFieldNumber = 14, + kLoadFieldNumber = 15, + kStoreFieldNumber = 16, + kLoadVectorElementFieldNumber = 17, + kStoreVectorElementFieldNumber = 18, + kSwizzleFieldNumber = 19, + kIfFieldNumber = 20, + kSwitchFieldNumber = 21, + kLoopFieldNumber = 22, + kExitIfFieldNumber = 23, + kExitSwitchFieldNumber = 24, + kExitLoopFieldNumber = 25, + kNextIterationFieldNumber = 26, + kContinueFieldNumber = 27, + kBreakIfFieldNumber = 28, + kUnreachableFieldNumber = 29, + }; + // repeated uint32 operands = 1; + int operands_size() const; + private: + int _internal_operands_size() const; + + public: + void clear_operands() ; + ::uint32_t operands(int index) const; + void set_operands(int index, ::uint32_t value); + void add_operands(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& operands() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_operands(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_operands() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_operands(); + + public: + // repeated uint32 results = 2; + int results_size() const; + private: + int _internal_results_size() const; + + public: + void clear_results() ; + ::uint32_t results(int index) const; + void set_results(int index, ::uint32_t value); + void add_results(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& results() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_results(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_results() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_results(); + + public: + // .tint.core.ir.binary.pb.InstructionReturn return = 3; + bool has_return_() const; + private: + bool _internal_has_return_() const; + + public: + void clear_return_() ; + const ::tint::core::ir::binary::pb::InstructionReturn& return_() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE release_return_(); + ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NONNULL mutable_return_(); + void set_allocated_return_(::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_return_(::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE unsafe_arena_release_return_(); + + private: + const ::tint::core::ir::binary::pb::InstructionReturn& _internal_return_() const; + ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NONNULL _internal_mutable_return_(); + + public: + // .tint.core.ir.binary.pb.InstructionUnary unary = 4; + bool has_unary() const; + private: + bool _internal_has_unary() const; + + public: + void clear_unary() ; + const ::tint::core::ir::binary::pb::InstructionUnary& unary() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE release_unary(); + ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NONNULL mutable_unary(); + void set_allocated_unary(::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_unary(::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE unsafe_arena_release_unary(); + + private: + const ::tint::core::ir::binary::pb::InstructionUnary& _internal_unary() const; + ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NONNULL _internal_mutable_unary(); + + public: + // .tint.core.ir.binary.pb.InstructionBinary binary = 5; + bool has_binary() const; + private: + bool _internal_has_binary() const; + + public: + void clear_binary() ; + const ::tint::core::ir::binary::pb::InstructionBinary& binary() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE release_binary(); + ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NONNULL mutable_binary(); + void set_allocated_binary(::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_binary(::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE unsafe_arena_release_binary(); + + private: + const ::tint::core::ir::binary::pb::InstructionBinary& _internal_binary() const; + ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NONNULL _internal_mutable_binary(); + + public: + // .tint.core.ir.binary.pb.InstructionDiscard discard = 6; + bool has_discard() const; + private: + bool _internal_has_discard() const; + + public: + void clear_discard() ; + const ::tint::core::ir::binary::pb::InstructionDiscard& discard() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE release_discard(); + ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NONNULL mutable_discard(); + void set_allocated_discard(::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_discard(::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE unsafe_arena_release_discard(); + + private: + const ::tint::core::ir::binary::pb::InstructionDiscard& _internal_discard() const; + ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NONNULL _internal_mutable_discard(); + + public: + // .tint.core.ir.binary.pb.InstructionLet let = 7; + bool has_let() const; + private: + bool _internal_has_let() const; + + public: + void clear_let() ; + const ::tint::core::ir::binary::pb::InstructionLet& let() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE release_let(); + ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NONNULL mutable_let(); + void set_allocated_let(::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_let(::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE unsafe_arena_release_let(); + + private: + const ::tint::core::ir::binary::pb::InstructionLet& _internal_let() const; + ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NONNULL _internal_mutable_let(); + + public: + // .tint.core.ir.binary.pb.InstructionVar var = 8; + bool has_var() const; + private: + bool _internal_has_var() const; + + public: + void clear_var() ; + const ::tint::core::ir::binary::pb::InstructionVar& var() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE release_var(); + ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NONNULL mutable_var(); + void set_allocated_var(::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_var(::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE unsafe_arena_release_var(); + + private: + const ::tint::core::ir::binary::pb::InstructionVar& _internal_var() const; + ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NONNULL _internal_mutable_var(); + + public: + // .tint.core.ir.binary.pb.InstructionBitcast bitcast = 9; + bool has_bitcast() const; + private: + bool _internal_has_bitcast() const; + + public: + void clear_bitcast() ; + const ::tint::core::ir::binary::pb::InstructionBitcast& bitcast() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE release_bitcast(); + ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NONNULL mutable_bitcast(); + void set_allocated_bitcast(::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_bitcast(::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE unsafe_arena_release_bitcast(); + + private: + const ::tint::core::ir::binary::pb::InstructionBitcast& _internal_bitcast() const; + ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NONNULL _internal_mutable_bitcast(); + + public: + // .tint.core.ir.binary.pb.InstructionConstruct construct = 10; + bool has_construct() const; + private: + bool _internal_has_construct() const; + + public: + void clear_construct() ; + const ::tint::core::ir::binary::pb::InstructionConstruct& construct() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE release_construct(); + ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NONNULL mutable_construct(); + void set_allocated_construct(::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_construct(::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE unsafe_arena_release_construct(); + + private: + const ::tint::core::ir::binary::pb::InstructionConstruct& _internal_construct() const; + ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NONNULL _internal_mutable_construct(); + + public: + // .tint.core.ir.binary.pb.InstructionConvert convert = 11; + bool has_convert() const; + private: + bool _internal_has_convert() const; + + public: + void clear_convert() ; + const ::tint::core::ir::binary::pb::InstructionConvert& convert() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE release_convert(); + ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NONNULL mutable_convert(); + void set_allocated_convert(::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_convert(::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE unsafe_arena_release_convert(); + + private: + const ::tint::core::ir::binary::pb::InstructionConvert& _internal_convert() const; + ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NONNULL _internal_mutable_convert(); + + public: + // .tint.core.ir.binary.pb.InstructionAccess access = 12; + bool has_access() const; + private: + bool _internal_has_access() const; + + public: + void clear_access() ; + const ::tint::core::ir::binary::pb::InstructionAccess& access() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE release_access(); + ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NONNULL mutable_access(); + void set_allocated_access(::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_access(::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE unsafe_arena_release_access(); + + private: + const ::tint::core::ir::binary::pb::InstructionAccess& _internal_access() const; + ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NONNULL _internal_mutable_access(); + + public: + // .tint.core.ir.binary.pb.InstructionUserCall user_call = 13; + bool has_user_call() const; + private: + bool _internal_has_user_call() const; + + public: + void clear_user_call() ; + const ::tint::core::ir::binary::pb::InstructionUserCall& user_call() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE release_user_call(); + ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NONNULL mutable_user_call(); + void set_allocated_user_call(::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_user_call(::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE unsafe_arena_release_user_call(); + + private: + const ::tint::core::ir::binary::pb::InstructionUserCall& _internal_user_call() const; + ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NONNULL _internal_mutable_user_call(); + + public: + // .tint.core.ir.binary.pb.InstructionBuiltinCall builtin_call = 14; + bool has_builtin_call() const; + private: + bool _internal_has_builtin_call() const; + + public: + void clear_builtin_call() ; + const ::tint::core::ir::binary::pb::InstructionBuiltinCall& builtin_call() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE release_builtin_call(); + ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NONNULL mutable_builtin_call(); + void set_allocated_builtin_call(::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_builtin_call(::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE unsafe_arena_release_builtin_call(); + + private: + const ::tint::core::ir::binary::pb::InstructionBuiltinCall& _internal_builtin_call() const; + ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NONNULL _internal_mutable_builtin_call(); + + public: + // .tint.core.ir.binary.pb.InstructionLoad load = 15; + bool has_load() const; + private: + bool _internal_has_load() const; + + public: + void clear_load() ; + const ::tint::core::ir::binary::pb::InstructionLoad& load() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE release_load(); + ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NONNULL mutable_load(); + void set_allocated_load(::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_load(::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE unsafe_arena_release_load(); + + private: + const ::tint::core::ir::binary::pb::InstructionLoad& _internal_load() const; + ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NONNULL _internal_mutable_load(); + + public: + // .tint.core.ir.binary.pb.InstructionStore store = 16; + bool has_store() const; + private: + bool _internal_has_store() const; + + public: + void clear_store() ; + const ::tint::core::ir::binary::pb::InstructionStore& store() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE release_store(); + ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NONNULL mutable_store(); + void set_allocated_store(::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_store(::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE unsafe_arena_release_store(); + + private: + const ::tint::core::ir::binary::pb::InstructionStore& _internal_store() const; + ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NONNULL _internal_mutable_store(); + + public: + // .tint.core.ir.binary.pb.InstructionLoadVectorElement load_vector_element = 17; + bool has_load_vector_element() const; + private: + bool _internal_has_load_vector_element() const; + + public: + void clear_load_vector_element() ; + const ::tint::core::ir::binary::pb::InstructionLoadVectorElement& load_vector_element() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE release_load_vector_element(); + ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NONNULL mutable_load_vector_element(); + void set_allocated_load_vector_element(::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_load_vector_element(::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE unsafe_arena_release_load_vector_element(); + + private: + const ::tint::core::ir::binary::pb::InstructionLoadVectorElement& _internal_load_vector_element() const; + ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NONNULL _internal_mutable_load_vector_element(); + + public: + // .tint.core.ir.binary.pb.InstructionStoreVectorElement store_vector_element = 18; + bool has_store_vector_element() const; + private: + bool _internal_has_store_vector_element() const; + + public: + void clear_store_vector_element() ; + const ::tint::core::ir::binary::pb::InstructionStoreVectorElement& store_vector_element() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE release_store_vector_element(); + ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NONNULL mutable_store_vector_element(); + void set_allocated_store_vector_element(::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_store_vector_element(::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE unsafe_arena_release_store_vector_element(); + + private: + const ::tint::core::ir::binary::pb::InstructionStoreVectorElement& _internal_store_vector_element() const; + ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NONNULL _internal_mutable_store_vector_element(); + + public: + // .tint.core.ir.binary.pb.InstructionSwizzle swizzle = 19; + bool has_swizzle() const; + private: + bool _internal_has_swizzle() const; + + public: + void clear_swizzle() ; + const ::tint::core::ir::binary::pb::InstructionSwizzle& swizzle() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE release_swizzle(); + ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NONNULL mutable_swizzle(); + void set_allocated_swizzle(::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_swizzle(::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE unsafe_arena_release_swizzle(); + + private: + const ::tint::core::ir::binary::pb::InstructionSwizzle& _internal_swizzle() const; + ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NONNULL _internal_mutable_swizzle(); + + public: + // .tint.core.ir.binary.pb.InstructionIf if = 20; + bool has_if_() const; + private: + bool _internal_has_if_() const; + + public: + void clear_if_() ; + const ::tint::core::ir::binary::pb::InstructionIf& if_() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE release_if_(); + ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NONNULL mutable_if_(); + void set_allocated_if_(::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_if_(::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE unsafe_arena_release_if_(); + + private: + const ::tint::core::ir::binary::pb::InstructionIf& _internal_if_() const; + ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NONNULL _internal_mutable_if_(); + + public: + // .tint.core.ir.binary.pb.InstructionSwitch switch = 21; + bool has_switch_() const; + private: + bool _internal_has_switch_() const; + + public: + void clear_switch_() ; + const ::tint::core::ir::binary::pb::InstructionSwitch& switch_() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE release_switch_(); + ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NONNULL mutable_switch_(); + void set_allocated_switch_(::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_switch_(::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE unsafe_arena_release_switch_(); + + private: + const ::tint::core::ir::binary::pb::InstructionSwitch& _internal_switch_() const; + ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NONNULL _internal_mutable_switch_(); + + public: + // .tint.core.ir.binary.pb.InstructionLoop loop = 22; + bool has_loop() const; + private: + bool _internal_has_loop() const; + + public: + void clear_loop() ; + const ::tint::core::ir::binary::pb::InstructionLoop& loop() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE release_loop(); + ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NONNULL mutable_loop(); + void set_allocated_loop(::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_loop(::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE unsafe_arena_release_loop(); + + private: + const ::tint::core::ir::binary::pb::InstructionLoop& _internal_loop() const; + ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NONNULL _internal_mutable_loop(); + + public: + // .tint.core.ir.binary.pb.InstructionExitIf exit_if = 23; + bool has_exit_if() const; + private: + bool _internal_has_exit_if() const; + + public: + void clear_exit_if() ; + const ::tint::core::ir::binary::pb::InstructionExitIf& exit_if() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE release_exit_if(); + ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NONNULL mutable_exit_if(); + void set_allocated_exit_if(::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_exit_if(::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE unsafe_arena_release_exit_if(); + + private: + const ::tint::core::ir::binary::pb::InstructionExitIf& _internal_exit_if() const; + ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NONNULL _internal_mutable_exit_if(); + + public: + // .tint.core.ir.binary.pb.InstructionExitSwitch exit_switch = 24; + bool has_exit_switch() const; + private: + bool _internal_has_exit_switch() const; + + public: + void clear_exit_switch() ; + const ::tint::core::ir::binary::pb::InstructionExitSwitch& exit_switch() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE release_exit_switch(); + ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NONNULL mutable_exit_switch(); + void set_allocated_exit_switch(::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_exit_switch(::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE unsafe_arena_release_exit_switch(); + + private: + const ::tint::core::ir::binary::pb::InstructionExitSwitch& _internal_exit_switch() const; + ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NONNULL _internal_mutable_exit_switch(); + + public: + // .tint.core.ir.binary.pb.InstructionExitLoop exit_loop = 25; + bool has_exit_loop() const; + private: + bool _internal_has_exit_loop() const; + + public: + void clear_exit_loop() ; + const ::tint::core::ir::binary::pb::InstructionExitLoop& exit_loop() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE release_exit_loop(); + ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NONNULL mutable_exit_loop(); + void set_allocated_exit_loop(::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_exit_loop(::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE unsafe_arena_release_exit_loop(); + + private: + const ::tint::core::ir::binary::pb::InstructionExitLoop& _internal_exit_loop() const; + ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NONNULL _internal_mutable_exit_loop(); + + public: + // .tint.core.ir.binary.pb.InstructionNextIteration next_iteration = 26; + bool has_next_iteration() const; + private: + bool _internal_has_next_iteration() const; + + public: + void clear_next_iteration() ; + const ::tint::core::ir::binary::pb::InstructionNextIteration& next_iteration() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE release_next_iteration(); + ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NONNULL mutable_next_iteration(); + void set_allocated_next_iteration(::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_next_iteration(::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE unsafe_arena_release_next_iteration(); + + private: + const ::tint::core::ir::binary::pb::InstructionNextIteration& _internal_next_iteration() const; + ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NONNULL _internal_mutable_next_iteration(); + + public: + // .tint.core.ir.binary.pb.InstructionContinue continue = 27; + bool has_continue_() const; + private: + bool _internal_has_continue_() const; + + public: + void clear_continue_() ; + const ::tint::core::ir::binary::pb::InstructionContinue& continue_() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE release_continue_(); + ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NONNULL mutable_continue_(); + void set_allocated_continue_(::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_continue_(::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE unsafe_arena_release_continue_(); + + private: + const ::tint::core::ir::binary::pb::InstructionContinue& _internal_continue_() const; + ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NONNULL _internal_mutable_continue_(); + + public: + // .tint.core.ir.binary.pb.InstructionBreakIf break_if = 28; + bool has_break_if() const; + private: + bool _internal_has_break_if() const; + + public: + void clear_break_if() ; + const ::tint::core::ir::binary::pb::InstructionBreakIf& break_if() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE release_break_if(); + ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NONNULL mutable_break_if(); + void set_allocated_break_if(::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_break_if(::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE unsafe_arena_release_break_if(); + + private: + const ::tint::core::ir::binary::pb::InstructionBreakIf& _internal_break_if() const; + ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NONNULL _internal_mutable_break_if(); + + public: + // .tint.core.ir.binary.pb.InstructionUnreachable unreachable = 29; + bool has_unreachable() const; + private: + bool _internal_has_unreachable() const; + + public: + void clear_unreachable() ; + const ::tint::core::ir::binary::pb::InstructionUnreachable& unreachable() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE release_unreachable(); + ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NONNULL mutable_unreachable(); + void set_allocated_unreachable(::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_unreachable(::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE unsafe_arena_release_unreachable(); + + private: + const ::tint::core::ir::binary::pb::InstructionUnreachable& _internal_unreachable() const; + ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NONNULL _internal_mutable_unreachable(); + + public: + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Instruction) + private: + class _Internal; + void set_has_return_(); + void set_has_unary(); + void set_has_binary(); + void set_has_discard(); + void set_has_let(); + void set_has_var(); + void set_has_bitcast(); + void set_has_construct(); + void set_has_convert(); + void set_has_access(); + void set_has_user_call(); + void set_has_builtin_call(); + void set_has_load(); + void set_has_store(); + void set_has_load_vector_element(); + void set_has_store_vector_element(); + void set_has_swizzle(); + void set_has_if_(); + void set_has_switch_(); + void set_has_loop(); + void set_has_exit_if(); + void set_has_exit_switch(); + void set_has_exit_loop(); + void set_has_next_iteration(); + void set_has_continue_(); + void set_has_break_if(); + void set_has_unreachable(); + inline bool has_kind() const; + inline void clear_has_kind(); + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 29, + 27, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Instruction& from_msg); + ::google::protobuf::RepeatedField<::uint32_t> operands_; + ::google::protobuf::internal::CachedSize _operands_cached_byte_size_; + ::google::protobuf::RepeatedField<::uint32_t> results_; + ::google::protobuf::internal::CachedSize _results_cached_byte_size_; + union KindUnion { + constexpr KindUnion() : _constinit_{} {} + ::google::protobuf::internal::ConstantInitialized _constinit_; + ::google::protobuf::Message* PROTOBUF_NULLABLE return__; + ::google::protobuf::Message* PROTOBUF_NULLABLE unary_; + ::google::protobuf::Message* PROTOBUF_NULLABLE binary_; + ::google::protobuf::Message* PROTOBUF_NULLABLE discard_; + ::google::protobuf::Message* PROTOBUF_NULLABLE let_; + ::google::protobuf::Message* PROTOBUF_NULLABLE var_; + ::google::protobuf::Message* PROTOBUF_NULLABLE bitcast_; + ::google::protobuf::Message* PROTOBUF_NULLABLE construct_; + ::google::protobuf::Message* PROTOBUF_NULLABLE convert_; + ::google::protobuf::Message* PROTOBUF_NULLABLE access_; + ::google::protobuf::Message* PROTOBUF_NULLABLE user_call_; + ::google::protobuf::Message* PROTOBUF_NULLABLE builtin_call_; + ::google::protobuf::Message* PROTOBUF_NULLABLE load_; + ::google::protobuf::Message* PROTOBUF_NULLABLE store_; + ::google::protobuf::Message* PROTOBUF_NULLABLE load_vector_element_; + ::google::protobuf::Message* PROTOBUF_NULLABLE store_vector_element_; + ::google::protobuf::Message* PROTOBUF_NULLABLE swizzle_; + ::google::protobuf::Message* PROTOBUF_NULLABLE if__; + ::google::protobuf::Message* PROTOBUF_NULLABLE switch__; + ::google::protobuf::Message* PROTOBUF_NULLABLE loop_; + ::google::protobuf::Message* PROTOBUF_NULLABLE exit_if_; + ::google::protobuf::Message* PROTOBUF_NULLABLE exit_switch_; + ::google::protobuf::Message* PROTOBUF_NULLABLE exit_loop_; + ::google::protobuf::Message* PROTOBUF_NULLABLE next_iteration_; + ::google::protobuf::Message* PROTOBUF_NULLABLE continue__; + ::google::protobuf::Message* PROTOBUF_NULLABLE break_if_; + ::google::protobuf::Message* PROTOBUF_NULLABLE unreachable_; + } kind_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t _oneof_case_[1]; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Instruction_class_data_; +// ------------------------------------------------------------------- + +class FunctionParameter final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.FunctionParameter) */ { + public: + inline FunctionParameter() : FunctionParameter(nullptr) {} + ~FunctionParameter() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FunctionParameter* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FunctionParameter)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR FunctionParameter(::google::protobuf::internal::ConstantInitialized); + + inline FunctionParameter(const FunctionParameter& from) : FunctionParameter(nullptr, from) {} + inline FunctionParameter(FunctionParameter&& from) noexcept + : FunctionParameter(nullptr, ::std::move(from)) {} + inline FunctionParameter& operator=(const FunctionParameter& from) { + CopyFrom(from); + return *this; + } + inline FunctionParameter& operator=(FunctionParameter&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FunctionParameter& default_instance() { + return *reinterpret_cast( + &_FunctionParameter_default_instance_); + } + static constexpr int kIndexInFileMessages = 24; + friend void swap(FunctionParameter& a, FunctionParameter& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(FunctionParameter* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FunctionParameter* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FunctionParameter* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const FunctionParameter& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const FunctionParameter& from) { FunctionParameter::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(FunctionParameter* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.FunctionParameter"; } + + protected: + explicit FunctionParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + FunctionParameter(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const FunctionParameter& from); + FunctionParameter( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, FunctionParameter&& from) noexcept + : FunctionParameter(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 2, + kAttributesFieldNumber = 3, + kTypeFieldNumber = 1, + }; + // optional string name = 2; + bool has_name() const; + void clear_name() ; + const ::std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_name(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name(); + void set_allocated_name(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_name() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_name(); + + public: + // optional .tint.core.ir.binary.pb.AttributesFunctionParameter attributes = 3; + bool has_attributes() const; + void clear_attributes() ; + const ::tint::core::ir::binary::pb::AttributesFunctionParameter& attributes() const; + [[nodiscard]] ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE release_attributes(); + ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NONNULL mutable_attributes(); + void set_allocated_attributes(::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_attributes(::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE unsafe_arena_release_attributes(); + + private: + const ::tint::core::ir::binary::pb::AttributesFunctionParameter& _internal_attributes() const; + ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NONNULL _internal_mutable_attributes(); + + public: + // uint32 type = 1; + void clear_type() ; + ::uint32_t type() const; + void set_type(::uint32_t value); + + private: + ::uint32_t _internal_type() const; + void _internal_set_type(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.FunctionParameter) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 1, 53, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const FunctionParameter& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE attributes_; + ::uint32_t type_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull FunctionParameter_class_data_; +// ------------------------------------------------------------------- + +class Value final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Value) */ { + public: + inline Value() : Value(nullptr) {} + ~Value() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Value* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Value)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Value(::google::protobuf::internal::ConstantInitialized); + + inline Value(const Value& from) : Value(nullptr, from) {} + inline Value(Value&& from) noexcept + : Value(nullptr, ::std::move(from)) {} + inline Value& operator=(const Value& from) { + CopyFrom(from); + return *this; + } + inline Value& operator=(Value&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Value& default_instance() { + return *reinterpret_cast( + &_Value_default_instance_); + } + enum KindCase { + kFunction = 1, + kInstructionResult = 2, + kFunctionParameter = 3, + kBlockParameter = 4, + kConstant = 5, + KIND_NOT_SET = 0, + }; + static constexpr int kIndexInFileMessages = 22; + friend void swap(Value& a, Value& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Value* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Value* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Value* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Value& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Value& from) { Value::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Value* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Value"; } + + protected: + explicit Value(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Value(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Value& from); + Value( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Value&& from) noexcept + : Value(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kFunctionFieldNumber = 1, + kInstructionResultFieldNumber = 2, + kFunctionParameterFieldNumber = 3, + kBlockParameterFieldNumber = 4, + kConstantFieldNumber = 5, + }; + // uint32 function = 1; + bool has_function() const; + void clear_function() ; + ::uint32_t function() const; + void set_function(::uint32_t value); + + private: + ::uint32_t _internal_function() const; + void _internal_set_function(::uint32_t value); + + public: + // .tint.core.ir.binary.pb.InstructionResult instruction_result = 2; + bool has_instruction_result() const; + private: + bool _internal_has_instruction_result() const; + + public: + void clear_instruction_result() ; + const ::tint::core::ir::binary::pb::InstructionResult& instruction_result() const; + [[nodiscard]] ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE release_instruction_result(); + ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NONNULL mutable_instruction_result(); + void set_allocated_instruction_result(::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_instruction_result(::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE unsafe_arena_release_instruction_result(); + + private: + const ::tint::core::ir::binary::pb::InstructionResult& _internal_instruction_result() const; + ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NONNULL _internal_mutable_instruction_result(); + + public: + // .tint.core.ir.binary.pb.FunctionParameter function_parameter = 3; + bool has_function_parameter() const; + private: + bool _internal_has_function_parameter() const; + + public: + void clear_function_parameter() ; + const ::tint::core::ir::binary::pb::FunctionParameter& function_parameter() const; + [[nodiscard]] ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE release_function_parameter(); + ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NONNULL mutable_function_parameter(); + void set_allocated_function_parameter(::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_function_parameter(::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE unsafe_arena_release_function_parameter(); + + private: + const ::tint::core::ir::binary::pb::FunctionParameter& _internal_function_parameter() const; + ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NONNULL _internal_mutable_function_parameter(); + + public: + // .tint.core.ir.binary.pb.BlockParameter block_parameter = 4; + bool has_block_parameter() const; + private: + bool _internal_has_block_parameter() const; + + public: + void clear_block_parameter() ; + const ::tint::core::ir::binary::pb::BlockParameter& block_parameter() const; + [[nodiscard]] ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE release_block_parameter(); + ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NONNULL mutable_block_parameter(); + void set_allocated_block_parameter(::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_block_parameter(::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE unsafe_arena_release_block_parameter(); + + private: + const ::tint::core::ir::binary::pb::BlockParameter& _internal_block_parameter() const; + ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NONNULL _internal_mutable_block_parameter(); + + public: + // uint32 constant = 5; + bool has_constant() const; + void clear_constant() ; + ::uint32_t constant() const; + void set_constant(::uint32_t value); + + private: + ::uint32_t _internal_constant() const; + void _internal_set_constant(::uint32_t value); + + public: + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Value) + private: + class _Internal; + void set_has_function(); + void set_has_instruction_result(); + void set_has_function_parameter(); + void set_has_block_parameter(); + void set_has_constant(); + inline bool has_kind() const; + inline void clear_has_kind(); + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 5, + 3, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Value& from_msg); + union KindUnion { + constexpr KindUnion() : _constinit_{} {} + ::google::protobuf::internal::ConstantInitialized _constinit_; + ::uint32_t function_; + ::google::protobuf::Message* PROTOBUF_NULLABLE instruction_result_; + ::google::protobuf::Message* PROTOBUF_NULLABLE function_parameter_; + ::google::protobuf::Message* PROTOBUF_NULLABLE block_parameter_; + ::uint32_t constant_; + } kind_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t _oneof_case_[1]; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Value_class_data_; +// ------------------------------------------------------------------- + +class TypeStruct final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.TypeStruct) */ { + public: + inline TypeStruct() : TypeStruct(nullptr) {} + ~TypeStruct() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TypeStruct* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TypeStruct)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR TypeStruct(::google::protobuf::internal::ConstantInitialized); + + inline TypeStruct(const TypeStruct& from) : TypeStruct(nullptr, from) {} + inline TypeStruct(TypeStruct&& from) noexcept + : TypeStruct(nullptr, ::std::move(from)) {} + inline TypeStruct& operator=(const TypeStruct& from) { + CopyFrom(from); + return *this; + } + inline TypeStruct& operator=(TypeStruct&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const TypeStruct& default_instance() { + return *reinterpret_cast( + &_TypeStruct_default_instance_); + } + static constexpr int kIndexInFileMessages = 7; + friend void swap(TypeStruct& a, TypeStruct& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(TypeStruct* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TypeStruct* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + TypeStruct* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const TypeStruct& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const TypeStruct& from) { TypeStruct::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TypeStruct* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.TypeStruct"; } + + protected: + explicit TypeStruct(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TypeStruct(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TypeStruct& from); + TypeStruct( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TypeStruct&& from) noexcept + : TypeStruct(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kMemberFieldNumber = 2, + kNameFieldNumber = 1, + }; + // repeated .tint.core.ir.binary.pb.TypeStructMember member = 2; + int member_size() const; + private: + int _internal_member_size() const; + + public: + void clear_member() ; + ::tint::core::ir::binary::pb::TypeStructMember* PROTOBUF_NONNULL mutable_member(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>* PROTOBUF_NONNULL mutable_member(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>& _internal_member() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>* PROTOBUF_NONNULL _internal_mutable_member(); + public: + const ::tint::core::ir::binary::pb::TypeStructMember& member(int index) const; + ::tint::core::ir::binary::pb::TypeStructMember* PROTOBUF_NONNULL add_member(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>& member() const; + // string name = 1; + void clear_name() ; + const ::std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_name(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_name(); + void set_allocated_name(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_name() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_name(); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.TypeStruct) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<1, 2, + 1, 46, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TypeStruct& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::TypeStructMember > member_; + ::google::protobuf::internal::ArenaStringPtr name_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull TypeStruct_class_data_; +// ------------------------------------------------------------------- + +class Block final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Block) */ { + public: + inline Block() : Block(nullptr) {} + ~Block() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Block* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Block)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Block(::google::protobuf::internal::ConstantInitialized); + + inline Block(const Block& from) : Block(nullptr, from) {} + inline Block(Block&& from) noexcept + : Block(nullptr, ::std::move(from)) {} + inline Block& operator=(const Block& from) { + CopyFrom(from); + return *this; + } + inline Block& operator=(Block&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Block& default_instance() { + return *reinterpret_cast( + &_Block_default_instance_); + } + static constexpr int kIndexInFileMessages = 32; + friend void swap(Block& a, Block& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Block* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Block* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Block* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Block& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Block& from) { Block::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Block* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Block"; } + + protected: + explicit Block(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Block(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Block& from); + Block( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Block&& from) noexcept + : Block(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kParametersFieldNumber = 1, + kInstructionsFieldNumber = 2, + kIsMultiInFieldNumber = 3, + }; + // repeated uint32 parameters = 1; + int parameters_size() const; + private: + int _internal_parameters_size() const; + + public: + void clear_parameters() ; + ::uint32_t parameters(int index) const; + void set_parameters(int index, ::uint32_t value); + void add_parameters(::uint32_t value); + const ::google::protobuf::RepeatedField<::uint32_t>& parameters() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL mutable_parameters(); + + private: + const ::google::protobuf::RepeatedField<::uint32_t>& _internal_parameters() const; + ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL _internal_mutable_parameters(); + + public: + // repeated .tint.core.ir.binary.pb.Instruction instructions = 2; + int instructions_size() const; + private: + int _internal_instructions_size() const; + + public: + void clear_instructions() ; + ::tint::core::ir::binary::pb::Instruction* PROTOBUF_NONNULL mutable_instructions(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>* PROTOBUF_NONNULL mutable_instructions(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>& _internal_instructions() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>* PROTOBUF_NONNULL _internal_mutable_instructions(); + public: + const ::tint::core::ir::binary::pb::Instruction& instructions(int index) const; + ::tint::core::ir::binary::pb::Instruction* PROTOBUF_NONNULL add_instructions(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>& instructions() const; + // bool is_multi_in = 3; + void clear_is_multi_in() ; + bool is_multi_in() const; + void set_is_multi_in(bool value); + + private: + bool _internal_is_multi_in() const; + void _internal_set_is_multi_in(bool value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Block) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<2, 3, + 1, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Block& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedField<::uint32_t> parameters_; + ::google::protobuf::internal::CachedSize _parameters_cached_byte_size_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::Instruction > instructions_; + bool is_multi_in_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Block_class_data_; +// ------------------------------------------------------------------- + +class Type final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Type) */ { + public: + inline Type() : Type(nullptr) {} + ~Type() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Type* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Type)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Type(::google::protobuf::internal::ConstantInitialized); + + inline Type(const Type& from) : Type(nullptr, from) {} + inline Type(Type&& from) noexcept + : Type(nullptr, ::std::move(from)) {} + inline Type& operator=(const Type& from) { + CopyFrom(from); + return *this; + } + inline Type& operator=(Type&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Type& default_instance() { + return *reinterpret_cast( + &_Type_default_instance_); + } + enum KindCase { + kBasic = 1, + kVector = 2, + kMatrix = 3, + kArray = 4, + kPointer = 5, + kStruct = 6, + kAtomic = 7, + kDepthTexture = 8, + kSampledTexture = 9, + kMultisampledTexture = 10, + kDepthMultisampledTexture = 11, + kStorageTexture = 12, + kExternalTexture = 13, + kSampler = 14, + kInputAttachment = 15, + kSubgroupMatrixLeft = 16, + kSubgroupMatrixRight = 17, + kSubgroupMatrixResult = 18, + kBuiltinStruct = 19, + kBindingArray = 20, + kTexelBuffer = 21, + kBuffer = 23, + KIND_NOT_SET = 0, + }; + static constexpr int kIndexInFileMessages = 1; + friend void swap(Type& a, Type& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Type* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Type* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Type* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Type& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Type& from) { Type::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Type* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Type"; } + + protected: + explicit Type(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Type(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Type& from); + Type( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Type&& from) noexcept + : Type(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kBasicFieldNumber = 1, + kVectorFieldNumber = 2, + kMatrixFieldNumber = 3, + kArrayFieldNumber = 4, + kPointerFieldNumber = 5, + kStructFieldNumber = 6, + kAtomicFieldNumber = 7, + kDepthTextureFieldNumber = 8, + kSampledTextureFieldNumber = 9, + kMultisampledTextureFieldNumber = 10, + kDepthMultisampledTextureFieldNumber = 11, + kStorageTextureFieldNumber = 12, + kExternalTextureFieldNumber = 13, + kSamplerFieldNumber = 14, + kInputAttachmentFieldNumber = 15, + kSubgroupMatrixLeftFieldNumber = 16, + kSubgroupMatrixRightFieldNumber = 17, + kSubgroupMatrixResultFieldNumber = 18, + kBuiltinStructFieldNumber = 19, + kBindingArrayFieldNumber = 20, + kTexelBufferFieldNumber = 21, + kBufferFieldNumber = 23, + }; + // .tint.core.ir.binary.pb.TypeBasic basic = 1; + bool has_basic() const; + void clear_basic() ; + ::tint::core::ir::binary::pb::TypeBasic basic() const; + void set_basic(::tint::core::ir::binary::pb::TypeBasic value); + + private: + ::tint::core::ir::binary::pb::TypeBasic _internal_basic() const; + void _internal_set_basic(::tint::core::ir::binary::pb::TypeBasic value); + + public: + // .tint.core.ir.binary.pb.TypeVector vector = 2; + bool has_vector() const; + private: + bool _internal_has_vector() const; + + public: + void clear_vector() ; + const ::tint::core::ir::binary::pb::TypeVector& vector() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE release_vector(); + ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NONNULL mutable_vector(); + void set_allocated_vector(::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_vector(::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE unsafe_arena_release_vector(); + + private: + const ::tint::core::ir::binary::pb::TypeVector& _internal_vector() const; + ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NONNULL _internal_mutable_vector(); + + public: + // .tint.core.ir.binary.pb.TypeMatrix matrix = 3; + bool has_matrix() const; + private: + bool _internal_has_matrix() const; + + public: + void clear_matrix() ; + const ::tint::core::ir::binary::pb::TypeMatrix& matrix() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE release_matrix(); + ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NONNULL mutable_matrix(); + void set_allocated_matrix(::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_matrix(::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE unsafe_arena_release_matrix(); + + private: + const ::tint::core::ir::binary::pb::TypeMatrix& _internal_matrix() const; + ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NONNULL _internal_mutable_matrix(); + + public: + // .tint.core.ir.binary.pb.TypeArray array = 4; + bool has_array() const; + private: + bool _internal_has_array() const; + + public: + void clear_array() ; + const ::tint::core::ir::binary::pb::TypeArray& array() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE release_array(); + ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NONNULL mutable_array(); + void set_allocated_array(::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_array(::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE unsafe_arena_release_array(); + + private: + const ::tint::core::ir::binary::pb::TypeArray& _internal_array() const; + ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NONNULL _internal_mutable_array(); + + public: + // .tint.core.ir.binary.pb.TypePointer pointer = 5; + bool has_pointer() const; + private: + bool _internal_has_pointer() const; + + public: + void clear_pointer() ; + const ::tint::core::ir::binary::pb::TypePointer& pointer() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE release_pointer(); + ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NONNULL mutable_pointer(); + void set_allocated_pointer(::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_pointer(::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE unsafe_arena_release_pointer(); + + private: + const ::tint::core::ir::binary::pb::TypePointer& _internal_pointer() const; + ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NONNULL _internal_mutable_pointer(); + + public: + // .tint.core.ir.binary.pb.TypeStruct struct = 6; + bool has_struct_() const; + private: + bool _internal_has_struct_() const; + + public: + void clear_struct_() ; + const ::tint::core::ir::binary::pb::TypeStruct& struct_() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE release_struct_(); + ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NONNULL mutable_struct_(); + void set_allocated_struct_(::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_struct_(::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE unsafe_arena_release_struct_(); + + private: + const ::tint::core::ir::binary::pb::TypeStruct& _internal_struct_() const; + ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NONNULL _internal_mutable_struct_(); + + public: + // .tint.core.ir.binary.pb.TypeAtomic atomic = 7; + bool has_atomic() const; + private: + bool _internal_has_atomic() const; + + public: + void clear_atomic() ; + const ::tint::core::ir::binary::pb::TypeAtomic& atomic() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE release_atomic(); + ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NONNULL mutable_atomic(); + void set_allocated_atomic(::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_atomic(::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE unsafe_arena_release_atomic(); + + private: + const ::tint::core::ir::binary::pb::TypeAtomic& _internal_atomic() const; + ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NONNULL _internal_mutable_atomic(); + + public: + // .tint.core.ir.binary.pb.TypeDepthTexture depth_texture = 8; + bool has_depth_texture() const; + private: + bool _internal_has_depth_texture() const; + + public: + void clear_depth_texture() ; + const ::tint::core::ir::binary::pb::TypeDepthTexture& depth_texture() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE release_depth_texture(); + ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NONNULL mutable_depth_texture(); + void set_allocated_depth_texture(::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_depth_texture(::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE unsafe_arena_release_depth_texture(); + + private: + const ::tint::core::ir::binary::pb::TypeDepthTexture& _internal_depth_texture() const; + ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NONNULL _internal_mutable_depth_texture(); + + public: + // .tint.core.ir.binary.pb.TypeSampledTexture sampled_texture = 9; + bool has_sampled_texture() const; + private: + bool _internal_has_sampled_texture() const; + + public: + void clear_sampled_texture() ; + const ::tint::core::ir::binary::pb::TypeSampledTexture& sampled_texture() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE release_sampled_texture(); + ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NONNULL mutable_sampled_texture(); + void set_allocated_sampled_texture(::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_sampled_texture(::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE unsafe_arena_release_sampled_texture(); + + private: + const ::tint::core::ir::binary::pb::TypeSampledTexture& _internal_sampled_texture() const; + ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NONNULL _internal_mutable_sampled_texture(); + + public: + // .tint.core.ir.binary.pb.TypeMultisampledTexture multisampled_texture = 10; + bool has_multisampled_texture() const; + private: + bool _internal_has_multisampled_texture() const; + + public: + void clear_multisampled_texture() ; + const ::tint::core::ir::binary::pb::TypeMultisampledTexture& multisampled_texture() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE release_multisampled_texture(); + ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NONNULL mutable_multisampled_texture(); + void set_allocated_multisampled_texture(::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_multisampled_texture(::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE unsafe_arena_release_multisampled_texture(); + + private: + const ::tint::core::ir::binary::pb::TypeMultisampledTexture& _internal_multisampled_texture() const; + ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NONNULL _internal_mutable_multisampled_texture(); + + public: + // .tint.core.ir.binary.pb.TypeDepthMultisampledTexture depth_multisampled_texture = 11; + bool has_depth_multisampled_texture() const; + private: + bool _internal_has_depth_multisampled_texture() const; + + public: + void clear_depth_multisampled_texture() ; + const ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture& depth_multisampled_texture() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE release_depth_multisampled_texture(); + ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NONNULL mutable_depth_multisampled_texture(); + void set_allocated_depth_multisampled_texture(::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_depth_multisampled_texture(::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE unsafe_arena_release_depth_multisampled_texture(); + + private: + const ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture& _internal_depth_multisampled_texture() const; + ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NONNULL _internal_mutable_depth_multisampled_texture(); + + public: + // .tint.core.ir.binary.pb.TypeStorageTexture storage_texture = 12; + bool has_storage_texture() const; + private: + bool _internal_has_storage_texture() const; + + public: + void clear_storage_texture() ; + const ::tint::core::ir::binary::pb::TypeStorageTexture& storage_texture() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE release_storage_texture(); + ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NONNULL mutable_storage_texture(); + void set_allocated_storage_texture(::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_storage_texture(::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE unsafe_arena_release_storage_texture(); + + private: + const ::tint::core::ir::binary::pb::TypeStorageTexture& _internal_storage_texture() const; + ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NONNULL _internal_mutable_storage_texture(); + + public: + // .tint.core.ir.binary.pb.TypeExternalTexture external_texture = 13; + bool has_external_texture() const; + private: + bool _internal_has_external_texture() const; + + public: + void clear_external_texture() ; + const ::tint::core::ir::binary::pb::TypeExternalTexture& external_texture() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE release_external_texture(); + ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NONNULL mutable_external_texture(); + void set_allocated_external_texture(::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_external_texture(::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE unsafe_arena_release_external_texture(); + + private: + const ::tint::core::ir::binary::pb::TypeExternalTexture& _internal_external_texture() const; + ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NONNULL _internal_mutable_external_texture(); + + public: + // .tint.core.ir.binary.pb.TypeSampler sampler = 14; + bool has_sampler() const; + private: + bool _internal_has_sampler() const; + + public: + void clear_sampler() ; + const ::tint::core::ir::binary::pb::TypeSampler& sampler() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE release_sampler(); + ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NONNULL mutable_sampler(); + void set_allocated_sampler(::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_sampler(::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE unsafe_arena_release_sampler(); + + private: + const ::tint::core::ir::binary::pb::TypeSampler& _internal_sampler() const; + ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NONNULL _internal_mutable_sampler(); + + public: + // .tint.core.ir.binary.pb.TypeInputAttachment input_attachment = 15; + bool has_input_attachment() const; + private: + bool _internal_has_input_attachment() const; + + public: + void clear_input_attachment() ; + const ::tint::core::ir::binary::pb::TypeInputAttachment& input_attachment() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE release_input_attachment(); + ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NONNULL mutable_input_attachment(); + void set_allocated_input_attachment(::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_input_attachment(::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE unsafe_arena_release_input_attachment(); + + private: + const ::tint::core::ir::binary::pb::TypeInputAttachment& _internal_input_attachment() const; + ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NONNULL _internal_mutable_input_attachment(); + + public: + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_left = 16; + bool has_subgroup_matrix_left() const; + private: + bool _internal_has_subgroup_matrix_left() const; + + public: + void clear_subgroup_matrix_left() ; + const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& subgroup_matrix_left() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE release_subgroup_matrix_left(); + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL mutable_subgroup_matrix_left(); + void set_allocated_subgroup_matrix_left(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_subgroup_matrix_left(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE unsafe_arena_release_subgroup_matrix_left(); + + private: + const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& _internal_subgroup_matrix_left() const; + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL _internal_mutable_subgroup_matrix_left(); + + public: + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_right = 17; + bool has_subgroup_matrix_right() const; + private: + bool _internal_has_subgroup_matrix_right() const; + + public: + void clear_subgroup_matrix_right() ; + const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& subgroup_matrix_right() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE release_subgroup_matrix_right(); + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL mutable_subgroup_matrix_right(); + void set_allocated_subgroup_matrix_right(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_subgroup_matrix_right(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE unsafe_arena_release_subgroup_matrix_right(); + + private: + const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& _internal_subgroup_matrix_right() const; + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL _internal_mutable_subgroup_matrix_right(); + + public: + // .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_result = 18; + bool has_subgroup_matrix_result() const; + private: + bool _internal_has_subgroup_matrix_result() const; + + public: + void clear_subgroup_matrix_result() ; + const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& subgroup_matrix_result() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE release_subgroup_matrix_result(); + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL mutable_subgroup_matrix_result(); + void set_allocated_subgroup_matrix_result(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_subgroup_matrix_result(::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE unsafe_arena_release_subgroup_matrix_result(); + + private: + const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& _internal_subgroup_matrix_result() const; + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL _internal_mutable_subgroup_matrix_result(); + + public: + // .tint.core.ir.binary.pb.TypeBuiltinStruct builtin_struct = 19; + bool has_builtin_struct() const; + void clear_builtin_struct() ; + ::tint::core::ir::binary::pb::TypeBuiltinStruct builtin_struct() const; + void set_builtin_struct(::tint::core::ir::binary::pb::TypeBuiltinStruct value); + + private: + ::tint::core::ir::binary::pb::TypeBuiltinStruct _internal_builtin_struct() const; + void _internal_set_builtin_struct(::tint::core::ir::binary::pb::TypeBuiltinStruct value); + + public: + // .tint.core.ir.binary.pb.TypeBindingArray binding_array = 20; + bool has_binding_array() const; + private: + bool _internal_has_binding_array() const; + + public: + void clear_binding_array() ; + const ::tint::core::ir::binary::pb::TypeBindingArray& binding_array() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE release_binding_array(); + ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NONNULL mutable_binding_array(); + void set_allocated_binding_array(::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_binding_array(::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE unsafe_arena_release_binding_array(); + + private: + const ::tint::core::ir::binary::pb::TypeBindingArray& _internal_binding_array() const; + ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NONNULL _internal_mutable_binding_array(); + + public: + // .tint.core.ir.binary.pb.TypeTexelBuffer texel_buffer = 21; + bool has_texel_buffer() const; + private: + bool _internal_has_texel_buffer() const; + + public: + void clear_texel_buffer() ; + const ::tint::core::ir::binary::pb::TypeTexelBuffer& texel_buffer() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE release_texel_buffer(); + ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NONNULL mutable_texel_buffer(); + void set_allocated_texel_buffer(::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_texel_buffer(::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE unsafe_arena_release_texel_buffer(); + + private: + const ::tint::core::ir::binary::pb::TypeTexelBuffer& _internal_texel_buffer() const; + ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NONNULL _internal_mutable_texel_buffer(); + + public: + // .tint.core.ir.binary.pb.TypeBuffer buffer = 23; + bool has_buffer() const; + private: + bool _internal_has_buffer() const; + + public: + void clear_buffer() ; + const ::tint::core::ir::binary::pb::TypeBuffer& buffer() const; + [[nodiscard]] ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE release_buffer(); + ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NONNULL mutable_buffer(); + void set_allocated_buffer(::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_buffer(::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE value); + ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE unsafe_arena_release_buffer(); + + private: + const ::tint::core::ir::binary::pb::TypeBuffer& _internal_buffer() const; + ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NONNULL _internal_mutable_buffer(); + + public: + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Type) + private: + class _Internal; + void set_has_basic(); + void set_has_vector(); + void set_has_matrix(); + void set_has_array(); + void set_has_pointer(); + void set_has_struct_(); + void set_has_atomic(); + void set_has_depth_texture(); + void set_has_sampled_texture(); + void set_has_multisampled_texture(); + void set_has_depth_multisampled_texture(); + void set_has_storage_texture(); + void set_has_external_texture(); + void set_has_sampler(); + void set_has_input_attachment(); + void set_has_subgroup_matrix_left(); + void set_has_subgroup_matrix_right(); + void set_has_subgroup_matrix_result(); + void set_has_builtin_struct(); + void set_has_binding_array(); + void set_has_texel_buffer(); + void set_has_buffer(); + inline bool has_kind() const; + inline void clear_has_kind(); + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<0, 22, + 20, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Type& from_msg); + union KindUnion { + constexpr KindUnion() : _constinit_{} {} + ::google::protobuf::internal::ConstantInitialized _constinit_; + int basic_; + ::google::protobuf::Message* PROTOBUF_NULLABLE vector_; + ::google::protobuf::Message* PROTOBUF_NULLABLE matrix_; + ::google::protobuf::Message* PROTOBUF_NULLABLE array_; + ::google::protobuf::Message* PROTOBUF_NULLABLE pointer_; + ::google::protobuf::Message* PROTOBUF_NULLABLE struct__; + ::google::protobuf::Message* PROTOBUF_NULLABLE atomic_; + ::google::protobuf::Message* PROTOBUF_NULLABLE depth_texture_; + ::google::protobuf::Message* PROTOBUF_NULLABLE sampled_texture_; + ::google::protobuf::Message* PROTOBUF_NULLABLE multisampled_texture_; + ::google::protobuf::Message* PROTOBUF_NULLABLE depth_multisampled_texture_; + ::google::protobuf::Message* PROTOBUF_NULLABLE storage_texture_; + ::google::protobuf::Message* PROTOBUF_NULLABLE external_texture_; + ::google::protobuf::Message* PROTOBUF_NULLABLE sampler_; + ::google::protobuf::Message* PROTOBUF_NULLABLE input_attachment_; + ::google::protobuf::Message* PROTOBUF_NULLABLE subgroup_matrix_left_; + ::google::protobuf::Message* PROTOBUF_NULLABLE subgroup_matrix_right_; + ::google::protobuf::Message* PROTOBUF_NULLABLE subgroup_matrix_result_; + int builtin_struct_; + ::google::protobuf::Message* PROTOBUF_NULLABLE binding_array_; + ::google::protobuf::Message* PROTOBUF_NULLABLE texel_buffer_; + ::google::protobuf::Message* PROTOBUF_NULLABLE buffer_; + } kind_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t _oneof_case_[1]; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Type_class_data_; +// ------------------------------------------------------------------- + +class Module final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:tint.core.ir.binary.pb.Module) */ { + public: + inline Module() : Module(nullptr) {} + ~Module() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Module* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Module)); + } +#endif + + template + explicit PROTOBUF_CONSTEXPR Module(::google::protobuf::internal::ConstantInitialized); + + inline Module(const Module& from) : Module(nullptr, from) {} + inline Module(Module&& from) noexcept + : Module(nullptr, ::std::move(from)) {} + inline Module& operator=(const Module& from) { + CopyFrom(from); + return *this; + } + inline Module& operator=(Module&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Module& default_instance() { + return *reinterpret_cast( + &_Module_default_instance_); + } + static constexpr int kIndexInFileMessages = 0; + friend void swap(Module& a, Module& b) { a.Swap(&b); } + PROTOBUF_NOINLINE void Swap(Module* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Module* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Module* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Module& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const Module& from) { Module::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + ::size_t ByteSizeLong() const final; + ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Module* PROTOBUF_NONNULL other); + private: + template + friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)(); + static ::absl::string_view FullMessageName() { return "tint.core.ir.binary.pb.Module"; } + + protected: + explicit Module(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Module(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Module& from); + Module( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Module&& from) noexcept + : Module(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_(); + + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kTypesFieldNumber = 1, + kValuesFieldNumber = 2, + kConstantValuesFieldNumber = 3, + kFunctionsFieldNumber = 4, + kBlocksFieldNumber = 5, + kRootBlockFieldNumber = 6, + }; + // repeated .tint.core.ir.binary.pb.Type types = 1; + int types_size() const; + private: + int _internal_types_size() const; + + public: + void clear_types() ; + ::tint::core::ir::binary::pb::Type* PROTOBUF_NONNULL mutable_types(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>* PROTOBUF_NONNULL mutable_types(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>& _internal_types() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>* PROTOBUF_NONNULL _internal_mutable_types(); + public: + const ::tint::core::ir::binary::pb::Type& types(int index) const; + ::tint::core::ir::binary::pb::Type* PROTOBUF_NONNULL add_types(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>& types() const; + // repeated .tint.core.ir.binary.pb.Value values = 2; + int values_size() const; + private: + int _internal_values_size() const; + + public: + void clear_values() ; + ::tint::core::ir::binary::pb::Value* PROTOBUF_NONNULL mutable_values(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>* PROTOBUF_NONNULL mutable_values(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>& _internal_values() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>* PROTOBUF_NONNULL _internal_mutable_values(); + public: + const ::tint::core::ir::binary::pb::Value& values(int index) const; + ::tint::core::ir::binary::pb::Value* PROTOBUF_NONNULL add_values(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>& values() const; + // repeated .tint.core.ir.binary.pb.ConstantValue constant_values = 3; + int constant_values_size() const; + private: + int _internal_constant_values_size() const; + + public: + void clear_constant_values() ; + ::tint::core::ir::binary::pb::ConstantValue* PROTOBUF_NONNULL mutable_constant_values(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>* PROTOBUF_NONNULL mutable_constant_values(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>& _internal_constant_values() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>* PROTOBUF_NONNULL _internal_mutable_constant_values(); + public: + const ::tint::core::ir::binary::pb::ConstantValue& constant_values(int index) const; + ::tint::core::ir::binary::pb::ConstantValue* PROTOBUF_NONNULL add_constant_values(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>& constant_values() const; + // repeated .tint.core.ir.binary.pb.Function functions = 4; + int functions_size() const; + private: + int _internal_functions_size() const; + + public: + void clear_functions() ; + ::tint::core::ir::binary::pb::Function* PROTOBUF_NONNULL mutable_functions(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>* PROTOBUF_NONNULL mutable_functions(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>& _internal_functions() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>* PROTOBUF_NONNULL _internal_mutable_functions(); + public: + const ::tint::core::ir::binary::pb::Function& functions(int index) const; + ::tint::core::ir::binary::pb::Function* PROTOBUF_NONNULL add_functions(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>& functions() const; + // repeated .tint.core.ir.binary.pb.Block blocks = 5; + int blocks_size() const; + private: + int _internal_blocks_size() const; + + public: + void clear_blocks() ; + ::tint::core::ir::binary::pb::Block* PROTOBUF_NONNULL mutable_blocks(int index); + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>* PROTOBUF_NONNULL mutable_blocks(); + + private: + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>& _internal_blocks() const; + ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>* PROTOBUF_NONNULL _internal_mutable_blocks(); + public: + const ::tint::core::ir::binary::pb::Block& blocks(int index) const; + ::tint::core::ir::binary::pb::Block* PROTOBUF_NONNULL add_blocks(); + const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>& blocks() const; + // uint32 root_block = 6; + void clear_root_block() ; + ::uint32_t root_block() const; + void set_root_block(::uint32_t value); + + private: + ::uint32_t _internal_root_block() const; + void _internal_set_root_block(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:tint.core.ir.binary.pb.Module) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable<3, 6, + 5, 0, + 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Module& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::Type > types_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::Value > values_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::ConstantValue > constant_values_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::Function > functions_; + ::google::protobuf::RepeatedPtrField< ::tint::core::ir::binary::pb::Block > blocks_; + ::uint32_t root_block_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_src_2ftint_2futils_2fprotos_2fir_2fir_2eproto; +}; + +extern const ::google::protobuf::internal::ClassDataFull Module_class_data_; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// Module + +// repeated .tint.core.ir.binary.pb.Type types = 1; +inline int Module::_internal_types_size() const { + return _internal_types().size(); +} +inline int Module::types_size() const { + return _internal_types_size(); +} +inline void Module::clear_types() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.types_.Clear(); +} +inline ::tint::core::ir::binary::pb::Type* PROTOBUF_NONNULL Module::mutable_types(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Module.types) + return _internal_mutable_types()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>* PROTOBUF_NONNULL Module::mutable_types() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Module.types) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_types(); +} +inline const ::tint::core::ir::binary::pb::Type& Module::types(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Module.types) + return _internal_types().Get(index); +} +inline ::tint::core::ir::binary::pb::Type* PROTOBUF_NONNULL Module::add_types() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::Type* _add = _internal_mutable_types()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Module.types) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>& Module::types() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Module.types) + return _internal_types(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>& +Module::_internal_types() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.types_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Type>* PROTOBUF_NONNULL +Module::_internal_mutable_types() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.types_; +} + +// repeated .tint.core.ir.binary.pb.Value values = 2; +inline int Module::_internal_values_size() const { + return _internal_values().size(); +} +inline int Module::values_size() const { + return _internal_values_size(); +} +inline void Module::clear_values() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.values_.Clear(); +} +inline ::tint::core::ir::binary::pb::Value* PROTOBUF_NONNULL Module::mutable_values(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Module.values) + return _internal_mutable_values()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>* PROTOBUF_NONNULL Module::mutable_values() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Module.values) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_values(); +} +inline const ::tint::core::ir::binary::pb::Value& Module::values(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Module.values) + return _internal_values().Get(index); +} +inline ::tint::core::ir::binary::pb::Value* PROTOBUF_NONNULL Module::add_values() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::Value* _add = _internal_mutable_values()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Module.values) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>& Module::values() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Module.values) + return _internal_values(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>& +Module::_internal_values() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.values_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Value>* PROTOBUF_NONNULL +Module::_internal_mutable_values() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.values_; +} + +// repeated .tint.core.ir.binary.pb.ConstantValue constant_values = 3; +inline int Module::_internal_constant_values_size() const { + return _internal_constant_values().size(); +} +inline int Module::constant_values_size() const { + return _internal_constant_values_size(); +} +inline void Module::clear_constant_values() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.constant_values_.Clear(); +} +inline ::tint::core::ir::binary::pb::ConstantValue* PROTOBUF_NONNULL Module::mutable_constant_values(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Module.constant_values) + return _internal_mutable_constant_values()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>* PROTOBUF_NONNULL Module::mutable_constant_values() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Module.constant_values) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_constant_values(); +} +inline const ::tint::core::ir::binary::pb::ConstantValue& Module::constant_values(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Module.constant_values) + return _internal_constant_values().Get(index); +} +inline ::tint::core::ir::binary::pb::ConstantValue* PROTOBUF_NONNULL Module::add_constant_values() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::ConstantValue* _add = _internal_mutable_constant_values()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Module.constant_values) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>& Module::constant_values() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Module.constant_values) + return _internal_constant_values(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>& +Module::_internal_constant_values() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.constant_values_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::ConstantValue>* PROTOBUF_NONNULL +Module::_internal_mutable_constant_values() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.constant_values_; +} + +// repeated .tint.core.ir.binary.pb.Function functions = 4; +inline int Module::_internal_functions_size() const { + return _internal_functions().size(); +} +inline int Module::functions_size() const { + return _internal_functions_size(); +} +inline void Module::clear_functions() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.functions_.Clear(); +} +inline ::tint::core::ir::binary::pb::Function* PROTOBUF_NONNULL Module::mutable_functions(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Module.functions) + return _internal_mutable_functions()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>* PROTOBUF_NONNULL Module::mutable_functions() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Module.functions) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_functions(); +} +inline const ::tint::core::ir::binary::pb::Function& Module::functions(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Module.functions) + return _internal_functions().Get(index); +} +inline ::tint::core::ir::binary::pb::Function* PROTOBUF_NONNULL Module::add_functions() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::Function* _add = _internal_mutable_functions()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Module.functions) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>& Module::functions() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Module.functions) + return _internal_functions(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>& +Module::_internal_functions() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.functions_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Function>* PROTOBUF_NONNULL +Module::_internal_mutable_functions() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.functions_; +} + +// repeated .tint.core.ir.binary.pb.Block blocks = 5; +inline int Module::_internal_blocks_size() const { + return _internal_blocks().size(); +} +inline int Module::blocks_size() const { + return _internal_blocks_size(); +} +inline void Module::clear_blocks() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.blocks_.Clear(); +} +inline ::tint::core::ir::binary::pb::Block* PROTOBUF_NONNULL Module::mutable_blocks(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Module.blocks) + return _internal_mutable_blocks()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>* PROTOBUF_NONNULL Module::mutable_blocks() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Module.blocks) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_blocks(); +} +inline const ::tint::core::ir::binary::pb::Block& Module::blocks(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Module.blocks) + return _internal_blocks().Get(index); +} +inline ::tint::core::ir::binary::pb::Block* PROTOBUF_NONNULL Module::add_blocks() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::Block* _add = _internal_mutable_blocks()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Module.blocks) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>& Module::blocks() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Module.blocks) + return _internal_blocks(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>& +Module::_internal_blocks() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.blocks_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Block>* PROTOBUF_NONNULL +Module::_internal_mutable_blocks() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.blocks_; +} + +// uint32 root_block = 6; +inline void Module::clear_root_block() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.root_block_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t Module::root_block() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Module.root_block) + return _internal_root_block(); +} +inline void Module::set_root_block(::uint32_t value) { + _internal_set_root_block(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Module.root_block) +} +inline ::uint32_t Module::_internal_root_block() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.root_block_; +} +inline void Module::_internal_set_root_block(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.root_block_ = value; +} + +// ------------------------------------------------------------------- + +// Type + +// .tint.core.ir.binary.pb.TypeBasic basic = 1; +inline bool Type::has_basic() const { + return kind_case() == kBasic; +} +inline void Type::set_has_basic() { + _impl_._oneof_case_[0] = kBasic; +} +inline void Type::clear_basic() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBasic) { + _impl_.kind_.basic_ = 0; + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeBasic Type::basic() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.basic) + return _internal_basic(); +} +inline void Type::set_basic(::tint::core::ir::binary::pb::TypeBasic value) { + if (kind_case() != kBasic) { + clear_kind(); + set_has_basic(); + } + _impl_.kind_.basic_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Type.basic) +} +inline ::tint::core::ir::binary::pb::TypeBasic Type::_internal_basic() const { + if (kind_case() == kBasic) { + return static_cast<::tint::core::ir::binary::pb::TypeBasic>(_impl_.kind_.basic_); + } + return static_cast<::tint::core::ir::binary::pb::TypeBasic>(0); +} + +// .tint.core.ir.binary.pb.TypeVector vector = 2; +inline bool Type::has_vector() const { + return kind_case() == kVector; +} +inline bool Type::_internal_has_vector() const { + return kind_case() == kVector; +} +inline void Type::set_has_vector() { + _impl_._oneof_case_[0] = kVector; +} +inline void Type::clear_vector() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kVector) { + if (GetArena() == nullptr) { + delete _impl_.kind_.vector_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.vector_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE Type::release_vector() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.vector) + if (kind_case() == kVector) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeVector*>(_impl_.kind_.vector_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.vector_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeVector& Type::_internal_vector() const { + return kind_case() == kVector ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeVector*>(_impl_.kind_.vector_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeVector&>(::tint::core::ir::binary::pb::_TypeVector_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeVector& Type::vector() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.vector) + return _internal_vector(); +} +inline ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE Type::unsafe_arena_release_vector() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.vector) + if (kind_case() == kVector) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeVector*>(_impl_.kind_.vector_); + _impl_.kind_.vector_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_vector( + ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_vector(); + _impl_.kind_.vector_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.vector) +} +inline ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NONNULL Type::_internal_mutable_vector() { + if (kind_case() != kVector) { + clear_kind(); + set_has_vector(); + _impl_.kind_.vector_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeVector>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeVector*>(_impl_.kind_.vector_); +} +inline ::tint::core::ir::binary::pb::TypeVector* PROTOBUF_NONNULL Type::mutable_vector() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeVector* _msg = _internal_mutable_vector(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.vector) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeMatrix matrix = 3; +inline bool Type::has_matrix() const { + return kind_case() == kMatrix; +} +inline bool Type::_internal_has_matrix() const { + return kind_case() == kMatrix; +} +inline void Type::set_has_matrix() { + _impl_._oneof_case_[0] = kMatrix; +} +inline void Type::clear_matrix() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kMatrix) { + if (GetArena() == nullptr) { + delete _impl_.kind_.matrix_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.matrix_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE Type::release_matrix() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.matrix) + if (kind_case() == kMatrix) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeMatrix*>(_impl_.kind_.matrix_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.matrix_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeMatrix& Type::_internal_matrix() const { + return kind_case() == kMatrix ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeMatrix*>(_impl_.kind_.matrix_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeMatrix&>(::tint::core::ir::binary::pb::_TypeMatrix_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeMatrix& Type::matrix() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.matrix) + return _internal_matrix(); +} +inline ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE Type::unsafe_arena_release_matrix() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.matrix) + if (kind_case() == kMatrix) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeMatrix*>(_impl_.kind_.matrix_); + _impl_.kind_.matrix_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_matrix( + ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_matrix(); + _impl_.kind_.matrix_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.matrix) +} +inline ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NONNULL Type::_internal_mutable_matrix() { + if (kind_case() != kMatrix) { + clear_kind(); + set_has_matrix(); + _impl_.kind_.matrix_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeMatrix>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeMatrix*>(_impl_.kind_.matrix_); +} +inline ::tint::core::ir::binary::pb::TypeMatrix* PROTOBUF_NONNULL Type::mutable_matrix() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeMatrix* _msg = _internal_mutable_matrix(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.matrix) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeArray array = 4; +inline bool Type::has_array() const { + return kind_case() == kArray; +} +inline bool Type::_internal_has_array() const { + return kind_case() == kArray; +} +inline void Type::set_has_array() { + _impl_._oneof_case_[0] = kArray; +} +inline void Type::clear_array() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kArray) { + if (GetArena() == nullptr) { + delete _impl_.kind_.array_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.array_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE Type::release_array() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.array) + if (kind_case() == kArray) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeArray*>(_impl_.kind_.array_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.array_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeArray& Type::_internal_array() const { + return kind_case() == kArray ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeArray*>(_impl_.kind_.array_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeArray&>(::tint::core::ir::binary::pb::_TypeArray_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeArray& Type::array() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.array) + return _internal_array(); +} +inline ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE Type::unsafe_arena_release_array() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.array) + if (kind_case() == kArray) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeArray*>(_impl_.kind_.array_); + _impl_.kind_.array_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_array( + ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_array(); + _impl_.kind_.array_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.array) +} +inline ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NONNULL Type::_internal_mutable_array() { + if (kind_case() != kArray) { + clear_kind(); + set_has_array(); + _impl_.kind_.array_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeArray>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeArray*>(_impl_.kind_.array_); +} +inline ::tint::core::ir::binary::pb::TypeArray* PROTOBUF_NONNULL Type::mutable_array() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeArray* _msg = _internal_mutable_array(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.array) + return _msg; +} + +// .tint.core.ir.binary.pb.TypePointer pointer = 5; +inline bool Type::has_pointer() const { + return kind_case() == kPointer; +} +inline bool Type::_internal_has_pointer() const { + return kind_case() == kPointer; +} +inline void Type::set_has_pointer() { + _impl_._oneof_case_[0] = kPointer; +} +inline void Type::clear_pointer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kPointer) { + if (GetArena() == nullptr) { + delete _impl_.kind_.pointer_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.pointer_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE Type::release_pointer() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.pointer) + if (kind_case() == kPointer) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypePointer*>(_impl_.kind_.pointer_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.pointer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypePointer& Type::_internal_pointer() const { + return kind_case() == kPointer ? *reinterpret_cast<::tint::core::ir::binary::pb::TypePointer*>(_impl_.kind_.pointer_) : reinterpret_cast<::tint::core::ir::binary::pb::TypePointer&>(::tint::core::ir::binary::pb::_TypePointer_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypePointer& Type::pointer() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.pointer) + return _internal_pointer(); +} +inline ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE Type::unsafe_arena_release_pointer() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.pointer) + if (kind_case() == kPointer) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypePointer*>(_impl_.kind_.pointer_); + _impl_.kind_.pointer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_pointer( + ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_pointer(); + _impl_.kind_.pointer_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.pointer) +} +inline ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NONNULL Type::_internal_mutable_pointer() { + if (kind_case() != kPointer) { + clear_kind(); + set_has_pointer(); + _impl_.kind_.pointer_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypePointer>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypePointer*>(_impl_.kind_.pointer_); +} +inline ::tint::core::ir::binary::pb::TypePointer* PROTOBUF_NONNULL Type::mutable_pointer() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypePointer* _msg = _internal_mutable_pointer(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.pointer) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeStruct struct = 6; +inline bool Type::has_struct_() const { + return kind_case() == kStruct; +} +inline bool Type::_internal_has_struct_() const { + return kind_case() == kStruct; +} +inline void Type::set_has_struct_() { + _impl_._oneof_case_[0] = kStruct; +} +inline void Type::clear_struct_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kStruct) { + if (GetArena() == nullptr) { + delete _impl_.kind_.struct__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.struct__); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE Type::release_struct_() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.struct) + if (kind_case() == kStruct) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeStruct*>(_impl_.kind_.struct__); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.struct__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeStruct& Type::_internal_struct_() const { + return kind_case() == kStruct ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeStruct*>(_impl_.kind_.struct__) : reinterpret_cast<::tint::core::ir::binary::pb::TypeStruct&>(::tint::core::ir::binary::pb::_TypeStruct_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeStruct& Type::struct_() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.struct) + return _internal_struct_(); +} +inline ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE Type::unsafe_arena_release_struct_() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.struct) + if (kind_case() == kStruct) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeStruct*>(_impl_.kind_.struct__); + _impl_.kind_.struct__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_struct_( + ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_struct_(); + _impl_.kind_.struct__ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.struct) +} +inline ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NONNULL Type::_internal_mutable_struct_() { + if (kind_case() != kStruct) { + clear_kind(); + set_has_struct_(); + _impl_.kind_.struct__ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeStruct>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeStruct*>(_impl_.kind_.struct__); +} +inline ::tint::core::ir::binary::pb::TypeStruct* PROTOBUF_NONNULL Type::mutable_struct_() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeStruct* _msg = _internal_mutable_struct_(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.struct) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeAtomic atomic = 7; +inline bool Type::has_atomic() const { + return kind_case() == kAtomic; +} +inline bool Type::_internal_has_atomic() const { + return kind_case() == kAtomic; +} +inline void Type::set_has_atomic() { + _impl_._oneof_case_[0] = kAtomic; +} +inline void Type::clear_atomic() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kAtomic) { + if (GetArena() == nullptr) { + delete _impl_.kind_.atomic_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.atomic_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE Type::release_atomic() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.atomic) + if (kind_case() == kAtomic) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeAtomic*>(_impl_.kind_.atomic_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.atomic_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeAtomic& Type::_internal_atomic() const { + return kind_case() == kAtomic ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeAtomic*>(_impl_.kind_.atomic_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeAtomic&>(::tint::core::ir::binary::pb::_TypeAtomic_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeAtomic& Type::atomic() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.atomic) + return _internal_atomic(); +} +inline ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE Type::unsafe_arena_release_atomic() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.atomic) + if (kind_case() == kAtomic) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeAtomic*>(_impl_.kind_.atomic_); + _impl_.kind_.atomic_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_atomic( + ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_atomic(); + _impl_.kind_.atomic_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.atomic) +} +inline ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NONNULL Type::_internal_mutable_atomic() { + if (kind_case() != kAtomic) { + clear_kind(); + set_has_atomic(); + _impl_.kind_.atomic_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeAtomic>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeAtomic*>(_impl_.kind_.atomic_); +} +inline ::tint::core::ir::binary::pb::TypeAtomic* PROTOBUF_NONNULL Type::mutable_atomic() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeAtomic* _msg = _internal_mutable_atomic(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.atomic) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeDepthTexture depth_texture = 8; +inline bool Type::has_depth_texture() const { + return kind_case() == kDepthTexture; +} +inline bool Type::_internal_has_depth_texture() const { + return kind_case() == kDepthTexture; +} +inline void Type::set_has_depth_texture() { + _impl_._oneof_case_[0] = kDepthTexture; +} +inline void Type::clear_depth_texture() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kDepthTexture) { + if (GetArena() == nullptr) { + delete _impl_.kind_.depth_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.depth_texture_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE Type::release_depth_texture() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.depth_texture) + if (kind_case() == kDepthTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthTexture*>(_impl_.kind_.depth_texture_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.depth_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeDepthTexture& Type::_internal_depth_texture() const { + return kind_case() == kDepthTexture ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthTexture*>(_impl_.kind_.depth_texture_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthTexture&>(::tint::core::ir::binary::pb::_TypeDepthTexture_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeDepthTexture& Type::depth_texture() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.depth_texture) + return _internal_depth_texture(); +} +inline ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE Type::unsafe_arena_release_depth_texture() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.depth_texture) + if (kind_case() == kDepthTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthTexture*>(_impl_.kind_.depth_texture_); + _impl_.kind_.depth_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_depth_texture( + ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_depth_texture(); + _impl_.kind_.depth_texture_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.depth_texture) +} +inline ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NONNULL Type::_internal_mutable_depth_texture() { + if (kind_case() != kDepthTexture) { + clear_kind(); + set_has_depth_texture(); + _impl_.kind_.depth_texture_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeDepthTexture>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthTexture*>(_impl_.kind_.depth_texture_); +} +inline ::tint::core::ir::binary::pb::TypeDepthTexture* PROTOBUF_NONNULL Type::mutable_depth_texture() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeDepthTexture* _msg = _internal_mutable_depth_texture(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.depth_texture) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeSampledTexture sampled_texture = 9; +inline bool Type::has_sampled_texture() const { + return kind_case() == kSampledTexture; +} +inline bool Type::_internal_has_sampled_texture() const { + return kind_case() == kSampledTexture; +} +inline void Type::set_has_sampled_texture() { + _impl_._oneof_case_[0] = kSampledTexture; +} +inline void Type::clear_sampled_texture() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSampledTexture) { + if (GetArena() == nullptr) { + delete _impl_.kind_.sampled_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.sampled_texture_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE Type::release_sampled_texture() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.sampled_texture) + if (kind_case() == kSampledTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSampledTexture*>(_impl_.kind_.sampled_texture_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.sampled_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeSampledTexture& Type::_internal_sampled_texture() const { + return kind_case() == kSampledTexture ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeSampledTexture*>(_impl_.kind_.sampled_texture_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeSampledTexture&>(::tint::core::ir::binary::pb::_TypeSampledTexture_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeSampledTexture& Type::sampled_texture() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.sampled_texture) + return _internal_sampled_texture(); +} +inline ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE Type::unsafe_arena_release_sampled_texture() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.sampled_texture) + if (kind_case() == kSampledTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSampledTexture*>(_impl_.kind_.sampled_texture_); + _impl_.kind_.sampled_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_sampled_texture( + ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_sampled_texture(); + _impl_.kind_.sampled_texture_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.sampled_texture) +} +inline ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NONNULL Type::_internal_mutable_sampled_texture() { + if (kind_case() != kSampledTexture) { + clear_kind(); + set_has_sampled_texture(); + _impl_.kind_.sampled_texture_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeSampledTexture>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeSampledTexture*>(_impl_.kind_.sampled_texture_); +} +inline ::tint::core::ir::binary::pb::TypeSampledTexture* PROTOBUF_NONNULL Type::mutable_sampled_texture() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeSampledTexture* _msg = _internal_mutable_sampled_texture(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.sampled_texture) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeMultisampledTexture multisampled_texture = 10; +inline bool Type::has_multisampled_texture() const { + return kind_case() == kMultisampledTexture; +} +inline bool Type::_internal_has_multisampled_texture() const { + return kind_case() == kMultisampledTexture; +} +inline void Type::set_has_multisampled_texture() { + _impl_._oneof_case_[0] = kMultisampledTexture; +} +inline void Type::clear_multisampled_texture() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kMultisampledTexture) { + if (GetArena() == nullptr) { + delete _impl_.kind_.multisampled_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.multisampled_texture_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE Type::release_multisampled_texture() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.multisampled_texture) + if (kind_case() == kMultisampledTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeMultisampledTexture*>(_impl_.kind_.multisampled_texture_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.multisampled_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeMultisampledTexture& Type::_internal_multisampled_texture() const { + return kind_case() == kMultisampledTexture ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeMultisampledTexture*>(_impl_.kind_.multisampled_texture_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeMultisampledTexture&>(::tint::core::ir::binary::pb::_TypeMultisampledTexture_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeMultisampledTexture& Type::multisampled_texture() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.multisampled_texture) + return _internal_multisampled_texture(); +} +inline ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE Type::unsafe_arena_release_multisampled_texture() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.multisampled_texture) + if (kind_case() == kMultisampledTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeMultisampledTexture*>(_impl_.kind_.multisampled_texture_); + _impl_.kind_.multisampled_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_multisampled_texture( + ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_multisampled_texture(); + _impl_.kind_.multisampled_texture_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.multisampled_texture) +} +inline ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NONNULL Type::_internal_mutable_multisampled_texture() { + if (kind_case() != kMultisampledTexture) { + clear_kind(); + set_has_multisampled_texture(); + _impl_.kind_.multisampled_texture_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeMultisampledTexture>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeMultisampledTexture*>(_impl_.kind_.multisampled_texture_); +} +inline ::tint::core::ir::binary::pb::TypeMultisampledTexture* PROTOBUF_NONNULL Type::mutable_multisampled_texture() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeMultisampledTexture* _msg = _internal_mutable_multisampled_texture(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.multisampled_texture) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeDepthMultisampledTexture depth_multisampled_texture = 11; +inline bool Type::has_depth_multisampled_texture() const { + return kind_case() == kDepthMultisampledTexture; +} +inline bool Type::_internal_has_depth_multisampled_texture() const { + return kind_case() == kDepthMultisampledTexture; +} +inline void Type::set_has_depth_multisampled_texture() { + _impl_._oneof_case_[0] = kDepthMultisampledTexture; +} +inline void Type::clear_depth_multisampled_texture() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kDepthMultisampledTexture) { + if (GetArena() == nullptr) { + delete _impl_.kind_.depth_multisampled_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.depth_multisampled_texture_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE Type::release_depth_multisampled_texture() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.depth_multisampled_texture) + if (kind_case() == kDepthMultisampledTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture*>(_impl_.kind_.depth_multisampled_texture_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.depth_multisampled_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture& Type::_internal_depth_multisampled_texture() const { + return kind_case() == kDepthMultisampledTexture ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture*>(_impl_.kind_.depth_multisampled_texture_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture&>(::tint::core::ir::binary::pb::_TypeDepthMultisampledTexture_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture& Type::depth_multisampled_texture() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.depth_multisampled_texture) + return _internal_depth_multisampled_texture(); +} +inline ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE Type::unsafe_arena_release_depth_multisampled_texture() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.depth_multisampled_texture) + if (kind_case() == kDepthMultisampledTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture*>(_impl_.kind_.depth_multisampled_texture_); + _impl_.kind_.depth_multisampled_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_depth_multisampled_texture( + ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_depth_multisampled_texture(); + _impl_.kind_.depth_multisampled_texture_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.depth_multisampled_texture) +} +inline ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NONNULL Type::_internal_mutable_depth_multisampled_texture() { + if (kind_case() != kDepthMultisampledTexture) { + clear_kind(); + set_has_depth_multisampled_texture(); + _impl_.kind_.depth_multisampled_texture_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeDepthMultisampledTexture*>(_impl_.kind_.depth_multisampled_texture_); +} +inline ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* PROTOBUF_NONNULL Type::mutable_depth_multisampled_texture() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeDepthMultisampledTexture* _msg = _internal_mutable_depth_multisampled_texture(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.depth_multisampled_texture) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeStorageTexture storage_texture = 12; +inline bool Type::has_storage_texture() const { + return kind_case() == kStorageTexture; +} +inline bool Type::_internal_has_storage_texture() const { + return kind_case() == kStorageTexture; +} +inline void Type::set_has_storage_texture() { + _impl_._oneof_case_[0] = kStorageTexture; +} +inline void Type::clear_storage_texture() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kStorageTexture) { + if (GetArena() == nullptr) { + delete _impl_.kind_.storage_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.storage_texture_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE Type::release_storage_texture() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.storage_texture) + if (kind_case() == kStorageTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeStorageTexture*>(_impl_.kind_.storage_texture_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.storage_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeStorageTexture& Type::_internal_storage_texture() const { + return kind_case() == kStorageTexture ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeStorageTexture*>(_impl_.kind_.storage_texture_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeStorageTexture&>(::tint::core::ir::binary::pb::_TypeStorageTexture_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeStorageTexture& Type::storage_texture() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.storage_texture) + return _internal_storage_texture(); +} +inline ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE Type::unsafe_arena_release_storage_texture() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.storage_texture) + if (kind_case() == kStorageTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeStorageTexture*>(_impl_.kind_.storage_texture_); + _impl_.kind_.storage_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_storage_texture( + ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_storage_texture(); + _impl_.kind_.storage_texture_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.storage_texture) +} +inline ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NONNULL Type::_internal_mutable_storage_texture() { + if (kind_case() != kStorageTexture) { + clear_kind(); + set_has_storage_texture(); + _impl_.kind_.storage_texture_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeStorageTexture>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeStorageTexture*>(_impl_.kind_.storage_texture_); +} +inline ::tint::core::ir::binary::pb::TypeStorageTexture* PROTOBUF_NONNULL Type::mutable_storage_texture() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeStorageTexture* _msg = _internal_mutable_storage_texture(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.storage_texture) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeExternalTexture external_texture = 13; +inline bool Type::has_external_texture() const { + return kind_case() == kExternalTexture; +} +inline bool Type::_internal_has_external_texture() const { + return kind_case() == kExternalTexture; +} +inline void Type::set_has_external_texture() { + _impl_._oneof_case_[0] = kExternalTexture; +} +inline void Type::clear_external_texture() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kExternalTexture) { + if (GetArena() == nullptr) { + delete _impl_.kind_.external_texture_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.external_texture_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE Type::release_external_texture() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.external_texture) + if (kind_case() == kExternalTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeExternalTexture*>(_impl_.kind_.external_texture_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.external_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeExternalTexture& Type::_internal_external_texture() const { + return kind_case() == kExternalTexture ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeExternalTexture*>(_impl_.kind_.external_texture_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeExternalTexture&>(::tint::core::ir::binary::pb::_TypeExternalTexture_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeExternalTexture& Type::external_texture() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.external_texture) + return _internal_external_texture(); +} +inline ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE Type::unsafe_arena_release_external_texture() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.external_texture) + if (kind_case() == kExternalTexture) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeExternalTexture*>(_impl_.kind_.external_texture_); + _impl_.kind_.external_texture_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_external_texture( + ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_external_texture(); + _impl_.kind_.external_texture_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.external_texture) +} +inline ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NONNULL Type::_internal_mutable_external_texture() { + if (kind_case() != kExternalTexture) { + clear_kind(); + set_has_external_texture(); + _impl_.kind_.external_texture_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeExternalTexture>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeExternalTexture*>(_impl_.kind_.external_texture_); +} +inline ::tint::core::ir::binary::pb::TypeExternalTexture* PROTOBUF_NONNULL Type::mutable_external_texture() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeExternalTexture* _msg = _internal_mutable_external_texture(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.external_texture) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeSampler sampler = 14; +inline bool Type::has_sampler() const { + return kind_case() == kSampler; +} +inline bool Type::_internal_has_sampler() const { + return kind_case() == kSampler; +} +inline void Type::set_has_sampler() { + _impl_._oneof_case_[0] = kSampler; +} +inline void Type::clear_sampler() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSampler) { + if (GetArena() == nullptr) { + delete _impl_.kind_.sampler_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.sampler_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE Type::release_sampler() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.sampler) + if (kind_case() == kSampler) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSampler*>(_impl_.kind_.sampler_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.sampler_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeSampler& Type::_internal_sampler() const { + return kind_case() == kSampler ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeSampler*>(_impl_.kind_.sampler_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeSampler&>(::tint::core::ir::binary::pb::_TypeSampler_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeSampler& Type::sampler() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.sampler) + return _internal_sampler(); +} +inline ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE Type::unsafe_arena_release_sampler() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.sampler) + if (kind_case() == kSampler) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSampler*>(_impl_.kind_.sampler_); + _impl_.kind_.sampler_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_sampler( + ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_sampler(); + _impl_.kind_.sampler_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.sampler) +} +inline ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NONNULL Type::_internal_mutable_sampler() { + if (kind_case() != kSampler) { + clear_kind(); + set_has_sampler(); + _impl_.kind_.sampler_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeSampler>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeSampler*>(_impl_.kind_.sampler_); +} +inline ::tint::core::ir::binary::pb::TypeSampler* PROTOBUF_NONNULL Type::mutable_sampler() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeSampler* _msg = _internal_mutable_sampler(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.sampler) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeInputAttachment input_attachment = 15; +inline bool Type::has_input_attachment() const { + return kind_case() == kInputAttachment; +} +inline bool Type::_internal_has_input_attachment() const { + return kind_case() == kInputAttachment; +} +inline void Type::set_has_input_attachment() { + _impl_._oneof_case_[0] = kInputAttachment; +} +inline void Type::clear_input_attachment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kInputAttachment) { + if (GetArena() == nullptr) { + delete _impl_.kind_.input_attachment_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.input_attachment_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE Type::release_input_attachment() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.input_attachment) + if (kind_case() == kInputAttachment) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeInputAttachment*>(_impl_.kind_.input_attachment_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.input_attachment_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeInputAttachment& Type::_internal_input_attachment() const { + return kind_case() == kInputAttachment ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeInputAttachment*>(_impl_.kind_.input_attachment_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeInputAttachment&>(::tint::core::ir::binary::pb::_TypeInputAttachment_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeInputAttachment& Type::input_attachment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.input_attachment) + return _internal_input_attachment(); +} +inline ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE Type::unsafe_arena_release_input_attachment() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.input_attachment) + if (kind_case() == kInputAttachment) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeInputAttachment*>(_impl_.kind_.input_attachment_); + _impl_.kind_.input_attachment_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_input_attachment( + ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_input_attachment(); + _impl_.kind_.input_attachment_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.input_attachment) +} +inline ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NONNULL Type::_internal_mutable_input_attachment() { + if (kind_case() != kInputAttachment) { + clear_kind(); + set_has_input_attachment(); + _impl_.kind_.input_attachment_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeInputAttachment>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeInputAttachment*>(_impl_.kind_.input_attachment_); +} +inline ::tint::core::ir::binary::pb::TypeInputAttachment* PROTOBUF_NONNULL Type::mutable_input_attachment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeInputAttachment* _msg = _internal_mutable_input_attachment(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.input_attachment) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_left = 16; +inline bool Type::has_subgroup_matrix_left() const { + return kind_case() == kSubgroupMatrixLeft; +} +inline bool Type::_internal_has_subgroup_matrix_left() const { + return kind_case() == kSubgroupMatrixLeft; +} +inline void Type::set_has_subgroup_matrix_left() { + _impl_._oneof_case_[0] = kSubgroupMatrixLeft; +} +inline void Type::clear_subgroup_matrix_left() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSubgroupMatrixLeft) { + if (GetArena() == nullptr) { + delete _impl_.kind_.subgroup_matrix_left_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.subgroup_matrix_left_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE Type::release_subgroup_matrix_left() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.subgroup_matrix_left) + if (kind_case() == kSubgroupMatrixLeft) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_left_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.subgroup_matrix_left_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& Type::_internal_subgroup_matrix_left() const { + return kind_case() == kSubgroupMatrixLeft ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_left_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix&>(::tint::core::ir::binary::pb::_TypeSubgroupMatrix_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& Type::subgroup_matrix_left() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.subgroup_matrix_left) + return _internal_subgroup_matrix_left(); +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE Type::unsafe_arena_release_subgroup_matrix_left() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.subgroup_matrix_left) + if (kind_case() == kSubgroupMatrixLeft) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_left_); + _impl_.kind_.subgroup_matrix_left_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_subgroup_matrix_left( + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_subgroup_matrix_left(); + _impl_.kind_.subgroup_matrix_left_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.subgroup_matrix_left) +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL Type::_internal_mutable_subgroup_matrix_left() { + if (kind_case() != kSubgroupMatrixLeft) { + clear_kind(); + set_has_subgroup_matrix_left(); + _impl_.kind_.subgroup_matrix_left_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeSubgroupMatrix>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_left_); +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL Type::mutable_subgroup_matrix_left() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* _msg = _internal_mutable_subgroup_matrix_left(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.subgroup_matrix_left) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_right = 17; +inline bool Type::has_subgroup_matrix_right() const { + return kind_case() == kSubgroupMatrixRight; +} +inline bool Type::_internal_has_subgroup_matrix_right() const { + return kind_case() == kSubgroupMatrixRight; +} +inline void Type::set_has_subgroup_matrix_right() { + _impl_._oneof_case_[0] = kSubgroupMatrixRight; +} +inline void Type::clear_subgroup_matrix_right() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSubgroupMatrixRight) { + if (GetArena() == nullptr) { + delete _impl_.kind_.subgroup_matrix_right_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.subgroup_matrix_right_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE Type::release_subgroup_matrix_right() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.subgroup_matrix_right) + if (kind_case() == kSubgroupMatrixRight) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_right_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.subgroup_matrix_right_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& Type::_internal_subgroup_matrix_right() const { + return kind_case() == kSubgroupMatrixRight ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_right_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix&>(::tint::core::ir::binary::pb::_TypeSubgroupMatrix_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& Type::subgroup_matrix_right() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.subgroup_matrix_right) + return _internal_subgroup_matrix_right(); +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE Type::unsafe_arena_release_subgroup_matrix_right() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.subgroup_matrix_right) + if (kind_case() == kSubgroupMatrixRight) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_right_); + _impl_.kind_.subgroup_matrix_right_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_subgroup_matrix_right( + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_subgroup_matrix_right(); + _impl_.kind_.subgroup_matrix_right_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.subgroup_matrix_right) +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL Type::_internal_mutable_subgroup_matrix_right() { + if (kind_case() != kSubgroupMatrixRight) { + clear_kind(); + set_has_subgroup_matrix_right(); + _impl_.kind_.subgroup_matrix_right_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeSubgroupMatrix>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_right_); +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL Type::mutable_subgroup_matrix_right() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* _msg = _internal_mutable_subgroup_matrix_right(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.subgroup_matrix_right) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeSubgroupMatrix subgroup_matrix_result = 18; +inline bool Type::has_subgroup_matrix_result() const { + return kind_case() == kSubgroupMatrixResult; +} +inline bool Type::_internal_has_subgroup_matrix_result() const { + return kind_case() == kSubgroupMatrixResult; +} +inline void Type::set_has_subgroup_matrix_result() { + _impl_._oneof_case_[0] = kSubgroupMatrixResult; +} +inline void Type::clear_subgroup_matrix_result() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSubgroupMatrixResult) { + if (GetArena() == nullptr) { + delete _impl_.kind_.subgroup_matrix_result_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.subgroup_matrix_result_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE Type::release_subgroup_matrix_result() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.subgroup_matrix_result) + if (kind_case() == kSubgroupMatrixResult) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_result_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.subgroup_matrix_result_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& Type::_internal_subgroup_matrix_result() const { + return kind_case() == kSubgroupMatrixResult ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_result_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix&>(::tint::core::ir::binary::pb::_TypeSubgroupMatrix_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeSubgroupMatrix& Type::subgroup_matrix_result() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.subgroup_matrix_result) + return _internal_subgroup_matrix_result(); +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE Type::unsafe_arena_release_subgroup_matrix_result() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.subgroup_matrix_result) + if (kind_case() == kSubgroupMatrixResult) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_result_); + _impl_.kind_.subgroup_matrix_result_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_subgroup_matrix_result( + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_subgroup_matrix_result(); + _impl_.kind_.subgroup_matrix_result_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.subgroup_matrix_result) +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL Type::_internal_mutable_subgroup_matrix_result() { + if (kind_case() != kSubgroupMatrixResult) { + clear_kind(); + set_has_subgroup_matrix_result(); + _impl_.kind_.subgroup_matrix_result_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeSubgroupMatrix>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeSubgroupMatrix*>(_impl_.kind_.subgroup_matrix_result_); +} +inline ::tint::core::ir::binary::pb::TypeSubgroupMatrix* PROTOBUF_NONNULL Type::mutable_subgroup_matrix_result() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeSubgroupMatrix* _msg = _internal_mutable_subgroup_matrix_result(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.subgroup_matrix_result) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeBuiltinStruct builtin_struct = 19; +inline bool Type::has_builtin_struct() const { + return kind_case() == kBuiltinStruct; +} +inline void Type::set_has_builtin_struct() { + _impl_._oneof_case_[0] = kBuiltinStruct; +} +inline void Type::clear_builtin_struct() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBuiltinStruct) { + _impl_.kind_.builtin_struct_ = 0; + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeBuiltinStruct Type::builtin_struct() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.builtin_struct) + return _internal_builtin_struct(); +} +inline void Type::set_builtin_struct(::tint::core::ir::binary::pb::TypeBuiltinStruct value) { + if (kind_case() != kBuiltinStruct) { + clear_kind(); + set_has_builtin_struct(); + } + _impl_.kind_.builtin_struct_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Type.builtin_struct) +} +inline ::tint::core::ir::binary::pb::TypeBuiltinStruct Type::_internal_builtin_struct() const { + if (kind_case() == kBuiltinStruct) { + return static_cast<::tint::core::ir::binary::pb::TypeBuiltinStruct>(_impl_.kind_.builtin_struct_); + } + return static_cast<::tint::core::ir::binary::pb::TypeBuiltinStruct>(0); +} + +// .tint.core.ir.binary.pb.TypeBindingArray binding_array = 20; +inline bool Type::has_binding_array() const { + return kind_case() == kBindingArray; +} +inline bool Type::_internal_has_binding_array() const { + return kind_case() == kBindingArray; +} +inline void Type::set_has_binding_array() { + _impl_._oneof_case_[0] = kBindingArray; +} +inline void Type::clear_binding_array() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBindingArray) { + if (GetArena() == nullptr) { + delete _impl_.kind_.binding_array_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.binding_array_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE Type::release_binding_array() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.binding_array) + if (kind_case() == kBindingArray) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeBindingArray*>(_impl_.kind_.binding_array_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.binding_array_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeBindingArray& Type::_internal_binding_array() const { + return kind_case() == kBindingArray ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeBindingArray*>(_impl_.kind_.binding_array_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeBindingArray&>(::tint::core::ir::binary::pb::_TypeBindingArray_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeBindingArray& Type::binding_array() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.binding_array) + return _internal_binding_array(); +} +inline ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE Type::unsafe_arena_release_binding_array() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.binding_array) + if (kind_case() == kBindingArray) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeBindingArray*>(_impl_.kind_.binding_array_); + _impl_.kind_.binding_array_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_binding_array( + ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_binding_array(); + _impl_.kind_.binding_array_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.binding_array) +} +inline ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NONNULL Type::_internal_mutable_binding_array() { + if (kind_case() != kBindingArray) { + clear_kind(); + set_has_binding_array(); + _impl_.kind_.binding_array_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeBindingArray>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeBindingArray*>(_impl_.kind_.binding_array_); +} +inline ::tint::core::ir::binary::pb::TypeBindingArray* PROTOBUF_NONNULL Type::mutable_binding_array() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeBindingArray* _msg = _internal_mutable_binding_array(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.binding_array) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeTexelBuffer texel_buffer = 21; +inline bool Type::has_texel_buffer() const { + return kind_case() == kTexelBuffer; +} +inline bool Type::_internal_has_texel_buffer() const { + return kind_case() == kTexelBuffer; +} +inline void Type::set_has_texel_buffer() { + _impl_._oneof_case_[0] = kTexelBuffer; +} +inline void Type::clear_texel_buffer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kTexelBuffer) { + if (GetArena() == nullptr) { + delete _impl_.kind_.texel_buffer_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.texel_buffer_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE Type::release_texel_buffer() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.texel_buffer) + if (kind_case() == kTexelBuffer) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeTexelBuffer*>(_impl_.kind_.texel_buffer_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.texel_buffer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeTexelBuffer& Type::_internal_texel_buffer() const { + return kind_case() == kTexelBuffer ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeTexelBuffer*>(_impl_.kind_.texel_buffer_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeTexelBuffer&>(::tint::core::ir::binary::pb::_TypeTexelBuffer_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeTexelBuffer& Type::texel_buffer() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.texel_buffer) + return _internal_texel_buffer(); +} +inline ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE Type::unsafe_arena_release_texel_buffer() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.texel_buffer) + if (kind_case() == kTexelBuffer) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeTexelBuffer*>(_impl_.kind_.texel_buffer_); + _impl_.kind_.texel_buffer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_texel_buffer( + ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_texel_buffer(); + _impl_.kind_.texel_buffer_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.texel_buffer) +} +inline ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NONNULL Type::_internal_mutable_texel_buffer() { + if (kind_case() != kTexelBuffer) { + clear_kind(); + set_has_texel_buffer(); + _impl_.kind_.texel_buffer_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeTexelBuffer>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeTexelBuffer*>(_impl_.kind_.texel_buffer_); +} +inline ::tint::core::ir::binary::pb::TypeTexelBuffer* PROTOBUF_NONNULL Type::mutable_texel_buffer() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeTexelBuffer* _msg = _internal_mutable_texel_buffer(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.texel_buffer) + return _msg; +} + +// .tint.core.ir.binary.pb.TypeBuffer buffer = 23; +inline bool Type::has_buffer() const { + return kind_case() == kBuffer; +} +inline bool Type::_internal_has_buffer() const { + return kind_case() == kBuffer; +} +inline void Type::set_has_buffer() { + _impl_._oneof_case_[0] = kBuffer; +} +inline void Type::clear_buffer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBuffer) { + if (GetArena() == nullptr) { + delete _impl_.kind_.buffer_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.buffer_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE Type::release_buffer() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Type.buffer) + if (kind_case() == kBuffer) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeBuffer*>(_impl_.kind_.buffer_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.buffer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::TypeBuffer& Type::_internal_buffer() const { + return kind_case() == kBuffer ? *reinterpret_cast<::tint::core::ir::binary::pb::TypeBuffer*>(_impl_.kind_.buffer_) : reinterpret_cast<::tint::core::ir::binary::pb::TypeBuffer&>(::tint::core::ir::binary::pb::_TypeBuffer_default_instance_); +} +inline const ::tint::core::ir::binary::pb::TypeBuffer& Type::buffer() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Type.buffer) + return _internal_buffer(); +} +inline ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE Type::unsafe_arena_release_buffer() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Type.buffer) + if (kind_case() == kBuffer) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::TypeBuffer*>(_impl_.kind_.buffer_); + _impl_.kind_.buffer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Type::unsafe_arena_set_allocated_buffer( + ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_buffer(); + _impl_.kind_.buffer_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Type.buffer) +} +inline ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NONNULL Type::_internal_mutable_buffer() { + if (kind_case() != kBuffer) { + clear_kind(); + set_has_buffer(); + _impl_.kind_.buffer_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::TypeBuffer>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::TypeBuffer*>(_impl_.kind_.buffer_); +} +inline ::tint::core::ir::binary::pb::TypeBuffer* PROTOBUF_NONNULL Type::mutable_buffer() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::TypeBuffer* _msg = _internal_mutable_buffer(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Type.buffer) + return _msg; +} + +inline bool Type::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void Type::clear_has_kind() { + _impl_._oneof_case_[0] = KIND_NOT_SET; +} +inline Type::KindCase Type::kind_case() const { + return Type::KindCase(_impl_._oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// TypeVector + +// uint32 width = 1; +inline void TypeVector::clear_width() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.width_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeVector::width() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeVector.width) + return _internal_width(); +} +inline void TypeVector::set_width(::uint32_t value) { + _internal_set_width(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeVector.width) +} +inline ::uint32_t TypeVector::_internal_width() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.width_; +} +inline void TypeVector::_internal_set_width(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.width_ = value; +} + +// uint32 element_type = 2; +inline void TypeVector::clear_element_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeVector::element_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeVector.element_type) + return _internal_element_type(); +} +inline void TypeVector::set_element_type(::uint32_t value) { + _internal_set_element_type(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeVector.element_type) +} +inline ::uint32_t TypeVector::_internal_element_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.element_type_; +} +inline void TypeVector::_internal_set_element_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_type_ = value; +} + +// ------------------------------------------------------------------- + +// TypeMatrix + +// uint32 num_columns = 1; +inline void TypeMatrix::clear_num_columns() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.num_columns_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeMatrix::num_columns() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeMatrix.num_columns) + return _internal_num_columns(); +} +inline void TypeMatrix::set_num_columns(::uint32_t value) { + _internal_set_num_columns(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeMatrix.num_columns) +} +inline ::uint32_t TypeMatrix::_internal_num_columns() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.num_columns_; +} +inline void TypeMatrix::_internal_set_num_columns(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.num_columns_ = value; +} + +// uint32 num_rows = 2; +inline void TypeMatrix::clear_num_rows() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.num_rows_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeMatrix::num_rows() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeMatrix.num_rows) + return _internal_num_rows(); +} +inline void TypeMatrix::set_num_rows(::uint32_t value) { + _internal_set_num_rows(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeMatrix.num_rows) +} +inline ::uint32_t TypeMatrix::_internal_num_rows() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.num_rows_; +} +inline void TypeMatrix::_internal_set_num_rows(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.num_rows_ = value; +} + +// uint32 element_type = 3; +inline void TypeMatrix::clear_element_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t TypeMatrix::element_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeMatrix.element_type) + return _internal_element_type(); +} +inline void TypeMatrix::set_element_type(::uint32_t value) { + _internal_set_element_type(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeMatrix.element_type) +} +inline ::uint32_t TypeMatrix::_internal_element_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.element_type_; +} +inline void TypeMatrix::_internal_set_element_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_type_ = value; +} + +// ------------------------------------------------------------------- + +// TypeArray + +// uint32 element = 1; +inline void TypeArray::clear_element() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeArray::element() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeArray.element) + return _internal_element(); +} +inline void TypeArray::set_element(::uint32_t value) { + _internal_set_element(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeArray.element) +} +inline ::uint32_t TypeArray::_internal_element() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.element_; +} +inline void TypeArray::_internal_set_element(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_ = value; +} + +// uint32 count = 3; +inline void TypeArray::clear_count() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeArray::count() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeArray.count) + return _internal_count(); +} +inline void TypeArray::set_count(::uint32_t value) { + _internal_set_count(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeArray.count) +} +inline ::uint32_t TypeArray::_internal_count() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.count_; +} +inline void TypeArray::_internal_set_count(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = value; +} + +// ------------------------------------------------------------------- + +// TypeBindingArray + +// uint32 element = 1; +inline void TypeBindingArray::clear_element() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeBindingArray::element() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeBindingArray.element) + return _internal_element(); +} +inline void TypeBindingArray::set_element(::uint32_t value) { + _internal_set_element(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeBindingArray.element) +} +inline ::uint32_t TypeBindingArray::_internal_element() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.element_; +} +inline void TypeBindingArray::_internal_set_element(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.element_ = value; +} + +// uint32 count = 2; +inline void TypeBindingArray::clear_count() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeBindingArray::count() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeBindingArray.count) + return _internal_count(); +} +inline void TypeBindingArray::set_count(::uint32_t value) { + _internal_set_count(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeBindingArray.count) +} +inline ::uint32_t TypeBindingArray::_internal_count() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.count_; +} +inline void TypeBindingArray::_internal_set_count(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = value; +} + +// ------------------------------------------------------------------- + +// TypePointer + +// .tint.core.ir.binary.pb.AddressSpace address_space = 1; +inline void TypePointer::clear_address_space() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.address_space_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::AddressSpace TypePointer::address_space() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypePointer.address_space) + return _internal_address_space(); +} +inline void TypePointer::set_address_space(::tint::core::ir::binary::pb::AddressSpace value) { + _internal_set_address_space(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypePointer.address_space) +} +inline ::tint::core::ir::binary::pb::AddressSpace TypePointer::_internal_address_space() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::AddressSpace>(_impl_.address_space_); +} +inline void TypePointer::_internal_set_address_space(::tint::core::ir::binary::pb::AddressSpace value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.address_space_ = value; +} + +// uint32 store_type = 2; +inline void TypePointer::clear_store_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.store_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypePointer::store_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypePointer.store_type) + return _internal_store_type(); +} +inline void TypePointer::set_store_type(::uint32_t value) { + _internal_set_store_type(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypePointer.store_type) +} +inline ::uint32_t TypePointer::_internal_store_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.store_type_; +} +inline void TypePointer::_internal_set_store_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.store_type_ = value; +} + +// .tint.core.ir.binary.pb.AccessControl access = 3; +inline void TypePointer::clear_access() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.access_ = 0; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::tint::core::ir::binary::pb::AccessControl TypePointer::access() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypePointer.access) + return _internal_access(); +} +inline void TypePointer::set_access(::tint::core::ir::binary::pb::AccessControl value) { + _internal_set_access(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypePointer.access) +} +inline ::tint::core::ir::binary::pb::AccessControl TypePointer::_internal_access() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::AccessControl>(_impl_.access_); +} +inline void TypePointer::_internal_set_access(::tint::core::ir::binary::pb::AccessControl value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.access_ = value; +} + +// ------------------------------------------------------------------- + +// TypeStruct + +// string name = 1; +inline void TypeStruct::clear_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::std::string& TypeStruct::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStruct.name) + return _internal_name(); +} +template +PROTOBUF_ALWAYS_INLINE void TypeStruct::set_name(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStruct.name) +} +inline ::std::string* PROTOBUF_NONNULL TypeStruct::mutable_name() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.TypeStruct.name) + return _s; +} +inline const ::std::string& TypeStruct::_internal_name() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.name_.Get(); +} +inline void TypeStruct::_internal_set_name(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL TypeStruct::_internal_mutable_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + return _impl_.name_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE TypeStruct::release_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.TypeStruct.name) + if ((_impl_._has_bits_[0] & 0x00000001U) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001U; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; +} +inline void TypeStruct::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + _impl_.name_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.TypeStruct.name) +} + +// repeated .tint.core.ir.binary.pb.TypeStructMember member = 2; +inline int TypeStruct::_internal_member_size() const { + return _internal_member().size(); +} +inline int TypeStruct::member_size() const { + return _internal_member_size(); +} +inline void TypeStruct::clear_member() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.member_.Clear(); +} +inline ::tint::core::ir::binary::pb::TypeStructMember* PROTOBUF_NONNULL TypeStruct::mutable_member(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.TypeStruct.member) + return _internal_mutable_member()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>* PROTOBUF_NONNULL TypeStruct::mutable_member() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.TypeStruct.member) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_member(); +} +inline const ::tint::core::ir::binary::pb::TypeStructMember& TypeStruct::member(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStruct.member) + return _internal_member().Get(index); +} +inline ::tint::core::ir::binary::pb::TypeStructMember* PROTOBUF_NONNULL TypeStruct::add_member() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::TypeStructMember* _add = _internal_mutable_member()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.TypeStruct.member) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>& TypeStruct::member() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.TypeStruct.member) + return _internal_member(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>& +TypeStruct::_internal_member() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.member_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::TypeStructMember>* PROTOBUF_NONNULL +TypeStruct::_internal_mutable_member() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.member_; +} + +// ------------------------------------------------------------------- + +// TypeStructMember + +// string name = 1; +inline void TypeStructMember::clear_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::std::string& TypeStructMember::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStructMember.name) + return _internal_name(); +} +template +PROTOBUF_ALWAYS_INLINE void TypeStructMember::set_name(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStructMember.name) +} +inline ::std::string* PROTOBUF_NONNULL TypeStructMember::mutable_name() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.TypeStructMember.name) + return _s; +} +inline const ::std::string& TypeStructMember::_internal_name() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.name_.Get(); +} +inline void TypeStructMember::_internal_set_name(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL TypeStructMember::_internal_mutable_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + return _impl_.name_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE TypeStructMember::release_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.TypeStructMember.name) + if ((_impl_._has_bits_[0] & 0x00000001U) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001U; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; +} +inline void TypeStructMember::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + _impl_.name_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.TypeStructMember.name) +} + +// uint32 type = 2; +inline void TypeStructMember::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t TypeStructMember::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStructMember.type) + return _internal_type(); +} +inline void TypeStructMember::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStructMember.type) +} +inline ::uint32_t TypeStructMember::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void TypeStructMember::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// uint32 size = 3; +inline void TypeStructMember::clear_size() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.size_ = 0u; + _impl_._has_bits_[0] &= ~0x00000008U; +} +inline ::uint32_t TypeStructMember::size() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStructMember.size) + return _internal_size(); +} +inline void TypeStructMember::set_size(::uint32_t value) { + _internal_set_size(value); + _impl_._has_bits_[0] |= 0x00000008U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStructMember.size) +} +inline ::uint32_t TypeStructMember::_internal_size() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.size_; +} +inline void TypeStructMember::_internal_set_size(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.size_ = value; +} + +// uint32 align = 4; +inline void TypeStructMember::clear_align() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.align_ = 0u; + _impl_._has_bits_[0] &= ~0x00000010U; +} +inline ::uint32_t TypeStructMember::align() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStructMember.align) + return _internal_align(); +} +inline void TypeStructMember::set_align(::uint32_t value) { + _internal_set_align(value); + _impl_._has_bits_[0] |= 0x00000010U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStructMember.align) +} +inline ::uint32_t TypeStructMember::_internal_align() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.align_; +} +inline void TypeStructMember::_internal_set_align(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.align_ = value; +} + +// optional .tint.core.ir.binary.pb.AttributesStructMember attributes = 5; +inline bool TypeStructMember::has_attributes() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + PROTOBUF_ASSUME(!value || _impl_.attributes_ != nullptr); + return value; +} +inline void TypeStructMember::clear_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attributes_ != nullptr) _impl_.attributes_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline const ::tint::core::ir::binary::pb::AttributesStructMember& TypeStructMember::_internal_attributes() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::AttributesStructMember* p = _impl_.attributes_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_AttributesStructMember_default_instance_); +} +inline const ::tint::core::ir::binary::pb::AttributesStructMember& TypeStructMember::attributes() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStructMember.attributes) + return _internal_attributes(); +} +inline void TypeStructMember::unsafe_arena_set_allocated_attributes( + ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attributes_); + } + _impl_.attributes_ = reinterpret_cast<::tint::core::ir::binary::pb::AttributesStructMember*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.TypeStructMember.attributes) +} +inline ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE TypeStructMember::release_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::AttributesStructMember* released = _impl_.attributes_; + _impl_.attributes_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE TypeStructMember::unsafe_arena_release_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.TypeStructMember.attributes) + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::AttributesStructMember* temp = _impl_.attributes_; + _impl_.attributes_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NONNULL TypeStructMember::_internal_mutable_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attributes_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::AttributesStructMember>(GetArena()); + _impl_.attributes_ = reinterpret_cast<::tint::core::ir::binary::pb::AttributesStructMember*>(p); + } + return _impl_.attributes_; +} +inline ::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NONNULL TypeStructMember::mutable_attributes() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000002U; + ::tint::core::ir::binary::pb::AttributesStructMember* _msg = _internal_mutable_attributes(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.TypeStructMember.attributes) + return _msg; +} +inline void TypeStructMember::set_allocated_attributes(::tint::core::ir::binary::pb::AttributesStructMember* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attributes_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + + _impl_.attributes_ = reinterpret_cast<::tint::core::ir::binary::pb::AttributesStructMember*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.TypeStructMember.attributes) +} + +// ------------------------------------------------------------------- + +// TypeAtomic + +// uint32 type = 1; +inline void TypeAtomic::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeAtomic::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeAtomic.type) + return _internal_type(); +} +inline void TypeAtomic::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeAtomic.type) +} +inline ::uint32_t TypeAtomic::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void TypeAtomic::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// ------------------------------------------------------------------- + +// TypeDepthTexture + +// .tint.core.ir.binary.pb.TextureDimension dimension = 1; +inline void TypeDepthTexture::clear_dimension() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeDepthTexture::dimension() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeDepthTexture.dimension) + return _internal_dimension(); +} +inline void TypeDepthTexture::set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + _internal_set_dimension(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeDepthTexture.dimension) +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeDepthTexture::_internal_dimension() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TextureDimension>(_impl_.dimension_); +} +inline void TypeDepthTexture::_internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = value; +} + +// ------------------------------------------------------------------- + +// TypeSampledTexture + +// .tint.core.ir.binary.pb.TextureDimension dimension = 1; +inline void TypeSampledTexture::clear_dimension() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeSampledTexture::dimension() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeSampledTexture.dimension) + return _internal_dimension(); +} +inline void TypeSampledTexture::set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + _internal_set_dimension(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeSampledTexture.dimension) +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeSampledTexture::_internal_dimension() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TextureDimension>(_impl_.dimension_); +} +inline void TypeSampledTexture::_internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = value; +} + +// uint32 sub_type = 2; +inline void TypeSampledTexture::clear_sub_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeSampledTexture::sub_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeSampledTexture.sub_type) + return _internal_sub_type(); +} +inline void TypeSampledTexture::set_sub_type(::uint32_t value) { + _internal_set_sub_type(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeSampledTexture.sub_type) +} +inline ::uint32_t TypeSampledTexture::_internal_sub_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.sub_type_; +} +inline void TypeSampledTexture::_internal_set_sub_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = value; +} + +// ------------------------------------------------------------------- + +// TypeMultisampledTexture + +// .tint.core.ir.binary.pb.TextureDimension dimension = 1; +inline void TypeMultisampledTexture::clear_dimension() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeMultisampledTexture::dimension() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeMultisampledTexture.dimension) + return _internal_dimension(); +} +inline void TypeMultisampledTexture::set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + _internal_set_dimension(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeMultisampledTexture.dimension) +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeMultisampledTexture::_internal_dimension() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TextureDimension>(_impl_.dimension_); +} +inline void TypeMultisampledTexture::_internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = value; +} + +// uint32 sub_type = 2; +inline void TypeMultisampledTexture::clear_sub_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeMultisampledTexture::sub_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeMultisampledTexture.sub_type) + return _internal_sub_type(); +} +inline void TypeMultisampledTexture::set_sub_type(::uint32_t value) { + _internal_set_sub_type(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeMultisampledTexture.sub_type) +} +inline ::uint32_t TypeMultisampledTexture::_internal_sub_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.sub_type_; +} +inline void TypeMultisampledTexture::_internal_set_sub_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = value; +} + +// ------------------------------------------------------------------- + +// TypeDepthMultisampledTexture + +// .tint.core.ir.binary.pb.TextureDimension dimension = 1; +inline void TypeDepthMultisampledTexture::clear_dimension() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeDepthMultisampledTexture::dimension() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeDepthMultisampledTexture.dimension) + return _internal_dimension(); +} +inline void TypeDepthMultisampledTexture::set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + _internal_set_dimension(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeDepthMultisampledTexture.dimension) +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeDepthMultisampledTexture::_internal_dimension() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TextureDimension>(_impl_.dimension_); +} +inline void TypeDepthMultisampledTexture::_internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = value; +} + +// ------------------------------------------------------------------- + +// TypeStorageTexture + +// .tint.core.ir.binary.pb.TextureDimension dimension = 1; +inline void TypeStorageTexture::clear_dimension() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeStorageTexture::dimension() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStorageTexture.dimension) + return _internal_dimension(); +} +inline void TypeStorageTexture::set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + _internal_set_dimension(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStorageTexture.dimension) +} +inline ::tint::core::ir::binary::pb::TextureDimension TypeStorageTexture::_internal_dimension() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TextureDimension>(_impl_.dimension_); +} +inline void TypeStorageTexture::_internal_set_dimension(::tint::core::ir::binary::pb::TextureDimension value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.dimension_ = value; +} + +// .tint.core.ir.binary.pb.TexelFormat texel_format = 2; +inline void TypeStorageTexture::clear_texel_format() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.texel_format_ = 0; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::tint::core::ir::binary::pb::TexelFormat TypeStorageTexture::texel_format() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStorageTexture.texel_format) + return _internal_texel_format(); +} +inline void TypeStorageTexture::set_texel_format(::tint::core::ir::binary::pb::TexelFormat value) { + _internal_set_texel_format(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStorageTexture.texel_format) +} +inline ::tint::core::ir::binary::pb::TexelFormat TypeStorageTexture::_internal_texel_format() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TexelFormat>(_impl_.texel_format_); +} +inline void TypeStorageTexture::_internal_set_texel_format(::tint::core::ir::binary::pb::TexelFormat value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.texel_format_ = value; +} + +// .tint.core.ir.binary.pb.AccessControl access = 3; +inline void TypeStorageTexture::clear_access() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.access_ = 0; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::tint::core::ir::binary::pb::AccessControl TypeStorageTexture::access() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeStorageTexture.access) + return _internal_access(); +} +inline void TypeStorageTexture::set_access(::tint::core::ir::binary::pb::AccessControl value) { + _internal_set_access(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeStorageTexture.access) +} +inline ::tint::core::ir::binary::pb::AccessControl TypeStorageTexture::_internal_access() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::AccessControl>(_impl_.access_); +} +inline void TypeStorageTexture::_internal_set_access(::tint::core::ir::binary::pb::AccessControl value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.access_ = value; +} + +// ------------------------------------------------------------------- + +// TypeResourceBinding + +// ------------------------------------------------------------------- + +// TypeExternalTexture + +// ------------------------------------------------------------------- + +// TypeSampler + +// .tint.core.ir.binary.pb.SamplerKind kind = 1; +inline void TypeSampler::clear_kind() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.kind_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::SamplerKind TypeSampler::kind() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeSampler.kind) + return _internal_kind(); +} +inline void TypeSampler::set_kind(::tint::core::ir::binary::pb::SamplerKind value) { + _internal_set_kind(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeSampler.kind) +} +inline ::tint::core::ir::binary::pb::SamplerKind TypeSampler::_internal_kind() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::SamplerKind>(_impl_.kind_); +} +inline void TypeSampler::_internal_set_kind(::tint::core::ir::binary::pb::SamplerKind value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.kind_ = value; +} + +// ------------------------------------------------------------------- + +// TypeInputAttachment + +// uint32 sub_type = 1; +inline void TypeInputAttachment::clear_sub_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeInputAttachment::sub_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeInputAttachment.sub_type) + return _internal_sub_type(); +} +inline void TypeInputAttachment::set_sub_type(::uint32_t value) { + _internal_set_sub_type(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeInputAttachment.sub_type) +} +inline ::uint32_t TypeInputAttachment::_internal_sub_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.sub_type_; +} +inline void TypeInputAttachment::_internal_set_sub_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = value; +} + +// ------------------------------------------------------------------- + +// TypeSubgroupMatrix + +// uint32 sub_type = 1; +inline void TypeSubgroupMatrix::clear_sub_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeSubgroupMatrix::sub_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeSubgroupMatrix.sub_type) + return _internal_sub_type(); +} +inline void TypeSubgroupMatrix::set_sub_type(::uint32_t value) { + _internal_set_sub_type(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeSubgroupMatrix.sub_type) +} +inline ::uint32_t TypeSubgroupMatrix::_internal_sub_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.sub_type_; +} +inline void TypeSubgroupMatrix::_internal_set_sub_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sub_type_ = value; +} + +// uint32 rows = 2; +inline void TypeSubgroupMatrix::clear_rows() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rows_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t TypeSubgroupMatrix::rows() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeSubgroupMatrix.rows) + return _internal_rows(); +} +inline void TypeSubgroupMatrix::set_rows(::uint32_t value) { + _internal_set_rows(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeSubgroupMatrix.rows) +} +inline ::uint32_t TypeSubgroupMatrix::_internal_rows() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.rows_; +} +inline void TypeSubgroupMatrix::_internal_set_rows(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rows_ = value; +} + +// uint32 columns = 3; +inline void TypeSubgroupMatrix::clear_columns() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.columns_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t TypeSubgroupMatrix::columns() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeSubgroupMatrix.columns) + return _internal_columns(); +} +inline void TypeSubgroupMatrix::set_columns(::uint32_t value) { + _internal_set_columns(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeSubgroupMatrix.columns) +} +inline ::uint32_t TypeSubgroupMatrix::_internal_columns() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.columns_; +} +inline void TypeSubgroupMatrix::_internal_set_columns(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.columns_ = value; +} + +// ------------------------------------------------------------------- + +// TypeBuffer + +// uint32 count = 1; +inline void TypeBuffer::clear_count() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t TypeBuffer::count() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeBuffer.count) + return _internal_count(); +} +inline void TypeBuffer::set_count(::uint32_t value) { + _internal_set_count(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeBuffer.count) +} +inline ::uint32_t TypeBuffer::_internal_count() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.count_; +} +inline void TypeBuffer::_internal_set_count(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = value; +} + +// ------------------------------------------------------------------- + +// TypeTexelBuffer + +// .tint.core.ir.binary.pb.TexelFormat texel_format = 1; +inline void TypeTexelBuffer::clear_texel_format() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.texel_format_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::TexelFormat TypeTexelBuffer::texel_format() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeTexelBuffer.texel_format) + return _internal_texel_format(); +} +inline void TypeTexelBuffer::set_texel_format(::tint::core::ir::binary::pb::TexelFormat value) { + _internal_set_texel_format(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeTexelBuffer.texel_format) +} +inline ::tint::core::ir::binary::pb::TexelFormat TypeTexelBuffer::_internal_texel_format() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::TexelFormat>(_impl_.texel_format_); +} +inline void TypeTexelBuffer::_internal_set_texel_format(::tint::core::ir::binary::pb::TexelFormat value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.texel_format_ = value; +} + +// .tint.core.ir.binary.pb.AccessControl access = 2; +inline void TypeTexelBuffer::clear_access() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.access_ = 0; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::tint::core::ir::binary::pb::AccessControl TypeTexelBuffer::access() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.TypeTexelBuffer.access) + return _internal_access(); +} +inline void TypeTexelBuffer::set_access(::tint::core::ir::binary::pb::AccessControl value) { + _internal_set_access(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.TypeTexelBuffer.access) +} +inline ::tint::core::ir::binary::pb::AccessControl TypeTexelBuffer::_internal_access() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::AccessControl>(_impl_.access_); +} +inline void TypeTexelBuffer::_internal_set_access(::tint::core::ir::binary::pb::AccessControl value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.access_ = value; +} + +// ------------------------------------------------------------------- + +// Value + +// uint32 function = 1; +inline bool Value::has_function() const { + return kind_case() == kFunction; +} +inline void Value::set_has_function() { + _impl_._oneof_case_[0] = kFunction; +} +inline void Value::clear_function() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kFunction) { + _impl_.kind_.function_ = 0u; + clear_has_kind(); + } +} +inline ::uint32_t Value::function() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Value.function) + return _internal_function(); +} +inline void Value::set_function(::uint32_t value) { + if (kind_case() != kFunction) { + clear_kind(); + set_has_function(); + } + _impl_.kind_.function_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Value.function) +} +inline ::uint32_t Value::_internal_function() const { + if (kind_case() == kFunction) { + return _impl_.kind_.function_; + } + return 0u; +} + +// .tint.core.ir.binary.pb.InstructionResult instruction_result = 2; +inline bool Value::has_instruction_result() const { + return kind_case() == kInstructionResult; +} +inline bool Value::_internal_has_instruction_result() const { + return kind_case() == kInstructionResult; +} +inline void Value::set_has_instruction_result() { + _impl_._oneof_case_[0] = kInstructionResult; +} +inline void Value::clear_instruction_result() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kInstructionResult) { + if (GetArena() == nullptr) { + delete _impl_.kind_.instruction_result_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.instruction_result_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE Value::release_instruction_result() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Value.instruction_result) + if (kind_case() == kInstructionResult) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionResult*>(_impl_.kind_.instruction_result_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.instruction_result_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionResult& Value::_internal_instruction_result() const { + return kind_case() == kInstructionResult ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionResult*>(_impl_.kind_.instruction_result_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionResult&>(::tint::core::ir::binary::pb::_InstructionResult_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionResult& Value::instruction_result() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Value.instruction_result) + return _internal_instruction_result(); +} +inline ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE Value::unsafe_arena_release_instruction_result() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Value.instruction_result) + if (kind_case() == kInstructionResult) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionResult*>(_impl_.kind_.instruction_result_); + _impl_.kind_.instruction_result_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Value::unsafe_arena_set_allocated_instruction_result( + ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_instruction_result(); + _impl_.kind_.instruction_result_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Value.instruction_result) +} +inline ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NONNULL Value::_internal_mutable_instruction_result() { + if (kind_case() != kInstructionResult) { + clear_kind(); + set_has_instruction_result(); + _impl_.kind_.instruction_result_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionResult>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionResult*>(_impl_.kind_.instruction_result_); +} +inline ::tint::core::ir::binary::pb::InstructionResult* PROTOBUF_NONNULL Value::mutable_instruction_result() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionResult* _msg = _internal_mutable_instruction_result(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Value.instruction_result) + return _msg; +} + +// .tint.core.ir.binary.pb.FunctionParameter function_parameter = 3; +inline bool Value::has_function_parameter() const { + return kind_case() == kFunctionParameter; +} +inline bool Value::_internal_has_function_parameter() const { + return kind_case() == kFunctionParameter; +} +inline void Value::set_has_function_parameter() { + _impl_._oneof_case_[0] = kFunctionParameter; +} +inline void Value::clear_function_parameter() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kFunctionParameter) { + if (GetArena() == nullptr) { + delete _impl_.kind_.function_parameter_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.function_parameter_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE Value::release_function_parameter() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Value.function_parameter) + if (kind_case() == kFunctionParameter) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::FunctionParameter*>(_impl_.kind_.function_parameter_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.function_parameter_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::FunctionParameter& Value::_internal_function_parameter() const { + return kind_case() == kFunctionParameter ? *reinterpret_cast<::tint::core::ir::binary::pb::FunctionParameter*>(_impl_.kind_.function_parameter_) : reinterpret_cast<::tint::core::ir::binary::pb::FunctionParameter&>(::tint::core::ir::binary::pb::_FunctionParameter_default_instance_); +} +inline const ::tint::core::ir::binary::pb::FunctionParameter& Value::function_parameter() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Value.function_parameter) + return _internal_function_parameter(); +} +inline ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE Value::unsafe_arena_release_function_parameter() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Value.function_parameter) + if (kind_case() == kFunctionParameter) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::FunctionParameter*>(_impl_.kind_.function_parameter_); + _impl_.kind_.function_parameter_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Value::unsafe_arena_set_allocated_function_parameter( + ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_function_parameter(); + _impl_.kind_.function_parameter_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Value.function_parameter) +} +inline ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NONNULL Value::_internal_mutable_function_parameter() { + if (kind_case() != kFunctionParameter) { + clear_kind(); + set_has_function_parameter(); + _impl_.kind_.function_parameter_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::FunctionParameter>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::FunctionParameter*>(_impl_.kind_.function_parameter_); +} +inline ::tint::core::ir::binary::pb::FunctionParameter* PROTOBUF_NONNULL Value::mutable_function_parameter() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::FunctionParameter* _msg = _internal_mutable_function_parameter(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Value.function_parameter) + return _msg; +} + +// .tint.core.ir.binary.pb.BlockParameter block_parameter = 4; +inline bool Value::has_block_parameter() const { + return kind_case() == kBlockParameter; +} +inline bool Value::_internal_has_block_parameter() const { + return kind_case() == kBlockParameter; +} +inline void Value::set_has_block_parameter() { + _impl_._oneof_case_[0] = kBlockParameter; +} +inline void Value::clear_block_parameter() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBlockParameter) { + if (GetArena() == nullptr) { + delete _impl_.kind_.block_parameter_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.block_parameter_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE Value::release_block_parameter() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Value.block_parameter) + if (kind_case() == kBlockParameter) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::BlockParameter*>(_impl_.kind_.block_parameter_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.block_parameter_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::BlockParameter& Value::_internal_block_parameter() const { + return kind_case() == kBlockParameter ? *reinterpret_cast<::tint::core::ir::binary::pb::BlockParameter*>(_impl_.kind_.block_parameter_) : reinterpret_cast<::tint::core::ir::binary::pb::BlockParameter&>(::tint::core::ir::binary::pb::_BlockParameter_default_instance_); +} +inline const ::tint::core::ir::binary::pb::BlockParameter& Value::block_parameter() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Value.block_parameter) + return _internal_block_parameter(); +} +inline ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE Value::unsafe_arena_release_block_parameter() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Value.block_parameter) + if (kind_case() == kBlockParameter) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::BlockParameter*>(_impl_.kind_.block_parameter_); + _impl_.kind_.block_parameter_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Value::unsafe_arena_set_allocated_block_parameter( + ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_block_parameter(); + _impl_.kind_.block_parameter_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Value.block_parameter) +} +inline ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NONNULL Value::_internal_mutable_block_parameter() { + if (kind_case() != kBlockParameter) { + clear_kind(); + set_has_block_parameter(); + _impl_.kind_.block_parameter_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::BlockParameter>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::BlockParameter*>(_impl_.kind_.block_parameter_); +} +inline ::tint::core::ir::binary::pb::BlockParameter* PROTOBUF_NONNULL Value::mutable_block_parameter() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::BlockParameter* _msg = _internal_mutable_block_parameter(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Value.block_parameter) + return _msg; +} + +// uint32 constant = 5; +inline bool Value::has_constant() const { + return kind_case() == kConstant; +} +inline void Value::set_has_constant() { + _impl_._oneof_case_[0] = kConstant; +} +inline void Value::clear_constant() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kConstant) { + _impl_.kind_.constant_ = 0u; + clear_has_kind(); + } +} +inline ::uint32_t Value::constant() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Value.constant) + return _internal_constant(); +} +inline void Value::set_constant(::uint32_t value) { + if (kind_case() != kConstant) { + clear_kind(); + set_has_constant(); + } + _impl_.kind_.constant_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Value.constant) +} +inline ::uint32_t Value::_internal_constant() const { + if (kind_case() == kConstant) { + return _impl_.kind_.constant_; + } + return 0u; +} + +inline bool Value::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void Value::clear_has_kind() { + _impl_._oneof_case_[0] = KIND_NOT_SET; +} +inline Value::KindCase Value::kind_case() const { + return Value::KindCase(_impl_._oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// InstructionResult + +// uint32 type = 1; +inline void InstructionResult::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t InstructionResult::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionResult.type) + return _internal_type(); +} +inline void InstructionResult::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionResult.type) +} +inline ::uint32_t InstructionResult::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void InstructionResult::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// optional string name = 2; +inline bool InstructionResult::has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + return value; +} +inline void InstructionResult::clear_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::std::string& InstructionResult::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionResult.name) + return _internal_name(); +} +template +PROTOBUF_ALWAYS_INLINE void InstructionResult::set_name(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionResult.name) +} +inline ::std::string* PROTOBUF_NONNULL InstructionResult::mutable_name() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.InstructionResult.name) + return _s; +} +inline const ::std::string& InstructionResult::_internal_name() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.name_.Get(); +} +inline void InstructionResult::_internal_set_name(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL InstructionResult::_internal_mutable_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + return _impl_.name_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE InstructionResult::release_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.InstructionResult.name) + if ((_impl_._has_bits_[0] & 0x00000001U) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001U; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; +} +inline void InstructionResult::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + _impl_.name_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.InstructionResult.name) +} + +// ------------------------------------------------------------------- + +// FunctionParameter + +// uint32 type = 1; +inline void FunctionParameter::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t FunctionParameter::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.FunctionParameter.type) + return _internal_type(); +} +inline void FunctionParameter::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.FunctionParameter.type) +} +inline ::uint32_t FunctionParameter::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void FunctionParameter::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// optional string name = 2; +inline bool FunctionParameter::has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + return value; +} +inline void FunctionParameter::clear_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::std::string& FunctionParameter::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.FunctionParameter.name) + return _internal_name(); +} +template +PROTOBUF_ALWAYS_INLINE void FunctionParameter::set_name(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.FunctionParameter.name) +} +inline ::std::string* PROTOBUF_NONNULL FunctionParameter::mutable_name() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.FunctionParameter.name) + return _s; +} +inline const ::std::string& FunctionParameter::_internal_name() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.name_.Get(); +} +inline void FunctionParameter::_internal_set_name(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL FunctionParameter::_internal_mutable_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + return _impl_.name_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE FunctionParameter::release_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.FunctionParameter.name) + if ((_impl_._has_bits_[0] & 0x00000001U) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001U; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; +} +inline void FunctionParameter::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + _impl_.name_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.FunctionParameter.name) +} + +// optional .tint.core.ir.binary.pb.AttributesFunctionParameter attributes = 3; +inline bool FunctionParameter::has_attributes() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + PROTOBUF_ASSUME(!value || _impl_.attributes_ != nullptr); + return value; +} +inline void FunctionParameter::clear_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attributes_ != nullptr) _impl_.attributes_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline const ::tint::core::ir::binary::pb::AttributesFunctionParameter& FunctionParameter::_internal_attributes() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::AttributesFunctionParameter* p = _impl_.attributes_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_AttributesFunctionParameter_default_instance_); +} +inline const ::tint::core::ir::binary::pb::AttributesFunctionParameter& FunctionParameter::attributes() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.FunctionParameter.attributes) + return _internal_attributes(); +} +inline void FunctionParameter::unsafe_arena_set_allocated_attributes( + ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attributes_); + } + _impl_.attributes_ = reinterpret_cast<::tint::core::ir::binary::pb::AttributesFunctionParameter*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.FunctionParameter.attributes) +} +inline ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE FunctionParameter::release_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::AttributesFunctionParameter* released = _impl_.attributes_; + _impl_.attributes_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE FunctionParameter::unsafe_arena_release_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.FunctionParameter.attributes) + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::AttributesFunctionParameter* temp = _impl_.attributes_; + _impl_.attributes_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NONNULL FunctionParameter::_internal_mutable_attributes() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attributes_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::AttributesFunctionParameter>(GetArena()); + _impl_.attributes_ = reinterpret_cast<::tint::core::ir::binary::pb::AttributesFunctionParameter*>(p); + } + return _impl_.attributes_; +} +inline ::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NONNULL FunctionParameter::mutable_attributes() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000002U; + ::tint::core::ir::binary::pb::AttributesFunctionParameter* _msg = _internal_mutable_attributes(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.FunctionParameter.attributes) + return _msg; +} +inline void FunctionParameter::set_allocated_attributes(::tint::core::ir::binary::pb::AttributesFunctionParameter* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attributes_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + + _impl_.attributes_ = reinterpret_cast<::tint::core::ir::binary::pb::AttributesFunctionParameter*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.FunctionParameter.attributes) +} + +// ------------------------------------------------------------------- + +// BlockParameter + +// uint32 type = 1; +inline void BlockParameter::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t BlockParameter::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.BlockParameter.type) + return _internal_type(); +} +inline void BlockParameter::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.BlockParameter.type) +} +inline ::uint32_t BlockParameter::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void BlockParameter::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// optional string name = 2; +inline bool BlockParameter::has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + return value; +} +inline void BlockParameter::clear_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::std::string& BlockParameter::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.BlockParameter.name) + return _internal_name(); +} +template +PROTOBUF_ALWAYS_INLINE void BlockParameter::set_name(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.BlockParameter.name) +} +inline ::std::string* PROTOBUF_NONNULL BlockParameter::mutable_name() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.BlockParameter.name) + return _s; +} +inline const ::std::string& BlockParameter::_internal_name() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.name_.Get(); +} +inline void BlockParameter::_internal_set_name(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL BlockParameter::_internal_mutable_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + return _impl_.name_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE BlockParameter::release_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.BlockParameter.name) + if ((_impl_._has_bits_[0] & 0x00000001U) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001U; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; +} +inline void BlockParameter::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + _impl_.name_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.BlockParameter.name) +} + +// ------------------------------------------------------------------- + +// ConstantValue + +// .tint.core.ir.binary.pb.ConstantValueScalar scalar = 1; +inline bool ConstantValue::has_scalar() const { + return kind_case() == kScalar; +} +inline bool ConstantValue::_internal_has_scalar() const { + return kind_case() == kScalar; +} +inline void ConstantValue::set_has_scalar() { + _impl_._oneof_case_[0] = kScalar; +} +inline void ConstantValue::clear_scalar() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kScalar) { + if (GetArena() == nullptr) { + delete _impl_.kind_.scalar_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.scalar_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE ConstantValue::release_scalar() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.ConstantValue.scalar) + if (kind_case() == kScalar) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueScalar*>(_impl_.kind_.scalar_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.scalar_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::ConstantValueScalar& ConstantValue::_internal_scalar() const { + return kind_case() == kScalar ? *reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueScalar*>(_impl_.kind_.scalar_) : reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueScalar&>(::tint::core::ir::binary::pb::_ConstantValueScalar_default_instance_); +} +inline const ::tint::core::ir::binary::pb::ConstantValueScalar& ConstantValue::scalar() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValue.scalar) + return _internal_scalar(); +} +inline ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE ConstantValue::unsafe_arena_release_scalar() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.ConstantValue.scalar) + if (kind_case() == kScalar) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueScalar*>(_impl_.kind_.scalar_); + _impl_.kind_.scalar_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void ConstantValue::unsafe_arena_set_allocated_scalar( + ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_scalar(); + _impl_.kind_.scalar_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.ConstantValue.scalar) +} +inline ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NONNULL ConstantValue::_internal_mutable_scalar() { + if (kind_case() != kScalar) { + clear_kind(); + set_has_scalar(); + _impl_.kind_.scalar_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::ConstantValueScalar>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueScalar*>(_impl_.kind_.scalar_); +} +inline ::tint::core::ir::binary::pb::ConstantValueScalar* PROTOBUF_NONNULL ConstantValue::mutable_scalar() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::ConstantValueScalar* _msg = _internal_mutable_scalar(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.ConstantValue.scalar) + return _msg; +} + +// .tint.core.ir.binary.pb.ConstantValueComposite composite = 2; +inline bool ConstantValue::has_composite() const { + return kind_case() == kComposite; +} +inline bool ConstantValue::_internal_has_composite() const { + return kind_case() == kComposite; +} +inline void ConstantValue::set_has_composite() { + _impl_._oneof_case_[0] = kComposite; +} +inline void ConstantValue::clear_composite() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kComposite) { + if (GetArena() == nullptr) { + delete _impl_.kind_.composite_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.composite_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE ConstantValue::release_composite() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.ConstantValue.composite) + if (kind_case() == kComposite) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueComposite*>(_impl_.kind_.composite_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.composite_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::ConstantValueComposite& ConstantValue::_internal_composite() const { + return kind_case() == kComposite ? *reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueComposite*>(_impl_.kind_.composite_) : reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueComposite&>(::tint::core::ir::binary::pb::_ConstantValueComposite_default_instance_); +} +inline const ::tint::core::ir::binary::pb::ConstantValueComposite& ConstantValue::composite() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValue.composite) + return _internal_composite(); +} +inline ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE ConstantValue::unsafe_arena_release_composite() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.ConstantValue.composite) + if (kind_case() == kComposite) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueComposite*>(_impl_.kind_.composite_); + _impl_.kind_.composite_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void ConstantValue::unsafe_arena_set_allocated_composite( + ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_composite(); + _impl_.kind_.composite_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.ConstantValue.composite) +} +inline ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NONNULL ConstantValue::_internal_mutable_composite() { + if (kind_case() != kComposite) { + clear_kind(); + set_has_composite(); + _impl_.kind_.composite_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::ConstantValueComposite>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueComposite*>(_impl_.kind_.composite_); +} +inline ::tint::core::ir::binary::pb::ConstantValueComposite* PROTOBUF_NONNULL ConstantValue::mutable_composite() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::ConstantValueComposite* _msg = _internal_mutable_composite(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.ConstantValue.composite) + return _msg; +} + +// .tint.core.ir.binary.pb.ConstantValueSplat splat = 3; +inline bool ConstantValue::has_splat() const { + return kind_case() == kSplat; +} +inline bool ConstantValue::_internal_has_splat() const { + return kind_case() == kSplat; +} +inline void ConstantValue::set_has_splat() { + _impl_._oneof_case_[0] = kSplat; +} +inline void ConstantValue::clear_splat() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSplat) { + if (GetArena() == nullptr) { + delete _impl_.kind_.splat_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.splat_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE ConstantValue::release_splat() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.ConstantValue.splat) + if (kind_case() == kSplat) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueSplat*>(_impl_.kind_.splat_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.splat_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::ConstantValueSplat& ConstantValue::_internal_splat() const { + return kind_case() == kSplat ? *reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueSplat*>(_impl_.kind_.splat_) : reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueSplat&>(::tint::core::ir::binary::pb::_ConstantValueSplat_default_instance_); +} +inline const ::tint::core::ir::binary::pb::ConstantValueSplat& ConstantValue::splat() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValue.splat) + return _internal_splat(); +} +inline ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE ConstantValue::unsafe_arena_release_splat() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.ConstantValue.splat) + if (kind_case() == kSplat) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueSplat*>(_impl_.kind_.splat_); + _impl_.kind_.splat_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void ConstantValue::unsafe_arena_set_allocated_splat( + ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_splat(); + _impl_.kind_.splat_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.ConstantValue.splat) +} +inline ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NONNULL ConstantValue::_internal_mutable_splat() { + if (kind_case() != kSplat) { + clear_kind(); + set_has_splat(); + _impl_.kind_.splat_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::ConstantValueSplat>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::ConstantValueSplat*>(_impl_.kind_.splat_); +} +inline ::tint::core::ir::binary::pb::ConstantValueSplat* PROTOBUF_NONNULL ConstantValue::mutable_splat() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::ConstantValueSplat* _msg = _internal_mutable_splat(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.ConstantValue.splat) + return _msg; +} + +inline bool ConstantValue::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void ConstantValue::clear_has_kind() { + _impl_._oneof_case_[0] = KIND_NOT_SET; +} +inline ConstantValue::KindCase ConstantValue::kind_case() const { + return ConstantValue::KindCase(_impl_._oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// ConstantValueScalar + +// bool bool = 1; +inline bool ConstantValueScalar::has_bool_() const { + return kind_case() == kBool; +} +inline void ConstantValueScalar::set_has_bool_() { + _impl_._oneof_case_[0] = kBool; +} +inline void ConstantValueScalar::clear_bool_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBool) { + _impl_.kind_.bool__ = false; + clear_has_kind(); + } +} +inline bool ConstantValueScalar::bool_() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueScalar.bool) + return _internal_bool_(); +} +inline void ConstantValueScalar::set_bool_(bool value) { + if (kind_case() != kBool) { + clear_kind(); + set_has_bool_(); + } + _impl_.kind_.bool__ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueScalar.bool) +} +inline bool ConstantValueScalar::_internal_bool_() const { + if (kind_case() == kBool) { + return _impl_.kind_.bool__; + } + return false; +} + +// int32 i32 = 2; +inline bool ConstantValueScalar::has_i32() const { + return kind_case() == kI32; +} +inline void ConstantValueScalar::set_has_i32() { + _impl_._oneof_case_[0] = kI32; +} +inline void ConstantValueScalar::clear_i32() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kI32) { + _impl_.kind_.i32_ = 0; + clear_has_kind(); + } +} +inline ::int32_t ConstantValueScalar::i32() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueScalar.i32) + return _internal_i32(); +} +inline void ConstantValueScalar::set_i32(::int32_t value) { + if (kind_case() != kI32) { + clear_kind(); + set_has_i32(); + } + _impl_.kind_.i32_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueScalar.i32) +} +inline ::int32_t ConstantValueScalar::_internal_i32() const { + if (kind_case() == kI32) { + return _impl_.kind_.i32_; + } + return 0; +} + +// uint32 u32 = 3; +inline bool ConstantValueScalar::has_u32() const { + return kind_case() == kU32; +} +inline void ConstantValueScalar::set_has_u32() { + _impl_._oneof_case_[0] = kU32; +} +inline void ConstantValueScalar::clear_u32() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kU32) { + _impl_.kind_.u32_ = 0u; + clear_has_kind(); + } +} +inline ::uint32_t ConstantValueScalar::u32() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueScalar.u32) + return _internal_u32(); +} +inline void ConstantValueScalar::set_u32(::uint32_t value) { + if (kind_case() != kU32) { + clear_kind(); + set_has_u32(); + } + _impl_.kind_.u32_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueScalar.u32) +} +inline ::uint32_t ConstantValueScalar::_internal_u32() const { + if (kind_case() == kU32) { + return _impl_.kind_.u32_; + } + return 0u; +} + +// float f32 = 4; +inline bool ConstantValueScalar::has_f32() const { + return kind_case() == kF32; +} +inline void ConstantValueScalar::set_has_f32() { + _impl_._oneof_case_[0] = kF32; +} +inline void ConstantValueScalar::clear_f32() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kF32) { + _impl_.kind_.f32_ = 0; + clear_has_kind(); + } +} +inline float ConstantValueScalar::f32() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueScalar.f32) + return _internal_f32(); +} +inline void ConstantValueScalar::set_f32(float value) { + if (kind_case() != kF32) { + clear_kind(); + set_has_f32(); + } + _impl_.kind_.f32_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueScalar.f32) +} +inline float ConstantValueScalar::_internal_f32() const { + if (kind_case() == kF32) { + return _impl_.kind_.f32_; + } + return 0; +} + +// float f16 = 5; +inline bool ConstantValueScalar::has_f16() const { + return kind_case() == kF16; +} +inline void ConstantValueScalar::set_has_f16() { + _impl_._oneof_case_[0] = kF16; +} +inline void ConstantValueScalar::clear_f16() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kF16) { + _impl_.kind_.f16_ = 0; + clear_has_kind(); + } +} +inline float ConstantValueScalar::f16() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueScalar.f16) + return _internal_f16(); +} +inline void ConstantValueScalar::set_f16(float value) { + if (kind_case() != kF16) { + clear_kind(); + set_has_f16(); + } + _impl_.kind_.f16_ = value; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueScalar.f16) +} +inline float ConstantValueScalar::_internal_f16() const { + if (kind_case() == kF16) { + return _impl_.kind_.f16_; + } + return 0; +} + +inline bool ConstantValueScalar::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void ConstantValueScalar::clear_has_kind() { + _impl_._oneof_case_[0] = KIND_NOT_SET; +} +inline ConstantValueScalar::KindCase ConstantValueScalar::kind_case() const { + return ConstantValueScalar::KindCase(_impl_._oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// ConstantValueComposite + +// uint32 type = 1; +inline void ConstantValueComposite::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t ConstantValueComposite::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueComposite.type) + return _internal_type(); +} +inline void ConstantValueComposite::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueComposite.type) +} +inline ::uint32_t ConstantValueComposite::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void ConstantValueComposite::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// repeated uint32 elements = 2; +inline int ConstantValueComposite::_internal_elements_size() const { + return _internal_elements().size(); +} +inline int ConstantValueComposite::elements_size() const { + return _internal_elements_size(); +} +inline void ConstantValueComposite::clear_elements() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.elements_.Clear(); +} +inline ::uint32_t ConstantValueComposite::elements(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueComposite.elements) + return _internal_elements().Get(index); +} +inline void ConstantValueComposite::set_elements(int index, ::uint32_t value) { + _internal_mutable_elements()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueComposite.elements) +} +inline void ConstantValueComposite::add_elements(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_elements()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.ConstantValueComposite.elements) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& ConstantValueComposite::elements() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.ConstantValueComposite.elements) + return _internal_elements(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL ConstantValueComposite::mutable_elements() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.ConstantValueComposite.elements) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_elements(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +ConstantValueComposite::_internal_elements() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.elements_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +ConstantValueComposite::_internal_mutable_elements() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.elements_; +} + +// ------------------------------------------------------------------- + +// ConstantValueSplat + +// uint32 type = 1; +inline void ConstantValueSplat::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t ConstantValueSplat::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueSplat.type) + return _internal_type(); +} +inline void ConstantValueSplat::set_type(::uint32_t value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueSplat.type) +} +inline ::uint32_t ConstantValueSplat::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.type_; +} +inline void ConstantValueSplat::_internal_set_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// uint32 elements = 2; +inline void ConstantValueSplat::clear_elements() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.elements_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t ConstantValueSplat::elements() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueSplat.elements) + return _internal_elements(); +} +inline void ConstantValueSplat::set_elements(::uint32_t value) { + _internal_set_elements(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueSplat.elements) +} +inline ::uint32_t ConstantValueSplat::_internal_elements() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.elements_; +} +inline void ConstantValueSplat::_internal_set_elements(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.elements_ = value; +} + +// uint32 count = 3; +inline void ConstantValueSplat::clear_count() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t ConstantValueSplat::count() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.ConstantValueSplat.count) + return _internal_count(); +} +inline void ConstantValueSplat::set_count(::uint32_t value) { + _internal_set_count(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.ConstantValueSplat.count) +} +inline ::uint32_t ConstantValueSplat::_internal_count() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.count_; +} +inline void ConstantValueSplat::_internal_set_count(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.count_ = value; +} + +// ------------------------------------------------------------------- + +// Function + +// uint32 return_type = 1; +inline void Function::clear_return_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_type_ = 0u; + _impl_._has_bits_[0] &= ~0x00000008U; +} +inline ::uint32_t Function::return_type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.return_type) + return _internal_return_type(); +} +inline void Function::set_return_type(::uint32_t value) { + _internal_set_return_type(value); + _impl_._has_bits_[0] |= 0x00000008U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.return_type) +} +inline ::uint32_t Function::_internal_return_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.return_type_; +} +inline void Function::_internal_set_return_type(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_type_ = value; +} + +// uint32 block = 2; +inline void Function::clear_block() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.block_ = 0u; + _impl_._has_bits_[0] &= ~0x00000010U; +} +inline ::uint32_t Function::block() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.block) + return _internal_block(); +} +inline void Function::set_block(::uint32_t value) { + _internal_set_block(value); + _impl_._has_bits_[0] |= 0x00000010U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.block) +} +inline ::uint32_t Function::_internal_block() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.block_; +} +inline void Function::_internal_set_block(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.block_ = value; +} + +// optional string name = 3; +inline bool Function::has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + return value; +} +inline void Function::clear_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::std::string& Function::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.name) + return _internal_name(); +} +template +PROTOBUF_ALWAYS_INLINE void Function::set_name(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.name) +} +inline ::std::string* PROTOBUF_NONNULL Function::mutable_name() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Function.name) + return _s; +} +inline const ::std::string& Function::_internal_name() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.name_.Get(); +} +inline void Function::_internal_set_name(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + _impl_.name_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Function::_internal_mutable_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001U; + return _impl_.name_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Function::release_name() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Function.name) + if ((_impl_._has_bits_[0] & 0x00000001U) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001U; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; +} +inline void Function::set_allocated_name(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + _impl_.name_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Function.name) +} + +// optional .tint.core.ir.binary.pb.PipelineStage pipeline_stage = 4; +inline bool Function::has_pipeline_stage() const { + bool value = (_impl_._has_bits_[0] & 0x00000020U) != 0; + return value; +} +inline void Function::clear_pipeline_stage() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pipeline_stage_ = 0; + _impl_._has_bits_[0] &= ~0x00000020U; +} +inline ::tint::core::ir::binary::pb::PipelineStage Function::pipeline_stage() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.pipeline_stage) + return _internal_pipeline_stage(); +} +inline void Function::set_pipeline_stage(::tint::core::ir::binary::pb::PipelineStage value) { + _internal_set_pipeline_stage(value); + _impl_._has_bits_[0] |= 0x00000020U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.pipeline_stage) +} +inline ::tint::core::ir::binary::pb::PipelineStage Function::_internal_pipeline_stage() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::PipelineStage>(_impl_.pipeline_stage_); +} +inline void Function::_internal_set_pipeline_stage(::tint::core::ir::binary::pb::PipelineStage value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.pipeline_stage_ = value; +} + +// optional .tint.core.ir.binary.pb.WorkgroupSize workgroup_size = 5; +inline bool Function::has_workgroup_size() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + PROTOBUF_ASSUME(!value || _impl_.workgroup_size_ != nullptr); + return value; +} +inline void Function::clear_workgroup_size() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.workgroup_size_ != nullptr) _impl_.workgroup_size_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline const ::tint::core::ir::binary::pb::WorkgroupSize& Function::_internal_workgroup_size() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::WorkgroupSize* p = _impl_.workgroup_size_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_WorkgroupSize_default_instance_); +} +inline const ::tint::core::ir::binary::pb::WorkgroupSize& Function::workgroup_size() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.workgroup_size) + return _internal_workgroup_size(); +} +inline void Function::unsafe_arena_set_allocated_workgroup_size( + ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.workgroup_size_); + } + _impl_.workgroup_size_ = reinterpret_cast<::tint::core::ir::binary::pb::WorkgroupSize*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Function.workgroup_size) +} +inline ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE Function::release_workgroup_size() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::WorkgroupSize* released = _impl_.workgroup_size_; + _impl_.workgroup_size_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE Function::unsafe_arena_release_workgroup_size() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Function.workgroup_size) + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::WorkgroupSize* temp = _impl_.workgroup_size_; + _impl_.workgroup_size_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NONNULL Function::_internal_mutable_workgroup_size() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.workgroup_size_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::WorkgroupSize>(GetArena()); + _impl_.workgroup_size_ = reinterpret_cast<::tint::core::ir::binary::pb::WorkgroupSize*>(p); + } + return _impl_.workgroup_size_; +} +inline ::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NONNULL Function::mutable_workgroup_size() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000002U; + ::tint::core::ir::binary::pb::WorkgroupSize* _msg = _internal_mutable_workgroup_size(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Function.workgroup_size) + return _msg; +} +inline void Function::set_allocated_workgroup_size(::tint::core::ir::binary::pb::WorkgroupSize* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.workgroup_size_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + + _impl_.workgroup_size_ = reinterpret_cast<::tint::core::ir::binary::pb::WorkgroupSize*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Function.workgroup_size) +} + +// repeated uint32 parameters = 6; +inline int Function::_internal_parameters_size() const { + return _internal_parameters().size(); +} +inline int Function::parameters_size() const { + return _internal_parameters_size(); +} +inline void Function::clear_parameters() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.parameters_.Clear(); +} +inline ::uint32_t Function::parameters(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.parameters) + return _internal_parameters().Get(index); +} +inline void Function::set_parameters(int index, ::uint32_t value) { + _internal_mutable_parameters()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.parameters) +} +inline void Function::add_parameters(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_parameters()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Function.parameters) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& Function::parameters() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Function.parameters) + return _internal_parameters(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL Function::mutable_parameters() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Function.parameters) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_parameters(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +Function::_internal_parameters() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.parameters_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +Function::_internal_mutable_parameters() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.parameters_; +} + +// optional uint32 return_location = 7; +inline bool Function::has_return_location() const { + bool value = (_impl_._has_bits_[0] & 0x00000040U) != 0; + return value; +} +inline void Function::clear_return_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_location_ = 0u; + _impl_._has_bits_[0] &= ~0x00000040U; +} +inline ::uint32_t Function::return_location() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.return_location) + return _internal_return_location(); +} +inline void Function::set_return_location(::uint32_t value) { + _internal_set_return_location(value); + _impl_._has_bits_[0] |= 0x00000040U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.return_location) +} +inline ::uint32_t Function::_internal_return_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.return_location_; +} +inline void Function::_internal_set_return_location(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_location_ = value; +} + +// optional .tint.core.ir.binary.pb.Interpolation return_interpolation = 8; +inline bool Function::has_return_interpolation() const { + bool value = (_impl_._has_bits_[0] & 0x00000004U) != 0; + PROTOBUF_ASSUME(!value || _impl_.return_interpolation_ != nullptr); + return value; +} +inline void Function::clear_return_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.return_interpolation_ != nullptr) _impl_.return_interpolation_->Clear(); + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline const ::tint::core::ir::binary::pb::Interpolation& Function::_internal_return_interpolation() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::Interpolation* p = _impl_.return_interpolation_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_Interpolation_default_instance_); +} +inline const ::tint::core::ir::binary::pb::Interpolation& Function::return_interpolation() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.return_interpolation) + return _internal_return_interpolation(); +} +inline void Function::unsafe_arena_set_allocated_return_interpolation( + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.return_interpolation_); + } + _impl_.return_interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000004U; + } else { + _impl_._has_bits_[0] &= ~0x00000004U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Function.return_interpolation) +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE Function::release_return_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000004U; + ::tint::core::ir::binary::pb::Interpolation* released = _impl_.return_interpolation_; + _impl_.return_interpolation_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE Function::unsafe_arena_release_return_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Function.return_interpolation) + + _impl_._has_bits_[0] &= ~0x00000004U; + ::tint::core::ir::binary::pb::Interpolation* temp = _impl_.return_interpolation_; + _impl_.return_interpolation_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL Function::_internal_mutable_return_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.return_interpolation_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::Interpolation>(GetArena()); + _impl_.return_interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(p); + } + return _impl_.return_interpolation_; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL Function::mutable_return_interpolation() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000004U; + ::tint::core::ir::binary::pb::Interpolation* _msg = _internal_mutable_return_interpolation(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Function.return_interpolation) + return _msg; +} +inline void Function::set_allocated_return_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.return_interpolation_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000004U; + } else { + _impl_._has_bits_[0] &= ~0x00000004U; + } + + _impl_.return_interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.Function.return_interpolation) +} + +// optional .tint.core.ir.binary.pb.BuiltinValue return_builtin = 9; +inline bool Function::has_return_builtin() const { + bool value = (_impl_._has_bits_[0] & 0x00000080U) != 0; + return value; +} +inline void Function::clear_return_builtin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_builtin_ = 0; + _impl_._has_bits_[0] &= ~0x00000080U; +} +inline ::tint::core::ir::binary::pb::BuiltinValue Function::return_builtin() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.return_builtin) + return _internal_return_builtin(); +} +inline void Function::set_return_builtin(::tint::core::ir::binary::pb::BuiltinValue value) { + _internal_set_return_builtin(value); + _impl_._has_bits_[0] |= 0x00000080U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.return_builtin) +} +inline ::tint::core::ir::binary::pb::BuiltinValue Function::_internal_return_builtin() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::BuiltinValue>(_impl_.return_builtin_); +} +inline void Function::_internal_set_return_builtin(::tint::core::ir::binary::pb::BuiltinValue value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_builtin_ = value; +} + +// bool return_invariant = 10; +inline void Function::clear_return_invariant() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_invariant_ = false; + _impl_._has_bits_[0] &= ~0x00000100U; +} +inline bool Function::return_invariant() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.return_invariant) + return _internal_return_invariant(); +} +inline void Function::set_return_invariant(bool value) { + _internal_set_return_invariant(value); + _impl_._has_bits_[0] |= 0x00000100U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.return_invariant) +} +inline bool Function::_internal_return_invariant() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.return_invariant_; +} +inline void Function::_internal_set_return_invariant(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.return_invariant_ = value; +} + +// optional uint32 subgroup_size = 11; +inline bool Function::has_subgroup_size() const { + bool value = (_impl_._has_bits_[0] & 0x00000200U) != 0; + return value; +} +inline void Function::clear_subgroup_size() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.subgroup_size_ = 0u; + _impl_._has_bits_[0] &= ~0x00000200U; +} +inline ::uint32_t Function::subgroup_size() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Function.subgroup_size) + return _internal_subgroup_size(); +} +inline void Function::set_subgroup_size(::uint32_t value) { + _internal_set_subgroup_size(value); + _impl_._has_bits_[0] |= 0x00000200U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Function.subgroup_size) +} +inline ::uint32_t Function::_internal_subgroup_size() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.subgroup_size_; +} +inline void Function::_internal_set_subgroup_size(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.subgroup_size_ = value; +} + +// ------------------------------------------------------------------- + +// WorkgroupSize + +// uint32 x = 1; +inline void WorkgroupSize::clear_x() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.x_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t WorkgroupSize::x() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.WorkgroupSize.x) + return _internal_x(); +} +inline void WorkgroupSize::set_x(::uint32_t value) { + _internal_set_x(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.WorkgroupSize.x) +} +inline ::uint32_t WorkgroupSize::_internal_x() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.x_; +} +inline void WorkgroupSize::_internal_set_x(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.x_ = value; +} + +// uint32 y = 2; +inline void WorkgroupSize::clear_y() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.y_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t WorkgroupSize::y() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.WorkgroupSize.y) + return _internal_y(); +} +inline void WorkgroupSize::set_y(::uint32_t value) { + _internal_set_y(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.WorkgroupSize.y) +} +inline ::uint32_t WorkgroupSize::_internal_y() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.y_; +} +inline void WorkgroupSize::_internal_set_y(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.y_ = value; +} + +// uint32 z = 3; +inline void WorkgroupSize::clear_z() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.z_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t WorkgroupSize::z() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.WorkgroupSize.z) + return _internal_z(); +} +inline void WorkgroupSize::set_z(::uint32_t value) { + _internal_set_z(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.WorkgroupSize.z) +} +inline ::uint32_t WorkgroupSize::_internal_z() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.z_; +} +inline void WorkgroupSize::_internal_set_z(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.z_ = value; +} + +// ------------------------------------------------------------------- + +// Block + +// repeated uint32 parameters = 1; +inline int Block::_internal_parameters_size() const { + return _internal_parameters().size(); +} +inline int Block::parameters_size() const { + return _internal_parameters_size(); +} +inline void Block::clear_parameters() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.parameters_.Clear(); +} +inline ::uint32_t Block::parameters(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Block.parameters) + return _internal_parameters().Get(index); +} +inline void Block::set_parameters(int index, ::uint32_t value) { + _internal_mutable_parameters()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Block.parameters) +} +inline void Block::add_parameters(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_parameters()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Block.parameters) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& Block::parameters() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Block.parameters) + return _internal_parameters(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL Block::mutable_parameters() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Block.parameters) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_parameters(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +Block::_internal_parameters() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.parameters_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +Block::_internal_mutable_parameters() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.parameters_; +} + +// repeated .tint.core.ir.binary.pb.Instruction instructions = 2; +inline int Block::_internal_instructions_size() const { + return _internal_instructions().size(); +} +inline int Block::instructions_size() const { + return _internal_instructions_size(); +} +inline void Block::clear_instructions() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.instructions_.Clear(); +} +inline ::tint::core::ir::binary::pb::Instruction* PROTOBUF_NONNULL Block::mutable_instructions(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Block.instructions) + return _internal_mutable_instructions()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>* PROTOBUF_NONNULL Block::mutable_instructions() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Block.instructions) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_instructions(); +} +inline const ::tint::core::ir::binary::pb::Instruction& Block::instructions(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Block.instructions) + return _internal_instructions().Get(index); +} +inline ::tint::core::ir::binary::pb::Instruction* PROTOBUF_NONNULL Block::add_instructions() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::Instruction* _add = _internal_mutable_instructions()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Block.instructions) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>& Block::instructions() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Block.instructions) + return _internal_instructions(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>& +Block::_internal_instructions() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.instructions_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::Instruction>* PROTOBUF_NONNULL +Block::_internal_mutable_instructions() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.instructions_; +} + +// bool is_multi_in = 3; +inline void Block::clear_is_multi_in() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.is_multi_in_ = false; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline bool Block::is_multi_in() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Block.is_multi_in) + return _internal_is_multi_in(); +} +inline void Block::set_is_multi_in(bool value) { + _internal_set_is_multi_in(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Block.is_multi_in) +} +inline bool Block::_internal_is_multi_in() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.is_multi_in_; +} +inline void Block::_internal_set_is_multi_in(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.is_multi_in_ = value; +} + +// ------------------------------------------------------------------- + +// Instruction + +// repeated uint32 operands = 1; +inline int Instruction::_internal_operands_size() const { + return _internal_operands().size(); +} +inline int Instruction::operands_size() const { + return _internal_operands_size(); +} +inline void Instruction::clear_operands() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.operands_.Clear(); +} +inline ::uint32_t Instruction::operands(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.operands) + return _internal_operands().Get(index); +} +inline void Instruction::set_operands(int index, ::uint32_t value) { + _internal_mutable_operands()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Instruction.operands) +} +inline void Instruction::add_operands(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_operands()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Instruction.operands) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& Instruction::operands() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Instruction.operands) + return _internal_operands(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL Instruction::mutable_operands() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Instruction.operands) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_operands(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +Instruction::_internal_operands() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.operands_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +Instruction::_internal_mutable_operands() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.operands_; +} + +// repeated uint32 results = 2; +inline int Instruction::_internal_results_size() const { + return _internal_results().size(); +} +inline int Instruction::results_size() const { + return _internal_results_size(); +} +inline void Instruction::clear_results() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.results_.Clear(); +} +inline ::uint32_t Instruction::results(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.results) + return _internal_results().Get(index); +} +inline void Instruction::set_results(int index, ::uint32_t value) { + _internal_mutable_results()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Instruction.results) +} +inline void Instruction::add_results(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_results()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.Instruction.results) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& Instruction::results() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.Instruction.results) + return _internal_results(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL Instruction::mutable_results() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.Instruction.results) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_results(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +Instruction::_internal_results() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.results_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +Instruction::_internal_mutable_results() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.results_; +} + +// .tint.core.ir.binary.pb.InstructionReturn return = 3; +inline bool Instruction::has_return_() const { + return kind_case() == kReturn; +} +inline bool Instruction::_internal_has_return_() const { + return kind_case() == kReturn; +} +inline void Instruction::set_has_return_() { + _impl_._oneof_case_[0] = kReturn; +} +inline void Instruction::clear_return_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kReturn) { + if (GetArena() == nullptr) { + delete _impl_.kind_.return__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.return__); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE Instruction::release_return_() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.return) + if (kind_case() == kReturn) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionReturn*>(_impl_.kind_.return__); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.return__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionReturn& Instruction::_internal_return_() const { + return kind_case() == kReturn ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionReturn*>(_impl_.kind_.return__) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionReturn&>(::tint::core::ir::binary::pb::_InstructionReturn_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionReturn& Instruction::return_() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.return) + return _internal_return_(); +} +inline ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_return_() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.return) + if (kind_case() == kReturn) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionReturn*>(_impl_.kind_.return__); + _impl_.kind_.return__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_return_( + ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_return_(); + _impl_.kind_.return__ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.return) +} +inline ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NONNULL Instruction::_internal_mutable_return_() { + if (kind_case() != kReturn) { + clear_kind(); + set_has_return_(); + _impl_.kind_.return__ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionReturn>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionReturn*>(_impl_.kind_.return__); +} +inline ::tint::core::ir::binary::pb::InstructionReturn* PROTOBUF_NONNULL Instruction::mutable_return_() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionReturn* _msg = _internal_mutable_return_(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.return) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionUnary unary = 4; +inline bool Instruction::has_unary() const { + return kind_case() == kUnary; +} +inline bool Instruction::_internal_has_unary() const { + return kind_case() == kUnary; +} +inline void Instruction::set_has_unary() { + _impl_._oneof_case_[0] = kUnary; +} +inline void Instruction::clear_unary() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kUnary) { + if (GetArena() == nullptr) { + delete _impl_.kind_.unary_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.unary_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE Instruction::release_unary() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.unary) + if (kind_case() == kUnary) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnary*>(_impl_.kind_.unary_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.unary_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionUnary& Instruction::_internal_unary() const { + return kind_case() == kUnary ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnary*>(_impl_.kind_.unary_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnary&>(::tint::core::ir::binary::pb::_InstructionUnary_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionUnary& Instruction::unary() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.unary) + return _internal_unary(); +} +inline ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_unary() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.unary) + if (kind_case() == kUnary) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnary*>(_impl_.kind_.unary_); + _impl_.kind_.unary_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_unary( + ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_unary(); + _impl_.kind_.unary_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.unary) +} +inline ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NONNULL Instruction::_internal_mutable_unary() { + if (kind_case() != kUnary) { + clear_kind(); + set_has_unary(); + _impl_.kind_.unary_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionUnary>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnary*>(_impl_.kind_.unary_); +} +inline ::tint::core::ir::binary::pb::InstructionUnary* PROTOBUF_NONNULL Instruction::mutable_unary() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionUnary* _msg = _internal_mutable_unary(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.unary) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionBinary binary = 5; +inline bool Instruction::has_binary() const { + return kind_case() == kBinary; +} +inline bool Instruction::_internal_has_binary() const { + return kind_case() == kBinary; +} +inline void Instruction::set_has_binary() { + _impl_._oneof_case_[0] = kBinary; +} +inline void Instruction::clear_binary() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBinary) { + if (GetArena() == nullptr) { + delete _impl_.kind_.binary_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.binary_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE Instruction::release_binary() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.binary) + if (kind_case() == kBinary) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBinary*>(_impl_.kind_.binary_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.binary_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionBinary& Instruction::_internal_binary() const { + return kind_case() == kBinary ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionBinary*>(_impl_.kind_.binary_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionBinary&>(::tint::core::ir::binary::pb::_InstructionBinary_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionBinary& Instruction::binary() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.binary) + return _internal_binary(); +} +inline ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_binary() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.binary) + if (kind_case() == kBinary) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBinary*>(_impl_.kind_.binary_); + _impl_.kind_.binary_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_binary( + ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_binary(); + _impl_.kind_.binary_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.binary) +} +inline ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NONNULL Instruction::_internal_mutable_binary() { + if (kind_case() != kBinary) { + clear_kind(); + set_has_binary(); + _impl_.kind_.binary_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionBinary>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionBinary*>(_impl_.kind_.binary_); +} +inline ::tint::core::ir::binary::pb::InstructionBinary* PROTOBUF_NONNULL Instruction::mutable_binary() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionBinary* _msg = _internal_mutable_binary(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.binary) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionDiscard discard = 6; +inline bool Instruction::has_discard() const { + return kind_case() == kDiscard; +} +inline bool Instruction::_internal_has_discard() const { + return kind_case() == kDiscard; +} +inline void Instruction::set_has_discard() { + _impl_._oneof_case_[0] = kDiscard; +} +inline void Instruction::clear_discard() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kDiscard) { + if (GetArena() == nullptr) { + delete _impl_.kind_.discard_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.discard_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE Instruction::release_discard() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.discard) + if (kind_case() == kDiscard) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionDiscard*>(_impl_.kind_.discard_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.discard_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionDiscard& Instruction::_internal_discard() const { + return kind_case() == kDiscard ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionDiscard*>(_impl_.kind_.discard_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionDiscard&>(::tint::core::ir::binary::pb::_InstructionDiscard_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionDiscard& Instruction::discard() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.discard) + return _internal_discard(); +} +inline ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_discard() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.discard) + if (kind_case() == kDiscard) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionDiscard*>(_impl_.kind_.discard_); + _impl_.kind_.discard_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_discard( + ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_discard(); + _impl_.kind_.discard_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.discard) +} +inline ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NONNULL Instruction::_internal_mutable_discard() { + if (kind_case() != kDiscard) { + clear_kind(); + set_has_discard(); + _impl_.kind_.discard_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionDiscard>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionDiscard*>(_impl_.kind_.discard_); +} +inline ::tint::core::ir::binary::pb::InstructionDiscard* PROTOBUF_NONNULL Instruction::mutable_discard() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionDiscard* _msg = _internal_mutable_discard(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.discard) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionLet let = 7; +inline bool Instruction::has_let() const { + return kind_case() == kLet; +} +inline bool Instruction::_internal_has_let() const { + return kind_case() == kLet; +} +inline void Instruction::set_has_let() { + _impl_._oneof_case_[0] = kLet; +} +inline void Instruction::clear_let() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kLet) { + if (GetArena() == nullptr) { + delete _impl_.kind_.let_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.let_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE Instruction::release_let() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.let) + if (kind_case() == kLet) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLet*>(_impl_.kind_.let_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.let_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionLet& Instruction::_internal_let() const { + return kind_case() == kLet ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionLet*>(_impl_.kind_.let_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionLet&>(::tint::core::ir::binary::pb::_InstructionLet_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionLet& Instruction::let() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.let) + return _internal_let(); +} +inline ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_let() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.let) + if (kind_case() == kLet) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLet*>(_impl_.kind_.let_); + _impl_.kind_.let_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_let( + ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_let(); + _impl_.kind_.let_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.let) +} +inline ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NONNULL Instruction::_internal_mutable_let() { + if (kind_case() != kLet) { + clear_kind(); + set_has_let(); + _impl_.kind_.let_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionLet>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionLet*>(_impl_.kind_.let_); +} +inline ::tint::core::ir::binary::pb::InstructionLet* PROTOBUF_NONNULL Instruction::mutable_let() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionLet* _msg = _internal_mutable_let(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.let) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionVar var = 8; +inline bool Instruction::has_var() const { + return kind_case() == kVar; +} +inline bool Instruction::_internal_has_var() const { + return kind_case() == kVar; +} +inline void Instruction::set_has_var() { + _impl_._oneof_case_[0] = kVar; +} +inline void Instruction::clear_var() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kVar) { + if (GetArena() == nullptr) { + delete _impl_.kind_.var_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.var_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE Instruction::release_var() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.var) + if (kind_case() == kVar) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionVar*>(_impl_.kind_.var_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.var_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionVar& Instruction::_internal_var() const { + return kind_case() == kVar ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionVar*>(_impl_.kind_.var_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionVar&>(::tint::core::ir::binary::pb::_InstructionVar_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionVar& Instruction::var() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.var) + return _internal_var(); +} +inline ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_var() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.var) + if (kind_case() == kVar) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionVar*>(_impl_.kind_.var_); + _impl_.kind_.var_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_var( + ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_var(); + _impl_.kind_.var_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.var) +} +inline ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NONNULL Instruction::_internal_mutable_var() { + if (kind_case() != kVar) { + clear_kind(); + set_has_var(); + _impl_.kind_.var_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionVar>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionVar*>(_impl_.kind_.var_); +} +inline ::tint::core::ir::binary::pb::InstructionVar* PROTOBUF_NONNULL Instruction::mutable_var() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionVar* _msg = _internal_mutable_var(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.var) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionBitcast bitcast = 9; +inline bool Instruction::has_bitcast() const { + return kind_case() == kBitcast; +} +inline bool Instruction::_internal_has_bitcast() const { + return kind_case() == kBitcast; +} +inline void Instruction::set_has_bitcast() { + _impl_._oneof_case_[0] = kBitcast; +} +inline void Instruction::clear_bitcast() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBitcast) { + if (GetArena() == nullptr) { + delete _impl_.kind_.bitcast_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.bitcast_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE Instruction::release_bitcast() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.bitcast) + if (kind_case() == kBitcast) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBitcast*>(_impl_.kind_.bitcast_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.bitcast_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionBitcast& Instruction::_internal_bitcast() const { + return kind_case() == kBitcast ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionBitcast*>(_impl_.kind_.bitcast_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionBitcast&>(::tint::core::ir::binary::pb::_InstructionBitcast_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionBitcast& Instruction::bitcast() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.bitcast) + return _internal_bitcast(); +} +inline ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_bitcast() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.bitcast) + if (kind_case() == kBitcast) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBitcast*>(_impl_.kind_.bitcast_); + _impl_.kind_.bitcast_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_bitcast( + ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_bitcast(); + _impl_.kind_.bitcast_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.bitcast) +} +inline ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NONNULL Instruction::_internal_mutable_bitcast() { + if (kind_case() != kBitcast) { + clear_kind(); + set_has_bitcast(); + _impl_.kind_.bitcast_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionBitcast>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionBitcast*>(_impl_.kind_.bitcast_); +} +inline ::tint::core::ir::binary::pb::InstructionBitcast* PROTOBUF_NONNULL Instruction::mutable_bitcast() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionBitcast* _msg = _internal_mutable_bitcast(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.bitcast) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionConstruct construct = 10; +inline bool Instruction::has_construct() const { + return kind_case() == kConstruct; +} +inline bool Instruction::_internal_has_construct() const { + return kind_case() == kConstruct; +} +inline void Instruction::set_has_construct() { + _impl_._oneof_case_[0] = kConstruct; +} +inline void Instruction::clear_construct() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kConstruct) { + if (GetArena() == nullptr) { + delete _impl_.kind_.construct_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.construct_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE Instruction::release_construct() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.construct) + if (kind_case() == kConstruct) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionConstruct*>(_impl_.kind_.construct_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.construct_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionConstruct& Instruction::_internal_construct() const { + return kind_case() == kConstruct ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionConstruct*>(_impl_.kind_.construct_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionConstruct&>(::tint::core::ir::binary::pb::_InstructionConstruct_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionConstruct& Instruction::construct() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.construct) + return _internal_construct(); +} +inline ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_construct() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.construct) + if (kind_case() == kConstruct) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionConstruct*>(_impl_.kind_.construct_); + _impl_.kind_.construct_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_construct( + ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_construct(); + _impl_.kind_.construct_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.construct) +} +inline ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NONNULL Instruction::_internal_mutable_construct() { + if (kind_case() != kConstruct) { + clear_kind(); + set_has_construct(); + _impl_.kind_.construct_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionConstruct>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionConstruct*>(_impl_.kind_.construct_); +} +inline ::tint::core::ir::binary::pb::InstructionConstruct* PROTOBUF_NONNULL Instruction::mutable_construct() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionConstruct* _msg = _internal_mutable_construct(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.construct) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionConvert convert = 11; +inline bool Instruction::has_convert() const { + return kind_case() == kConvert; +} +inline bool Instruction::_internal_has_convert() const { + return kind_case() == kConvert; +} +inline void Instruction::set_has_convert() { + _impl_._oneof_case_[0] = kConvert; +} +inline void Instruction::clear_convert() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kConvert) { + if (GetArena() == nullptr) { + delete _impl_.kind_.convert_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.convert_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE Instruction::release_convert() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.convert) + if (kind_case() == kConvert) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionConvert*>(_impl_.kind_.convert_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.convert_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionConvert& Instruction::_internal_convert() const { + return kind_case() == kConvert ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionConvert*>(_impl_.kind_.convert_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionConvert&>(::tint::core::ir::binary::pb::_InstructionConvert_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionConvert& Instruction::convert() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.convert) + return _internal_convert(); +} +inline ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_convert() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.convert) + if (kind_case() == kConvert) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionConvert*>(_impl_.kind_.convert_); + _impl_.kind_.convert_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_convert( + ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_convert(); + _impl_.kind_.convert_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.convert) +} +inline ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NONNULL Instruction::_internal_mutable_convert() { + if (kind_case() != kConvert) { + clear_kind(); + set_has_convert(); + _impl_.kind_.convert_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionConvert>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionConvert*>(_impl_.kind_.convert_); +} +inline ::tint::core::ir::binary::pb::InstructionConvert* PROTOBUF_NONNULL Instruction::mutable_convert() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionConvert* _msg = _internal_mutable_convert(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.convert) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionAccess access = 12; +inline bool Instruction::has_access() const { + return kind_case() == kAccess; +} +inline bool Instruction::_internal_has_access() const { + return kind_case() == kAccess; +} +inline void Instruction::set_has_access() { + _impl_._oneof_case_[0] = kAccess; +} +inline void Instruction::clear_access() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kAccess) { + if (GetArena() == nullptr) { + delete _impl_.kind_.access_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.access_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE Instruction::release_access() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.access) + if (kind_case() == kAccess) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionAccess*>(_impl_.kind_.access_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.access_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionAccess& Instruction::_internal_access() const { + return kind_case() == kAccess ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionAccess*>(_impl_.kind_.access_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionAccess&>(::tint::core::ir::binary::pb::_InstructionAccess_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionAccess& Instruction::access() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.access) + return _internal_access(); +} +inline ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_access() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.access) + if (kind_case() == kAccess) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionAccess*>(_impl_.kind_.access_); + _impl_.kind_.access_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_access( + ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_access(); + _impl_.kind_.access_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.access) +} +inline ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NONNULL Instruction::_internal_mutable_access() { + if (kind_case() != kAccess) { + clear_kind(); + set_has_access(); + _impl_.kind_.access_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionAccess>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionAccess*>(_impl_.kind_.access_); +} +inline ::tint::core::ir::binary::pb::InstructionAccess* PROTOBUF_NONNULL Instruction::mutable_access() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionAccess* _msg = _internal_mutable_access(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.access) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionUserCall user_call = 13; +inline bool Instruction::has_user_call() const { + return kind_case() == kUserCall; +} +inline bool Instruction::_internal_has_user_call() const { + return kind_case() == kUserCall; +} +inline void Instruction::set_has_user_call() { + _impl_._oneof_case_[0] = kUserCall; +} +inline void Instruction::clear_user_call() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kUserCall) { + if (GetArena() == nullptr) { + delete _impl_.kind_.user_call_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.user_call_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE Instruction::release_user_call() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.user_call) + if (kind_case() == kUserCall) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionUserCall*>(_impl_.kind_.user_call_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.user_call_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionUserCall& Instruction::_internal_user_call() const { + return kind_case() == kUserCall ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionUserCall*>(_impl_.kind_.user_call_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionUserCall&>(::tint::core::ir::binary::pb::_InstructionUserCall_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionUserCall& Instruction::user_call() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.user_call) + return _internal_user_call(); +} +inline ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_user_call() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.user_call) + if (kind_case() == kUserCall) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionUserCall*>(_impl_.kind_.user_call_); + _impl_.kind_.user_call_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_user_call( + ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_user_call(); + _impl_.kind_.user_call_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.user_call) +} +inline ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NONNULL Instruction::_internal_mutable_user_call() { + if (kind_case() != kUserCall) { + clear_kind(); + set_has_user_call(); + _impl_.kind_.user_call_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionUserCall>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionUserCall*>(_impl_.kind_.user_call_); +} +inline ::tint::core::ir::binary::pb::InstructionUserCall* PROTOBUF_NONNULL Instruction::mutable_user_call() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionUserCall* _msg = _internal_mutable_user_call(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.user_call) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionBuiltinCall builtin_call = 14; +inline bool Instruction::has_builtin_call() const { + return kind_case() == kBuiltinCall; +} +inline bool Instruction::_internal_has_builtin_call() const { + return kind_case() == kBuiltinCall; +} +inline void Instruction::set_has_builtin_call() { + _impl_._oneof_case_[0] = kBuiltinCall; +} +inline void Instruction::clear_builtin_call() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBuiltinCall) { + if (GetArena() == nullptr) { + delete _impl_.kind_.builtin_call_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.builtin_call_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE Instruction::release_builtin_call() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.builtin_call) + if (kind_case() == kBuiltinCall) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBuiltinCall*>(_impl_.kind_.builtin_call_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.builtin_call_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionBuiltinCall& Instruction::_internal_builtin_call() const { + return kind_case() == kBuiltinCall ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionBuiltinCall*>(_impl_.kind_.builtin_call_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionBuiltinCall&>(::tint::core::ir::binary::pb::_InstructionBuiltinCall_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionBuiltinCall& Instruction::builtin_call() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.builtin_call) + return _internal_builtin_call(); +} +inline ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_builtin_call() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.builtin_call) + if (kind_case() == kBuiltinCall) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBuiltinCall*>(_impl_.kind_.builtin_call_); + _impl_.kind_.builtin_call_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_builtin_call( + ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_builtin_call(); + _impl_.kind_.builtin_call_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.builtin_call) +} +inline ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NONNULL Instruction::_internal_mutable_builtin_call() { + if (kind_case() != kBuiltinCall) { + clear_kind(); + set_has_builtin_call(); + _impl_.kind_.builtin_call_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionBuiltinCall>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionBuiltinCall*>(_impl_.kind_.builtin_call_); +} +inline ::tint::core::ir::binary::pb::InstructionBuiltinCall* PROTOBUF_NONNULL Instruction::mutable_builtin_call() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionBuiltinCall* _msg = _internal_mutable_builtin_call(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.builtin_call) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionLoad load = 15; +inline bool Instruction::has_load() const { + return kind_case() == kLoad; +} +inline bool Instruction::_internal_has_load() const { + return kind_case() == kLoad; +} +inline void Instruction::set_has_load() { + _impl_._oneof_case_[0] = kLoad; +} +inline void Instruction::clear_load() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kLoad) { + if (GetArena() == nullptr) { + delete _impl_.kind_.load_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.load_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE Instruction::release_load() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.load) + if (kind_case() == kLoad) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoad*>(_impl_.kind_.load_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.load_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionLoad& Instruction::_internal_load() const { + return kind_case() == kLoad ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoad*>(_impl_.kind_.load_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoad&>(::tint::core::ir::binary::pb::_InstructionLoad_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionLoad& Instruction::load() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.load) + return _internal_load(); +} +inline ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_load() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.load) + if (kind_case() == kLoad) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoad*>(_impl_.kind_.load_); + _impl_.kind_.load_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_load( + ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_load(); + _impl_.kind_.load_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.load) +} +inline ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NONNULL Instruction::_internal_mutable_load() { + if (kind_case() != kLoad) { + clear_kind(); + set_has_load(); + _impl_.kind_.load_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionLoad>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoad*>(_impl_.kind_.load_); +} +inline ::tint::core::ir::binary::pb::InstructionLoad* PROTOBUF_NONNULL Instruction::mutable_load() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionLoad* _msg = _internal_mutable_load(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.load) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionStore store = 16; +inline bool Instruction::has_store() const { + return kind_case() == kStore; +} +inline bool Instruction::_internal_has_store() const { + return kind_case() == kStore; +} +inline void Instruction::set_has_store() { + _impl_._oneof_case_[0] = kStore; +} +inline void Instruction::clear_store() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kStore) { + if (GetArena() == nullptr) { + delete _impl_.kind_.store_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.store_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE Instruction::release_store() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.store) + if (kind_case() == kStore) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionStore*>(_impl_.kind_.store_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.store_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionStore& Instruction::_internal_store() const { + return kind_case() == kStore ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionStore*>(_impl_.kind_.store_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionStore&>(::tint::core::ir::binary::pb::_InstructionStore_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionStore& Instruction::store() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.store) + return _internal_store(); +} +inline ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_store() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.store) + if (kind_case() == kStore) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionStore*>(_impl_.kind_.store_); + _impl_.kind_.store_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_store( + ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_store(); + _impl_.kind_.store_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.store) +} +inline ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NONNULL Instruction::_internal_mutable_store() { + if (kind_case() != kStore) { + clear_kind(); + set_has_store(); + _impl_.kind_.store_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionStore>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionStore*>(_impl_.kind_.store_); +} +inline ::tint::core::ir::binary::pb::InstructionStore* PROTOBUF_NONNULL Instruction::mutable_store() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionStore* _msg = _internal_mutable_store(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.store) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionLoadVectorElement load_vector_element = 17; +inline bool Instruction::has_load_vector_element() const { + return kind_case() == kLoadVectorElement; +} +inline bool Instruction::_internal_has_load_vector_element() const { + return kind_case() == kLoadVectorElement; +} +inline void Instruction::set_has_load_vector_element() { + _impl_._oneof_case_[0] = kLoadVectorElement; +} +inline void Instruction::clear_load_vector_element() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kLoadVectorElement) { + if (GetArena() == nullptr) { + delete _impl_.kind_.load_vector_element_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.load_vector_element_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE Instruction::release_load_vector_element() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.load_vector_element) + if (kind_case() == kLoadVectorElement) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoadVectorElement*>(_impl_.kind_.load_vector_element_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.load_vector_element_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionLoadVectorElement& Instruction::_internal_load_vector_element() const { + return kind_case() == kLoadVectorElement ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoadVectorElement*>(_impl_.kind_.load_vector_element_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoadVectorElement&>(::tint::core::ir::binary::pb::_InstructionLoadVectorElement_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionLoadVectorElement& Instruction::load_vector_element() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.load_vector_element) + return _internal_load_vector_element(); +} +inline ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_load_vector_element() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.load_vector_element) + if (kind_case() == kLoadVectorElement) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoadVectorElement*>(_impl_.kind_.load_vector_element_); + _impl_.kind_.load_vector_element_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_load_vector_element( + ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_load_vector_element(); + _impl_.kind_.load_vector_element_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.load_vector_element) +} +inline ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NONNULL Instruction::_internal_mutable_load_vector_element() { + if (kind_case() != kLoadVectorElement) { + clear_kind(); + set_has_load_vector_element(); + _impl_.kind_.load_vector_element_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionLoadVectorElement>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoadVectorElement*>(_impl_.kind_.load_vector_element_); +} +inline ::tint::core::ir::binary::pb::InstructionLoadVectorElement* PROTOBUF_NONNULL Instruction::mutable_load_vector_element() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionLoadVectorElement* _msg = _internal_mutable_load_vector_element(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.load_vector_element) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionStoreVectorElement store_vector_element = 18; +inline bool Instruction::has_store_vector_element() const { + return kind_case() == kStoreVectorElement; +} +inline bool Instruction::_internal_has_store_vector_element() const { + return kind_case() == kStoreVectorElement; +} +inline void Instruction::set_has_store_vector_element() { + _impl_._oneof_case_[0] = kStoreVectorElement; +} +inline void Instruction::clear_store_vector_element() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kStoreVectorElement) { + if (GetArena() == nullptr) { + delete _impl_.kind_.store_vector_element_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.store_vector_element_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE Instruction::release_store_vector_element() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.store_vector_element) + if (kind_case() == kStoreVectorElement) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionStoreVectorElement*>(_impl_.kind_.store_vector_element_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.store_vector_element_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionStoreVectorElement& Instruction::_internal_store_vector_element() const { + return kind_case() == kStoreVectorElement ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionStoreVectorElement*>(_impl_.kind_.store_vector_element_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionStoreVectorElement&>(::tint::core::ir::binary::pb::_InstructionStoreVectorElement_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionStoreVectorElement& Instruction::store_vector_element() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.store_vector_element) + return _internal_store_vector_element(); +} +inline ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_store_vector_element() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.store_vector_element) + if (kind_case() == kStoreVectorElement) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionStoreVectorElement*>(_impl_.kind_.store_vector_element_); + _impl_.kind_.store_vector_element_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_store_vector_element( + ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_store_vector_element(); + _impl_.kind_.store_vector_element_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.store_vector_element) +} +inline ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NONNULL Instruction::_internal_mutable_store_vector_element() { + if (kind_case() != kStoreVectorElement) { + clear_kind(); + set_has_store_vector_element(); + _impl_.kind_.store_vector_element_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionStoreVectorElement>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionStoreVectorElement*>(_impl_.kind_.store_vector_element_); +} +inline ::tint::core::ir::binary::pb::InstructionStoreVectorElement* PROTOBUF_NONNULL Instruction::mutable_store_vector_element() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionStoreVectorElement* _msg = _internal_mutable_store_vector_element(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.store_vector_element) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionSwizzle swizzle = 19; +inline bool Instruction::has_swizzle() const { + return kind_case() == kSwizzle; +} +inline bool Instruction::_internal_has_swizzle() const { + return kind_case() == kSwizzle; +} +inline void Instruction::set_has_swizzle() { + _impl_._oneof_case_[0] = kSwizzle; +} +inline void Instruction::clear_swizzle() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSwizzle) { + if (GetArena() == nullptr) { + delete _impl_.kind_.swizzle_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.swizzle_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE Instruction::release_swizzle() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.swizzle) + if (kind_case() == kSwizzle) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwizzle*>(_impl_.kind_.swizzle_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.swizzle_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionSwizzle& Instruction::_internal_swizzle() const { + return kind_case() == kSwizzle ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwizzle*>(_impl_.kind_.swizzle_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwizzle&>(::tint::core::ir::binary::pb::_InstructionSwizzle_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionSwizzle& Instruction::swizzle() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.swizzle) + return _internal_swizzle(); +} +inline ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_swizzle() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.swizzle) + if (kind_case() == kSwizzle) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwizzle*>(_impl_.kind_.swizzle_); + _impl_.kind_.swizzle_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_swizzle( + ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_swizzle(); + _impl_.kind_.swizzle_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.swizzle) +} +inline ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NONNULL Instruction::_internal_mutable_swizzle() { + if (kind_case() != kSwizzle) { + clear_kind(); + set_has_swizzle(); + _impl_.kind_.swizzle_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionSwizzle>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwizzle*>(_impl_.kind_.swizzle_); +} +inline ::tint::core::ir::binary::pb::InstructionSwizzle* PROTOBUF_NONNULL Instruction::mutable_swizzle() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionSwizzle* _msg = _internal_mutable_swizzle(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.swizzle) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionIf if = 20; +inline bool Instruction::has_if_() const { + return kind_case() == kIf; +} +inline bool Instruction::_internal_has_if_() const { + return kind_case() == kIf; +} +inline void Instruction::set_has_if_() { + _impl_._oneof_case_[0] = kIf; +} +inline void Instruction::clear_if_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kIf) { + if (GetArena() == nullptr) { + delete _impl_.kind_.if__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.if__); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE Instruction::release_if_() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.if) + if (kind_case() == kIf) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionIf*>(_impl_.kind_.if__); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.if__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionIf& Instruction::_internal_if_() const { + return kind_case() == kIf ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionIf*>(_impl_.kind_.if__) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionIf&>(::tint::core::ir::binary::pb::_InstructionIf_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionIf& Instruction::if_() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.if) + return _internal_if_(); +} +inline ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_if_() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.if) + if (kind_case() == kIf) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionIf*>(_impl_.kind_.if__); + _impl_.kind_.if__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_if_( + ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_if_(); + _impl_.kind_.if__ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.if) +} +inline ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NONNULL Instruction::_internal_mutable_if_() { + if (kind_case() != kIf) { + clear_kind(); + set_has_if_(); + _impl_.kind_.if__ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionIf>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionIf*>(_impl_.kind_.if__); +} +inline ::tint::core::ir::binary::pb::InstructionIf* PROTOBUF_NONNULL Instruction::mutable_if_() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionIf* _msg = _internal_mutable_if_(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.if) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionSwitch switch = 21; +inline bool Instruction::has_switch_() const { + return kind_case() == kSwitch; +} +inline bool Instruction::_internal_has_switch_() const { + return kind_case() == kSwitch; +} +inline void Instruction::set_has_switch_() { + _impl_._oneof_case_[0] = kSwitch; +} +inline void Instruction::clear_switch_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kSwitch) { + if (GetArena() == nullptr) { + delete _impl_.kind_.switch__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.switch__); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE Instruction::release_switch_() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.switch) + if (kind_case() == kSwitch) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwitch*>(_impl_.kind_.switch__); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.switch__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionSwitch& Instruction::_internal_switch_() const { + return kind_case() == kSwitch ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwitch*>(_impl_.kind_.switch__) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwitch&>(::tint::core::ir::binary::pb::_InstructionSwitch_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionSwitch& Instruction::switch_() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.switch) + return _internal_switch_(); +} +inline ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_switch_() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.switch) + if (kind_case() == kSwitch) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwitch*>(_impl_.kind_.switch__); + _impl_.kind_.switch__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_switch_( + ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_switch_(); + _impl_.kind_.switch__ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.switch) +} +inline ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NONNULL Instruction::_internal_mutable_switch_() { + if (kind_case() != kSwitch) { + clear_kind(); + set_has_switch_(); + _impl_.kind_.switch__ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionSwitch>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionSwitch*>(_impl_.kind_.switch__); +} +inline ::tint::core::ir::binary::pb::InstructionSwitch* PROTOBUF_NONNULL Instruction::mutable_switch_() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionSwitch* _msg = _internal_mutable_switch_(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.switch) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionLoop loop = 22; +inline bool Instruction::has_loop() const { + return kind_case() == kLoop; +} +inline bool Instruction::_internal_has_loop() const { + return kind_case() == kLoop; +} +inline void Instruction::set_has_loop() { + _impl_._oneof_case_[0] = kLoop; +} +inline void Instruction::clear_loop() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kLoop) { + if (GetArena() == nullptr) { + delete _impl_.kind_.loop_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.loop_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE Instruction::release_loop() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.loop) + if (kind_case() == kLoop) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoop*>(_impl_.kind_.loop_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.loop_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionLoop& Instruction::_internal_loop() const { + return kind_case() == kLoop ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoop*>(_impl_.kind_.loop_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoop&>(::tint::core::ir::binary::pb::_InstructionLoop_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionLoop& Instruction::loop() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.loop) + return _internal_loop(); +} +inline ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_loop() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.loop) + if (kind_case() == kLoop) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoop*>(_impl_.kind_.loop_); + _impl_.kind_.loop_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_loop( + ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_loop(); + _impl_.kind_.loop_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.loop) +} +inline ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NONNULL Instruction::_internal_mutable_loop() { + if (kind_case() != kLoop) { + clear_kind(); + set_has_loop(); + _impl_.kind_.loop_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionLoop>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionLoop*>(_impl_.kind_.loop_); +} +inline ::tint::core::ir::binary::pb::InstructionLoop* PROTOBUF_NONNULL Instruction::mutable_loop() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionLoop* _msg = _internal_mutable_loop(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.loop) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionExitIf exit_if = 23; +inline bool Instruction::has_exit_if() const { + return kind_case() == kExitIf; +} +inline bool Instruction::_internal_has_exit_if() const { + return kind_case() == kExitIf; +} +inline void Instruction::set_has_exit_if() { + _impl_._oneof_case_[0] = kExitIf; +} +inline void Instruction::clear_exit_if() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kExitIf) { + if (GetArena() == nullptr) { + delete _impl_.kind_.exit_if_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.exit_if_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE Instruction::release_exit_if() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.exit_if) + if (kind_case() == kExitIf) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitIf*>(_impl_.kind_.exit_if_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.exit_if_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionExitIf& Instruction::_internal_exit_if() const { + return kind_case() == kExitIf ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitIf*>(_impl_.kind_.exit_if_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitIf&>(::tint::core::ir::binary::pb::_InstructionExitIf_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionExitIf& Instruction::exit_if() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.exit_if) + return _internal_exit_if(); +} +inline ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_exit_if() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.exit_if) + if (kind_case() == kExitIf) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitIf*>(_impl_.kind_.exit_if_); + _impl_.kind_.exit_if_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_exit_if( + ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_exit_if(); + _impl_.kind_.exit_if_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.exit_if) +} +inline ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NONNULL Instruction::_internal_mutable_exit_if() { + if (kind_case() != kExitIf) { + clear_kind(); + set_has_exit_if(); + _impl_.kind_.exit_if_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionExitIf>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitIf*>(_impl_.kind_.exit_if_); +} +inline ::tint::core::ir::binary::pb::InstructionExitIf* PROTOBUF_NONNULL Instruction::mutable_exit_if() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionExitIf* _msg = _internal_mutable_exit_if(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.exit_if) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionExitSwitch exit_switch = 24; +inline bool Instruction::has_exit_switch() const { + return kind_case() == kExitSwitch; +} +inline bool Instruction::_internal_has_exit_switch() const { + return kind_case() == kExitSwitch; +} +inline void Instruction::set_has_exit_switch() { + _impl_._oneof_case_[0] = kExitSwitch; +} +inline void Instruction::clear_exit_switch() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kExitSwitch) { + if (GetArena() == nullptr) { + delete _impl_.kind_.exit_switch_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.exit_switch_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE Instruction::release_exit_switch() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.exit_switch) + if (kind_case() == kExitSwitch) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitSwitch*>(_impl_.kind_.exit_switch_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.exit_switch_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionExitSwitch& Instruction::_internal_exit_switch() const { + return kind_case() == kExitSwitch ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitSwitch*>(_impl_.kind_.exit_switch_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitSwitch&>(::tint::core::ir::binary::pb::_InstructionExitSwitch_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionExitSwitch& Instruction::exit_switch() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.exit_switch) + return _internal_exit_switch(); +} +inline ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_exit_switch() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.exit_switch) + if (kind_case() == kExitSwitch) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitSwitch*>(_impl_.kind_.exit_switch_); + _impl_.kind_.exit_switch_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_exit_switch( + ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_exit_switch(); + _impl_.kind_.exit_switch_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.exit_switch) +} +inline ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NONNULL Instruction::_internal_mutable_exit_switch() { + if (kind_case() != kExitSwitch) { + clear_kind(); + set_has_exit_switch(); + _impl_.kind_.exit_switch_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionExitSwitch>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitSwitch*>(_impl_.kind_.exit_switch_); +} +inline ::tint::core::ir::binary::pb::InstructionExitSwitch* PROTOBUF_NONNULL Instruction::mutable_exit_switch() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionExitSwitch* _msg = _internal_mutable_exit_switch(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.exit_switch) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionExitLoop exit_loop = 25; +inline bool Instruction::has_exit_loop() const { + return kind_case() == kExitLoop; +} +inline bool Instruction::_internal_has_exit_loop() const { + return kind_case() == kExitLoop; +} +inline void Instruction::set_has_exit_loop() { + _impl_._oneof_case_[0] = kExitLoop; +} +inline void Instruction::clear_exit_loop() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kExitLoop) { + if (GetArena() == nullptr) { + delete _impl_.kind_.exit_loop_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.exit_loop_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE Instruction::release_exit_loop() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.exit_loop) + if (kind_case() == kExitLoop) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitLoop*>(_impl_.kind_.exit_loop_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.exit_loop_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionExitLoop& Instruction::_internal_exit_loop() const { + return kind_case() == kExitLoop ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitLoop*>(_impl_.kind_.exit_loop_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitLoop&>(::tint::core::ir::binary::pb::_InstructionExitLoop_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionExitLoop& Instruction::exit_loop() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.exit_loop) + return _internal_exit_loop(); +} +inline ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_exit_loop() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.exit_loop) + if (kind_case() == kExitLoop) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitLoop*>(_impl_.kind_.exit_loop_); + _impl_.kind_.exit_loop_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_exit_loop( + ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_exit_loop(); + _impl_.kind_.exit_loop_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.exit_loop) +} +inline ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NONNULL Instruction::_internal_mutable_exit_loop() { + if (kind_case() != kExitLoop) { + clear_kind(); + set_has_exit_loop(); + _impl_.kind_.exit_loop_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionExitLoop>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionExitLoop*>(_impl_.kind_.exit_loop_); +} +inline ::tint::core::ir::binary::pb::InstructionExitLoop* PROTOBUF_NONNULL Instruction::mutable_exit_loop() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionExitLoop* _msg = _internal_mutable_exit_loop(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.exit_loop) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionNextIteration next_iteration = 26; +inline bool Instruction::has_next_iteration() const { + return kind_case() == kNextIteration; +} +inline bool Instruction::_internal_has_next_iteration() const { + return kind_case() == kNextIteration; +} +inline void Instruction::set_has_next_iteration() { + _impl_._oneof_case_[0] = kNextIteration; +} +inline void Instruction::clear_next_iteration() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kNextIteration) { + if (GetArena() == nullptr) { + delete _impl_.kind_.next_iteration_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.next_iteration_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE Instruction::release_next_iteration() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.next_iteration) + if (kind_case() == kNextIteration) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionNextIteration*>(_impl_.kind_.next_iteration_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.next_iteration_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionNextIteration& Instruction::_internal_next_iteration() const { + return kind_case() == kNextIteration ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionNextIteration*>(_impl_.kind_.next_iteration_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionNextIteration&>(::tint::core::ir::binary::pb::_InstructionNextIteration_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionNextIteration& Instruction::next_iteration() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.next_iteration) + return _internal_next_iteration(); +} +inline ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_next_iteration() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.next_iteration) + if (kind_case() == kNextIteration) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionNextIteration*>(_impl_.kind_.next_iteration_); + _impl_.kind_.next_iteration_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_next_iteration( + ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_next_iteration(); + _impl_.kind_.next_iteration_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.next_iteration) +} +inline ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NONNULL Instruction::_internal_mutable_next_iteration() { + if (kind_case() != kNextIteration) { + clear_kind(); + set_has_next_iteration(); + _impl_.kind_.next_iteration_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionNextIteration>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionNextIteration*>(_impl_.kind_.next_iteration_); +} +inline ::tint::core::ir::binary::pb::InstructionNextIteration* PROTOBUF_NONNULL Instruction::mutable_next_iteration() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionNextIteration* _msg = _internal_mutable_next_iteration(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.next_iteration) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionContinue continue = 27; +inline bool Instruction::has_continue_() const { + return kind_case() == kContinue; +} +inline bool Instruction::_internal_has_continue_() const { + return kind_case() == kContinue; +} +inline void Instruction::set_has_continue_() { + _impl_._oneof_case_[0] = kContinue; +} +inline void Instruction::clear_continue_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kContinue) { + if (GetArena() == nullptr) { + delete _impl_.kind_.continue__; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.continue__); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE Instruction::release_continue_() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.continue) + if (kind_case() == kContinue) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionContinue*>(_impl_.kind_.continue__); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.continue__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionContinue& Instruction::_internal_continue_() const { + return kind_case() == kContinue ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionContinue*>(_impl_.kind_.continue__) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionContinue&>(::tint::core::ir::binary::pb::_InstructionContinue_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionContinue& Instruction::continue_() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.continue) + return _internal_continue_(); +} +inline ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_continue_() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.continue) + if (kind_case() == kContinue) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionContinue*>(_impl_.kind_.continue__); + _impl_.kind_.continue__ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_continue_( + ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_continue_(); + _impl_.kind_.continue__ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.continue) +} +inline ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NONNULL Instruction::_internal_mutable_continue_() { + if (kind_case() != kContinue) { + clear_kind(); + set_has_continue_(); + _impl_.kind_.continue__ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionContinue>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionContinue*>(_impl_.kind_.continue__); +} +inline ::tint::core::ir::binary::pb::InstructionContinue* PROTOBUF_NONNULL Instruction::mutable_continue_() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionContinue* _msg = _internal_mutable_continue_(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.continue) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionBreakIf break_if = 28; +inline bool Instruction::has_break_if() const { + return kind_case() == kBreakIf; +} +inline bool Instruction::_internal_has_break_if() const { + return kind_case() == kBreakIf; +} +inline void Instruction::set_has_break_if() { + _impl_._oneof_case_[0] = kBreakIf; +} +inline void Instruction::clear_break_if() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kBreakIf) { + if (GetArena() == nullptr) { + delete _impl_.kind_.break_if_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.break_if_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE Instruction::release_break_if() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.break_if) + if (kind_case() == kBreakIf) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBreakIf*>(_impl_.kind_.break_if_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.break_if_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionBreakIf& Instruction::_internal_break_if() const { + return kind_case() == kBreakIf ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionBreakIf*>(_impl_.kind_.break_if_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionBreakIf&>(::tint::core::ir::binary::pb::_InstructionBreakIf_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionBreakIf& Instruction::break_if() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.break_if) + return _internal_break_if(); +} +inline ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_break_if() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.break_if) + if (kind_case() == kBreakIf) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionBreakIf*>(_impl_.kind_.break_if_); + _impl_.kind_.break_if_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_break_if( + ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_break_if(); + _impl_.kind_.break_if_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.break_if) +} +inline ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NONNULL Instruction::_internal_mutable_break_if() { + if (kind_case() != kBreakIf) { + clear_kind(); + set_has_break_if(); + _impl_.kind_.break_if_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionBreakIf>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionBreakIf*>(_impl_.kind_.break_if_); +} +inline ::tint::core::ir::binary::pb::InstructionBreakIf* PROTOBUF_NONNULL Instruction::mutable_break_if() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionBreakIf* _msg = _internal_mutable_break_if(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.break_if) + return _msg; +} + +// .tint.core.ir.binary.pb.InstructionUnreachable unreachable = 29; +inline bool Instruction::has_unreachable() const { + return kind_case() == kUnreachable; +} +inline bool Instruction::_internal_has_unreachable() const { + return kind_case() == kUnreachable; +} +inline void Instruction::set_has_unreachable() { + _impl_._oneof_case_[0] = kUnreachable; +} +inline void Instruction::clear_unreachable() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (kind_case() == kUnreachable) { + if (GetArena() == nullptr) { + delete _impl_.kind_.unreachable_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + ::google::protobuf::internal::MaybePoisonAfterClear(_impl_.kind_.unreachable_); + } + clear_has_kind(); + } +} +inline ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE Instruction::release_unreachable() { + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.Instruction.unreachable) + if (kind_case() == kUnreachable) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnreachable*>(_impl_.kind_.unreachable_); + if (GetArena() != nullptr) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.unreachable_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::tint::core::ir::binary::pb::InstructionUnreachable& Instruction::_internal_unreachable() const { + return kind_case() == kUnreachable ? *reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnreachable*>(_impl_.kind_.unreachable_) : reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnreachable&>(::tint::core::ir::binary::pb::_InstructionUnreachable_default_instance_); +} +inline const ::tint::core::ir::binary::pb::InstructionUnreachable& Instruction::unreachable() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Instruction.unreachable) + return _internal_unreachable(); +} +inline ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE Instruction::unsafe_arena_release_unreachable() { + // @@protoc_insertion_point(field_unsafe_arena_release:tint.core.ir.binary.pb.Instruction.unreachable) + if (kind_case() == kUnreachable) { + clear_has_kind(); + auto* temp = reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnreachable*>(_impl_.kind_.unreachable_); + _impl_.kind_.unreachable_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Instruction::unsafe_arena_set_allocated_unreachable( + ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NULLABLE value) { + // We rely on the oneof clear method to free the earlier contents + // of this oneof. We can directly use the pointer we're given to + // set the new value. + clear_kind(); + if (value) { + set_has_unreachable(); + _impl_.kind_.unreachable_ = reinterpret_cast<::google::protobuf::Message*>(value); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.Instruction.unreachable) +} +inline ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NONNULL Instruction::_internal_mutable_unreachable() { + if (kind_case() != kUnreachable) { + clear_kind(); + set_has_unreachable(); + _impl_.kind_.unreachable_ = reinterpret_cast<::google::protobuf::Message*>( + ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::InstructionUnreachable>(GetArena())); + } + return reinterpret_cast<::tint::core::ir::binary::pb::InstructionUnreachable*>(_impl_.kind_.unreachable_); +} +inline ::tint::core::ir::binary::pb::InstructionUnreachable* PROTOBUF_NONNULL Instruction::mutable_unreachable() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::tint::core::ir::binary::pb::InstructionUnreachable* _msg = _internal_mutable_unreachable(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.Instruction.unreachable) + return _msg; +} + +inline bool Instruction::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void Instruction::clear_has_kind() { + _impl_._oneof_case_[0] = KIND_NOT_SET; +} +inline Instruction::KindCase Instruction::kind_case() const { + return Instruction::KindCase(_impl_._oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// InstructionReturn + +// ------------------------------------------------------------------- + +// InstructionUnary + +// .tint.core.ir.binary.pb.UnaryOp op = 1; +inline void InstructionUnary::clear_op() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.op_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::UnaryOp InstructionUnary::op() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionUnary.op) + return _internal_op(); +} +inline void InstructionUnary::set_op(::tint::core::ir::binary::pb::UnaryOp value) { + _internal_set_op(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionUnary.op) +} +inline ::tint::core::ir::binary::pb::UnaryOp InstructionUnary::_internal_op() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::UnaryOp>(_impl_.op_); +} +inline void InstructionUnary::_internal_set_op(::tint::core::ir::binary::pb::UnaryOp value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.op_ = value; +} + +// ------------------------------------------------------------------- + +// InstructionBinary + +// .tint.core.ir.binary.pb.BinaryOp op = 1; +inline void InstructionBinary::clear_op() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.op_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::BinaryOp InstructionBinary::op() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionBinary.op) + return _internal_op(); +} +inline void InstructionBinary::set_op(::tint::core::ir::binary::pb::BinaryOp value) { + _internal_set_op(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionBinary.op) +} +inline ::tint::core::ir::binary::pb::BinaryOp InstructionBinary::_internal_op() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::BinaryOp>(_impl_.op_); +} +inline void InstructionBinary::_internal_set_op(::tint::core::ir::binary::pb::BinaryOp value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.op_ = value; +} + +// ------------------------------------------------------------------- + +// InstructionBitcast + +// ------------------------------------------------------------------- + +// InstructionConstruct + +// ------------------------------------------------------------------- + +// InstructionDiscard + +// ------------------------------------------------------------------- + +// InstructionLet + +// ------------------------------------------------------------------- + +// InstructionVar + +// optional .tint.core.ir.binary.pb.BindingPoint binding_point = 1; +inline bool InstructionVar::has_binding_point() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + PROTOBUF_ASSUME(!value || _impl_.binding_point_ != nullptr); + return value; +} +inline void InstructionVar::clear_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.binding_point_ != nullptr) _impl_.binding_point_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::tint::core::ir::binary::pb::BindingPoint& InstructionVar::_internal_binding_point() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::BindingPoint* p = _impl_.binding_point_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_BindingPoint_default_instance_); +} +inline const ::tint::core::ir::binary::pb::BindingPoint& InstructionVar::binding_point() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionVar.binding_point) + return _internal_binding_point(); +} +inline void InstructionVar::unsafe_arena_set_allocated_binding_point( + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.binding_point_); + } + _impl_.binding_point_ = reinterpret_cast<::tint::core::ir::binary::pb::BindingPoint*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.InstructionVar.binding_point) +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE InstructionVar::release_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000001U; + ::tint::core::ir::binary::pb::BindingPoint* released = _impl_.binding_point_; + _impl_.binding_point_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE InstructionVar::unsafe_arena_release_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.InstructionVar.binding_point) + + _impl_._has_bits_[0] &= ~0x00000001U; + ::tint::core::ir::binary::pb::BindingPoint* temp = _impl_.binding_point_; + _impl_.binding_point_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL InstructionVar::_internal_mutable_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.binding_point_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::BindingPoint>(GetArena()); + _impl_.binding_point_ = reinterpret_cast<::tint::core::ir::binary::pb::BindingPoint*>(p); + } + return _impl_.binding_point_; +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL InstructionVar::mutable_binding_point() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000001U; + ::tint::core::ir::binary::pb::BindingPoint* _msg = _internal_mutable_binding_point(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.InstructionVar.binding_point) + return _msg; +} +inline void InstructionVar::set_allocated_binding_point(::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.binding_point_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + + _impl_.binding_point_ = reinterpret_cast<::tint::core::ir::binary::pb::BindingPoint*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.InstructionVar.binding_point) +} + +// optional uint32 input_attachment_index = 2; +inline bool InstructionVar::has_input_attachment_index() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + return value; +} +inline void InstructionVar::clear_input_attachment_index() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.input_attachment_index_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t InstructionVar::input_attachment_index() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionVar.input_attachment_index) + return _internal_input_attachment_index(); +} +inline void InstructionVar::set_input_attachment_index(::uint32_t value) { + _internal_set_input_attachment_index(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionVar.input_attachment_index) +} +inline ::uint32_t InstructionVar::_internal_input_attachment_index() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.input_attachment_index_; +} +inline void InstructionVar::_internal_set_input_attachment_index(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.input_attachment_index_ = value; +} + +// ------------------------------------------------------------------- + +// InstructionConvert + +// ------------------------------------------------------------------- + +// InstructionAccess + +// ------------------------------------------------------------------- + +// InstructionUserCall + +// ------------------------------------------------------------------- + +// InstructionBuiltinCall + +// .tint.core.ir.binary.pb.BuiltinFn builtin = 1; +inline void InstructionBuiltinCall::clear_builtin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.builtin_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::BuiltinFn InstructionBuiltinCall::builtin() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionBuiltinCall.builtin) + return _internal_builtin(); +} +inline void InstructionBuiltinCall::set_builtin(::tint::core::ir::binary::pb::BuiltinFn value) { + _internal_set_builtin(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionBuiltinCall.builtin) +} +inline ::tint::core::ir::binary::pb::BuiltinFn InstructionBuiltinCall::_internal_builtin() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::BuiltinFn>(_impl_.builtin_); +} +inline void InstructionBuiltinCall::_internal_set_builtin(::tint::core::ir::binary::pb::BuiltinFn value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.builtin_ = value; +} + +// repeated uint32 explicit_template_params = 2; +inline int InstructionBuiltinCall::_internal_explicit_template_params_size() const { + return _internal_explicit_template_params().size(); +} +inline int InstructionBuiltinCall::explicit_template_params_size() const { + return _internal_explicit_template_params_size(); +} +inline void InstructionBuiltinCall::clear_explicit_template_params() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.explicit_template_params_.Clear(); +} +inline ::uint32_t InstructionBuiltinCall::explicit_template_params(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionBuiltinCall.explicit_template_params) + return _internal_explicit_template_params().Get(index); +} +inline void InstructionBuiltinCall::set_explicit_template_params(int index, ::uint32_t value) { + _internal_mutable_explicit_template_params()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionBuiltinCall.explicit_template_params) +} +inline void InstructionBuiltinCall::add_explicit_template_params(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_explicit_template_params()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.InstructionBuiltinCall.explicit_template_params) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& InstructionBuiltinCall::explicit_template_params() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.InstructionBuiltinCall.explicit_template_params) + return _internal_explicit_template_params(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL InstructionBuiltinCall::mutable_explicit_template_params() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.InstructionBuiltinCall.explicit_template_params) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_explicit_template_params(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +InstructionBuiltinCall::_internal_explicit_template_params() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.explicit_template_params_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +InstructionBuiltinCall::_internal_mutable_explicit_template_params() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.explicit_template_params_; +} + +// ------------------------------------------------------------------- + +// InstructionLoad + +// ------------------------------------------------------------------- + +// InstructionStore + +// ------------------------------------------------------------------- + +// InstructionLoadVectorElement + +// ------------------------------------------------------------------- + +// InstructionStoreVectorElement + +// ------------------------------------------------------------------- + +// InstructionSwizzle + +// repeated uint32 indices = 1; +inline int InstructionSwizzle::_internal_indices_size() const { + return _internal_indices().size(); +} +inline int InstructionSwizzle::indices_size() const { + return _internal_indices_size(); +} +inline void InstructionSwizzle::clear_indices() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.indices_.Clear(); +} +inline ::uint32_t InstructionSwizzle::indices(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionSwizzle.indices) + return _internal_indices().Get(index); +} +inline void InstructionSwizzle::set_indices(int index, ::uint32_t value) { + _internal_mutable_indices()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionSwizzle.indices) +} +inline void InstructionSwizzle::add_indices(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_indices()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.InstructionSwizzle.indices) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& InstructionSwizzle::indices() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.InstructionSwizzle.indices) + return _internal_indices(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL InstructionSwizzle::mutable_indices() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.InstructionSwizzle.indices) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_indices(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +InstructionSwizzle::_internal_indices() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.indices_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +InstructionSwizzle::_internal_mutable_indices() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.indices_; +} + +// ------------------------------------------------------------------- + +// InstructionIf + +// optional uint32 true = 1; +inline bool InstructionIf::has_true_() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + return value; +} +inline void InstructionIf::clear_true_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.true__ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t InstructionIf::true_() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionIf.true) + return _internal_true_(); +} +inline void InstructionIf::set_true_(::uint32_t value) { + _internal_set_true_(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionIf.true) +} +inline ::uint32_t InstructionIf::_internal_true_() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.true__; +} +inline void InstructionIf::_internal_set_true_(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.true__ = value; +} + +// optional uint32 false = 2; +inline bool InstructionIf::has_false_() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + return value; +} +inline void InstructionIf::clear_false_() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.false__ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t InstructionIf::false_() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionIf.false) + return _internal_false_(); +} +inline void InstructionIf::set_false_(::uint32_t value) { + _internal_set_false_(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionIf.false) +} +inline ::uint32_t InstructionIf::_internal_false_() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.false__; +} +inline void InstructionIf::_internal_set_false_(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.false__ = value; +} + +// ------------------------------------------------------------------- + +// InstructionSwitch + +// repeated .tint.core.ir.binary.pb.SwitchCase cases = 1; +inline int InstructionSwitch::_internal_cases_size() const { + return _internal_cases().size(); +} +inline int InstructionSwitch::cases_size() const { + return _internal_cases_size(); +} +inline void InstructionSwitch::clear_cases() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.cases_.Clear(); +} +inline ::tint::core::ir::binary::pb::SwitchCase* PROTOBUF_NONNULL InstructionSwitch::mutable_cases(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.InstructionSwitch.cases) + return _internal_mutable_cases()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>* PROTOBUF_NONNULL InstructionSwitch::mutable_cases() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.InstructionSwitch.cases) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_cases(); +} +inline const ::tint::core::ir::binary::pb::SwitchCase& InstructionSwitch::cases(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionSwitch.cases) + return _internal_cases().Get(index); +} +inline ::tint::core::ir::binary::pb::SwitchCase* PROTOBUF_NONNULL InstructionSwitch::add_cases() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::tint::core::ir::binary::pb::SwitchCase* _add = _internal_mutable_cases()->Add(); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.InstructionSwitch.cases) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>& InstructionSwitch::cases() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.InstructionSwitch.cases) + return _internal_cases(); +} +inline const ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>& +InstructionSwitch::_internal_cases() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.cases_; +} +inline ::google::protobuf::RepeatedPtrField<::tint::core::ir::binary::pb::SwitchCase>* PROTOBUF_NONNULL +InstructionSwitch::_internal_mutable_cases() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.cases_; +} + +// ------------------------------------------------------------------- + +// InstructionLoop + +// optional uint32 initializer = 1; +inline bool InstructionLoop::has_initializer() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + return value; +} +inline void InstructionLoop::clear_initializer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initializer_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t InstructionLoop::initializer() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionLoop.initializer) + return _internal_initializer(); +} +inline void InstructionLoop::set_initializer(::uint32_t value) { + _internal_set_initializer(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionLoop.initializer) +} +inline ::uint32_t InstructionLoop::_internal_initializer() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.initializer_; +} +inline void InstructionLoop::_internal_set_initializer(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initializer_ = value; +} + +// optional uint32 body = 2; +inline bool InstructionLoop::has_body() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + return value; +} +inline void InstructionLoop::clear_body() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.body_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t InstructionLoop::body() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionLoop.body) + return _internal_body(); +} +inline void InstructionLoop::set_body(::uint32_t value) { + _internal_set_body(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionLoop.body) +} +inline ::uint32_t InstructionLoop::_internal_body() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.body_; +} +inline void InstructionLoop::_internal_set_body(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.body_ = value; +} + +// optional uint32 continuing = 3; +inline bool InstructionLoop::has_continuing() const { + bool value = (_impl_._has_bits_[0] & 0x00000004U) != 0; + return value; +} +inline void InstructionLoop::clear_continuing() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.continuing_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t InstructionLoop::continuing() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionLoop.continuing) + return _internal_continuing(); +} +inline void InstructionLoop::set_continuing(::uint32_t value) { + _internal_set_continuing(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionLoop.continuing) +} +inline ::uint32_t InstructionLoop::_internal_continuing() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.continuing_; +} +inline void InstructionLoop::_internal_set_continuing(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.continuing_ = value; +} + +// ------------------------------------------------------------------- + +// InstructionExitIf + +// ------------------------------------------------------------------- + +// InstructionExitSwitch + +// ------------------------------------------------------------------- + +// InstructionExitLoop + +// ------------------------------------------------------------------- + +// SwitchCase + +// uint32 block = 1; +inline void SwitchCase::clear_block() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.block_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t SwitchCase::block() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.SwitchCase.block) + return _internal_block(); +} +inline void SwitchCase::set_block(::uint32_t value) { + _internal_set_block(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.SwitchCase.block) +} +inline ::uint32_t SwitchCase::_internal_block() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.block_; +} +inline void SwitchCase::_internal_set_block(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.block_ = value; +} + +// repeated uint32 selectors = 2; +inline int SwitchCase::_internal_selectors_size() const { + return _internal_selectors().size(); +} +inline int SwitchCase::selectors_size() const { + return _internal_selectors_size(); +} +inline void SwitchCase::clear_selectors() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.selectors_.Clear(); +} +inline ::uint32_t SwitchCase::selectors(int index) const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.SwitchCase.selectors) + return _internal_selectors().Get(index); +} +inline void SwitchCase::set_selectors(int index, ::uint32_t value) { + _internal_mutable_selectors()->Set(index, value); + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.SwitchCase.selectors) +} +inline void SwitchCase::add_selectors(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_selectors()->Add(value); + // @@protoc_insertion_point(field_add:tint.core.ir.binary.pb.SwitchCase.selectors) +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& SwitchCase::selectors() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:tint.core.ir.binary.pb.SwitchCase.selectors) + return _internal_selectors(); +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL SwitchCase::mutable_selectors() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:tint.core.ir.binary.pb.SwitchCase.selectors) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_selectors(); +} +inline const ::google::protobuf::RepeatedField<::uint32_t>& +SwitchCase::_internal_selectors() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.selectors_; +} +inline ::google::protobuf::RepeatedField<::uint32_t>* PROTOBUF_NONNULL +SwitchCase::_internal_mutable_selectors() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.selectors_; +} + +// bool is_default = 3; +inline void SwitchCase::clear_is_default() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.is_default_ = false; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline bool SwitchCase::is_default() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.SwitchCase.is_default) + return _internal_is_default(); +} +inline void SwitchCase::set_is_default(bool value) { + _internal_set_is_default(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.SwitchCase.is_default) +} +inline bool SwitchCase::_internal_is_default() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.is_default_; +} +inline void SwitchCase::_internal_set_is_default(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.is_default_ = value; +} + +// ------------------------------------------------------------------- + +// BindingPoint + +// uint32 group = 1; +inline void BindingPoint::clear_group() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.group_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t BindingPoint::group() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.BindingPoint.group) + return _internal_group(); +} +inline void BindingPoint::set_group(::uint32_t value) { + _internal_set_group(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.BindingPoint.group) +} +inline ::uint32_t BindingPoint::_internal_group() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.group_; +} +inline void BindingPoint::_internal_set_group(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.group_ = value; +} + +// uint32 binding = 2; +inline void BindingPoint::clear_binding() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.binding_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t BindingPoint::binding() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.BindingPoint.binding) + return _internal_binding(); +} +inline void BindingPoint::set_binding(::uint32_t value) { + _internal_set_binding(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.BindingPoint.binding) +} +inline ::uint32_t BindingPoint::_internal_binding() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.binding_; +} +inline void BindingPoint::_internal_set_binding(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.binding_ = value; +} + +// ------------------------------------------------------------------- + +// InstructionNextIteration + +// ------------------------------------------------------------------- + +// InstructionContinue + +// ------------------------------------------------------------------- + +// InstructionBreakIf + +// uint32 num_next_iter_values = 1; +inline void InstructionBreakIf::clear_num_next_iter_values() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.num_next_iter_values_ = 0u; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::uint32_t InstructionBreakIf::num_next_iter_values() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.InstructionBreakIf.num_next_iter_values) + return _internal_num_next_iter_values(); +} +inline void InstructionBreakIf::set_num_next_iter_values(::uint32_t value) { + _internal_set_num_next_iter_values(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.InstructionBreakIf.num_next_iter_values) +} +inline ::uint32_t InstructionBreakIf::_internal_num_next_iter_values() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.num_next_iter_values_; +} +inline void InstructionBreakIf::_internal_set_num_next_iter_values(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.num_next_iter_values_ = value; +} + +// ------------------------------------------------------------------- + +// InstructionUnreachable + +// ------------------------------------------------------------------- + +// AttributesStructMember + +// optional uint32 location = 1; +inline bool AttributesStructMember::has_location() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + return value; +} +inline void AttributesStructMember::clear_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_ = 0u; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::uint32_t AttributesStructMember::location() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesStructMember.location) + return _internal_location(); +} +inline void AttributesStructMember::set_location(::uint32_t value) { + _internal_set_location(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesStructMember.location) +} +inline ::uint32_t AttributesStructMember::_internal_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.location_; +} +inline void AttributesStructMember::_internal_set_location(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_ = value; +} + +// optional uint32 blend_src = 2; +inline bool AttributesStructMember::has_blend_src() const { + bool value = (_impl_._has_bits_[0] & 0x00000004U) != 0; + return value; +} +inline void AttributesStructMember::clear_blend_src() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.blend_src_ = 0u; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::uint32_t AttributesStructMember::blend_src() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesStructMember.blend_src) + return _internal_blend_src(); +} +inline void AttributesStructMember::set_blend_src(::uint32_t value) { + _internal_set_blend_src(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesStructMember.blend_src) +} +inline ::uint32_t AttributesStructMember::_internal_blend_src() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.blend_src_; +} +inline void AttributesStructMember::_internal_set_blend_src(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.blend_src_ = value; +} + +// optional uint32 color = 3; +inline bool AttributesStructMember::has_color() const { + bool value = (_impl_._has_bits_[0] & 0x00000008U) != 0; + return value; +} +inline void AttributesStructMember::clear_color() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.color_ = 0u; + _impl_._has_bits_[0] &= ~0x00000008U; +} +inline ::uint32_t AttributesStructMember::color() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesStructMember.color) + return _internal_color(); +} +inline void AttributesStructMember::set_color(::uint32_t value) { + _internal_set_color(value); + _impl_._has_bits_[0] |= 0x00000008U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesStructMember.color) +} +inline ::uint32_t AttributesStructMember::_internal_color() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.color_; +} +inline void AttributesStructMember::_internal_set_color(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.color_ = value; +} + +// optional .tint.core.ir.binary.pb.BuiltinValue builtin = 4; +inline bool AttributesStructMember::has_builtin() const { + bool value = (_impl_._has_bits_[0] & 0x00000010U) != 0; + return value; +} +inline void AttributesStructMember::clear_builtin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.builtin_ = 0; + _impl_._has_bits_[0] &= ~0x00000010U; +} +inline ::tint::core::ir::binary::pb::BuiltinValue AttributesStructMember::builtin() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesStructMember.builtin) + return _internal_builtin(); +} +inline void AttributesStructMember::set_builtin(::tint::core::ir::binary::pb::BuiltinValue value) { + _internal_set_builtin(value); + _impl_._has_bits_[0] |= 0x00000010U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesStructMember.builtin) +} +inline ::tint::core::ir::binary::pb::BuiltinValue AttributesStructMember::_internal_builtin() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::BuiltinValue>(_impl_.builtin_); +} +inline void AttributesStructMember::_internal_set_builtin(::tint::core::ir::binary::pb::BuiltinValue value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.builtin_ = value; +} + +// optional .tint.core.ir.binary.pb.Interpolation interpolation = 5; +inline bool AttributesStructMember::has_interpolation() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + PROTOBUF_ASSUME(!value || _impl_.interpolation_ != nullptr); + return value; +} +inline void AttributesStructMember::clear_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.interpolation_ != nullptr) _impl_.interpolation_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::tint::core::ir::binary::pb::Interpolation& AttributesStructMember::_internal_interpolation() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::Interpolation* p = _impl_.interpolation_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_Interpolation_default_instance_); +} +inline const ::tint::core::ir::binary::pb::Interpolation& AttributesStructMember::interpolation() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesStructMember.interpolation) + return _internal_interpolation(); +} +inline void AttributesStructMember::unsafe_arena_set_allocated_interpolation( + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.interpolation_); + } + _impl_.interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.AttributesStructMember.interpolation) +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE AttributesStructMember::release_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000001U; + ::tint::core::ir::binary::pb::Interpolation* released = _impl_.interpolation_; + _impl_.interpolation_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE AttributesStructMember::unsafe_arena_release_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.AttributesStructMember.interpolation) + + _impl_._has_bits_[0] &= ~0x00000001U; + ::tint::core::ir::binary::pb::Interpolation* temp = _impl_.interpolation_; + _impl_.interpolation_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL AttributesStructMember::_internal_mutable_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.interpolation_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::Interpolation>(GetArena()); + _impl_.interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(p); + } + return _impl_.interpolation_; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL AttributesStructMember::mutable_interpolation() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000001U; + ::tint::core::ir::binary::pb::Interpolation* _msg = _internal_mutable_interpolation(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.AttributesStructMember.interpolation) + return _msg; +} +inline void AttributesStructMember::set_allocated_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.interpolation_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + + _impl_.interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.AttributesStructMember.interpolation) +} + +// bool invariant = 6; +inline void AttributesStructMember::clear_invariant() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.invariant_ = false; + _impl_._has_bits_[0] &= ~0x00000020U; +} +inline bool AttributesStructMember::invariant() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesStructMember.invariant) + return _internal_invariant(); +} +inline void AttributesStructMember::set_invariant(bool value) { + _internal_set_invariant(value); + _impl_._has_bits_[0] |= 0x00000020U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesStructMember.invariant) +} +inline bool AttributesStructMember::_internal_invariant() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.invariant_; +} +inline void AttributesStructMember::_internal_set_invariant(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.invariant_ = value; +} + +// ------------------------------------------------------------------- + +// AttributesFunctionParameter + +// optional .tint.core.ir.binary.pb.BuiltinValue builtin = 1; +inline bool AttributesFunctionParameter::has_builtin() const { + bool value = (_impl_._has_bits_[0] & 0x00000004U) != 0; + return value; +} +inline void AttributesFunctionParameter::clear_builtin() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.builtin_ = 0; + _impl_._has_bits_[0] &= ~0x00000004U; +} +inline ::tint::core::ir::binary::pb::BuiltinValue AttributesFunctionParameter::builtin() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesFunctionParameter.builtin) + return _internal_builtin(); +} +inline void AttributesFunctionParameter::set_builtin(::tint::core::ir::binary::pb::BuiltinValue value) { + _internal_set_builtin(value); + _impl_._has_bits_[0] |= 0x00000004U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesFunctionParameter.builtin) +} +inline ::tint::core::ir::binary::pb::BuiltinValue AttributesFunctionParameter::_internal_builtin() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::BuiltinValue>(_impl_.builtin_); +} +inline void AttributesFunctionParameter::_internal_set_builtin(::tint::core::ir::binary::pb::BuiltinValue value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.builtin_ = value; +} + +// optional uint32 location = 2; +inline bool AttributesFunctionParameter::has_location() const { + bool value = (_impl_._has_bits_[0] & 0x00000008U) != 0; + return value; +} +inline void AttributesFunctionParameter::clear_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_ = 0u; + _impl_._has_bits_[0] &= ~0x00000008U; +} +inline ::uint32_t AttributesFunctionParameter::location() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesFunctionParameter.location) + return _internal_location(); +} +inline void AttributesFunctionParameter::set_location(::uint32_t value) { + _internal_set_location(value); + _impl_._has_bits_[0] |= 0x00000008U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesFunctionParameter.location) +} +inline ::uint32_t AttributesFunctionParameter::_internal_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.location_; +} +inline void AttributesFunctionParameter::_internal_set_location(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_ = value; +} + +// optional uint32 color = 3; +inline bool AttributesFunctionParameter::has_color() const { + bool value = (_impl_._has_bits_[0] & 0x00000010U) != 0; + return value; +} +inline void AttributesFunctionParameter::clear_color() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.color_ = 0u; + _impl_._has_bits_[0] &= ~0x00000010U; +} +inline ::uint32_t AttributesFunctionParameter::color() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesFunctionParameter.color) + return _internal_color(); +} +inline void AttributesFunctionParameter::set_color(::uint32_t value) { + _internal_set_color(value); + _impl_._has_bits_[0] |= 0x00000010U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesFunctionParameter.color) +} +inline ::uint32_t AttributesFunctionParameter::_internal_color() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.color_; +} +inline void AttributesFunctionParameter::_internal_set_color(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.color_ = value; +} + +// optional .tint.core.ir.binary.pb.Interpolation interpolation = 4; +inline bool AttributesFunctionParameter::has_interpolation() const { + bool value = (_impl_._has_bits_[0] & 0x00000001U) != 0; + PROTOBUF_ASSUME(!value || _impl_.interpolation_ != nullptr); + return value; +} +inline void AttributesFunctionParameter::clear_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.interpolation_ != nullptr) _impl_.interpolation_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline const ::tint::core::ir::binary::pb::Interpolation& AttributesFunctionParameter::_internal_interpolation() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::Interpolation* p = _impl_.interpolation_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_Interpolation_default_instance_); +} +inline const ::tint::core::ir::binary::pb::Interpolation& AttributesFunctionParameter::interpolation() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesFunctionParameter.interpolation) + return _internal_interpolation(); +} +inline void AttributesFunctionParameter::unsafe_arena_set_allocated_interpolation( + ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.interpolation_); + } + _impl_.interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.AttributesFunctionParameter.interpolation) +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE AttributesFunctionParameter::release_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000001U; + ::tint::core::ir::binary::pb::Interpolation* released = _impl_.interpolation_; + _impl_.interpolation_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE AttributesFunctionParameter::unsafe_arena_release_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.AttributesFunctionParameter.interpolation) + + _impl_._has_bits_[0] &= ~0x00000001U; + ::tint::core::ir::binary::pb::Interpolation* temp = _impl_.interpolation_; + _impl_.interpolation_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL AttributesFunctionParameter::_internal_mutable_interpolation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.interpolation_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::Interpolation>(GetArena()); + _impl_.interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(p); + } + return _impl_.interpolation_; +} +inline ::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NONNULL AttributesFunctionParameter::mutable_interpolation() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000001U; + ::tint::core::ir::binary::pb::Interpolation* _msg = _internal_mutable_interpolation(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.AttributesFunctionParameter.interpolation) + return _msg; +} +inline void AttributesFunctionParameter::set_allocated_interpolation(::tint::core::ir::binary::pb::Interpolation* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.interpolation_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001U; + } else { + _impl_._has_bits_[0] &= ~0x00000001U; + } + + _impl_.interpolation_ = reinterpret_cast<::tint::core::ir::binary::pb::Interpolation*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.AttributesFunctionParameter.interpolation) +} + +// optional .tint.core.ir.binary.pb.BindingPoint binding_point = 5; +inline bool AttributesFunctionParameter::has_binding_point() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + PROTOBUF_ASSUME(!value || _impl_.binding_point_ != nullptr); + return value; +} +inline void AttributesFunctionParameter::clear_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.binding_point_ != nullptr) _impl_.binding_point_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline const ::tint::core::ir::binary::pb::BindingPoint& AttributesFunctionParameter::_internal_binding_point() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::tint::core::ir::binary::pb::BindingPoint* p = _impl_.binding_point_; + return p != nullptr ? *p : reinterpret_cast(::tint::core::ir::binary::pb::_BindingPoint_default_instance_); +} +inline const ::tint::core::ir::binary::pb::BindingPoint& AttributesFunctionParameter::binding_point() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesFunctionParameter.binding_point) + return _internal_binding_point(); +} +inline void AttributesFunctionParameter::unsafe_arena_set_allocated_binding_point( + ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.binding_point_); + } + _impl_.binding_point_ = reinterpret_cast<::tint::core::ir::binary::pb::BindingPoint*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:tint.core.ir.binary.pb.AttributesFunctionParameter.binding_point) +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE AttributesFunctionParameter::release_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::BindingPoint* released = _impl_.binding_point_; + _impl_.binding_point_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE AttributesFunctionParameter::unsafe_arena_release_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:tint.core.ir.binary.pb.AttributesFunctionParameter.binding_point) + + _impl_._has_bits_[0] &= ~0x00000002U; + ::tint::core::ir::binary::pb::BindingPoint* temp = _impl_.binding_point_; + _impl_.binding_point_ = nullptr; + return temp; +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL AttributesFunctionParameter::_internal_mutable_binding_point() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.binding_point_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::tint::core::ir::binary::pb::BindingPoint>(GetArena()); + _impl_.binding_point_ = reinterpret_cast<::tint::core::ir::binary::pb::BindingPoint*>(p); + } + return _impl_.binding_point_; +} +inline ::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NONNULL AttributesFunctionParameter::mutable_binding_point() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000002U; + ::tint::core::ir::binary::pb::BindingPoint* _msg = _internal_mutable_binding_point(); + // @@protoc_insertion_point(field_mutable:tint.core.ir.binary.pb.AttributesFunctionParameter.binding_point) + return _msg; +} +inline void AttributesFunctionParameter::set_allocated_binding_point(::tint::core::ir::binary::pb::BindingPoint* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.binding_point_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002U; + } else { + _impl_._has_bits_[0] &= ~0x00000002U; + } + + _impl_.binding_point_ = reinterpret_cast<::tint::core::ir::binary::pb::BindingPoint*>(value); + // @@protoc_insertion_point(field_set_allocated:tint.core.ir.binary.pb.AttributesFunctionParameter.binding_point) +} + +// bool invariant = 6; +inline void AttributesFunctionParameter::clear_invariant() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.invariant_ = false; + _impl_._has_bits_[0] &= ~0x00000020U; +} +inline bool AttributesFunctionParameter::invariant() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.AttributesFunctionParameter.invariant) + return _internal_invariant(); +} +inline void AttributesFunctionParameter::set_invariant(bool value) { + _internal_set_invariant(value); + _impl_._has_bits_[0] |= 0x00000020U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.AttributesFunctionParameter.invariant) +} +inline bool AttributesFunctionParameter::_internal_invariant() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.invariant_; +} +inline void AttributesFunctionParameter::_internal_set_invariant(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.invariant_ = value; +} + +// ------------------------------------------------------------------- + +// Interpolation + +// .tint.core.ir.binary.pb.InterpolationType type = 1; +inline void Interpolation::clear_type() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = 0; + _impl_._has_bits_[0] &= ~0x00000001U; +} +inline ::tint::core::ir::binary::pb::InterpolationType Interpolation::type() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Interpolation.type) + return _internal_type(); +} +inline void Interpolation::set_type(::tint::core::ir::binary::pb::InterpolationType value) { + _internal_set_type(value); + _impl_._has_bits_[0] |= 0x00000001U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Interpolation.type) +} +inline ::tint::core::ir::binary::pb::InterpolationType Interpolation::_internal_type() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::InterpolationType>(_impl_.type_); +} +inline void Interpolation::_internal_set_type(::tint::core::ir::binary::pb::InterpolationType value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.type_ = value; +} + +// optional .tint.core.ir.binary.pb.InterpolationSampling sampling = 2; +inline bool Interpolation::has_sampling() const { + bool value = (_impl_._has_bits_[0] & 0x00000002U) != 0; + return value; +} +inline void Interpolation::clear_sampling() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sampling_ = 0; + _impl_._has_bits_[0] &= ~0x00000002U; +} +inline ::tint::core::ir::binary::pb::InterpolationSampling Interpolation::sampling() const { + // @@protoc_insertion_point(field_get:tint.core.ir.binary.pb.Interpolation.sampling) + return _internal_sampling(); +} +inline void Interpolation::set_sampling(::tint::core::ir::binary::pb::InterpolationSampling value) { + _internal_set_sampling(value); + _impl_._has_bits_[0] |= 0x00000002U; + // @@protoc_insertion_point(field_set:tint.core.ir.binary.pb.Interpolation.sampling) +} +inline ::tint::core::ir::binary::pb::InterpolationSampling Interpolation::_internal_sampling() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::tint::core::ir::binary::pb::InterpolationSampling>(_impl_.sampling_); +} +inline void Interpolation::_internal_set_sampling(::tint::core::ir::binary::pb::InterpolationSampling value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sampling_ = value; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace pb +} // namespace binary +} // namespace ir +} // namespace core +} // namespace tint + + +namespace google { +namespace protobuf { + +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::TypeBasic> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::TypeBasic>() { + return ::tint::core::ir::binary::pb::TypeBasic_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::TypeBuiltinStruct> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::TypeBuiltinStruct>() { + return ::tint::core::ir::binary::pb::TypeBuiltinStruct_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::PipelineStage> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::PipelineStage>() { + return ::tint::core::ir::binary::pb::PipelineStage_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::AddressSpace> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::AddressSpace>() { + return ::tint::core::ir::binary::pb::AddressSpace_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::AccessControl> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::AccessControl>() { + return ::tint::core::ir::binary::pb::AccessControl_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::UnaryOp> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::UnaryOp>() { + return ::tint::core::ir::binary::pb::UnaryOp_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::BinaryOp> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::BinaryOp>() { + return ::tint::core::ir::binary::pb::BinaryOp_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::TextureDimension> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::TextureDimension>() { + return ::tint::core::ir::binary::pb::TextureDimension_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::TexelFormat> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::TexelFormat>() { + return ::tint::core::ir::binary::pb::TexelFormat_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::SamplerKind> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::SamplerKind>() { + return ::tint::core::ir::binary::pb::SamplerKind_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::InterpolationType> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::InterpolationType>() { + return ::tint::core::ir::binary::pb::InterpolationType_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::InterpolationSampling> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::InterpolationSampling>() { + return ::tint::core::ir::binary::pb::InterpolationSampling_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::BuiltinValue> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::BuiltinValue>() { + return ::tint::core::ir::binary::pb::BuiltinValue_descriptor(); +} +template <> +struct is_proto_enum<::tint::core::ir::binary::pb::BuiltinFn> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::tint::core::ir::binary::pb::BuiltinFn>() { + return ::tint::core::ir::binary::pb::BuiltinFn_descriptor(); +} + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" + +#endif // src_2ftint_2futils_2fprotos_2fir_2fir_2eproto_2epb_2eh diff --git a/3rdparty/dawn/src/tint/utils/reflection.cc b/3rdparty/dawn/src/tint/utils/reflection.cc new file mode 100644 index 000000000..33cc6aff8 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/reflection.cc @@ -0,0 +1,65 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/reflection.h" + +#include "src/tint/utils/math/math.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::reflection::detail { + +Result CheckAllFieldsReflected(VectorRef fields, + std::string_view class_name, + size_t class_size, + size_t class_align, + bool class_is_castable) { + size_t calculated_offset = class_is_castable ? sizeof(CastableBase) : 0; + for (auto& field : fields) { + calculated_offset = RoundUp(field.align, calculated_offset); + if (calculated_offset < field.offset) { + StringStream msg; + msg << "TINT_REFLECT(" << class_name << ", ...) field mismatch at '" << field.name + << "'.\n" + "Expected field offset of " + << calculated_offset << " bytes, but field was at " << field.offset << " bytes"; + return Failure{msg.str()}; + } + calculated_offset += field.size; + } + calculated_offset = RoundUp(class_align, calculated_offset); + if (calculated_offset != class_size) { + StringStream msg; + msg << "TINT_REFLECT(" << class_name + << ", ...) missing fields at end of class\n" + "Expected class size of " + << calculated_offset << " bytes, but class is " << class_size << " bytes"; + return Failure{msg.str()}; + } + return Success; +} + +} // namespace tint::reflection::detail diff --git a/3rdparty/dawn/src/tint/utils/reflection.h b/3rdparty/dawn/src/tint/utils/reflection.h new file mode 100644 index 000000000..451641aec --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/reflection.h @@ -0,0 +1,237 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_REFLECTION_H_ +#define SRC_TINT_UTILS_REFLECTION_H_ + +#include +#include +#include +#include +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/macros/foreach.h" +#include "src/tint/utils/memory/aligned_storage.h" +#include "src/tint/utils/result.h" + +/// Forward declarations +namespace tint { +class CastableBase; +} + +namespace tint::reflection::detail { + +/// Helper for detecting whether the type T contains a nested Reflection class. +template +struct HasReflection : std::false_type {}; + +/// Specialization for types that have a nested Reflection class. +template +struct HasReflection> : std::true_type {}; + +/// Helper for inferring the base class size of T. +template +struct BaseClassSize { + /// Zero as T::Base does not exist + static constexpr size_t value = 0; +}; + +/// Specialization for types that contain a 'Base' type alias. +template +struct BaseClassSize> { + /// The size of T::Base, or zero if T::Base is not a base of T + static constexpr size_t value = + std::is_base_of_v ? sizeof(typename T::Base) : 0; +}; + +/// ReflectedFieldInfo describes a single reflected field. Used by CheckAllFieldsReflected() +struct ReflectedFieldInfo { + /// The field name + const std::string_view name; + /// The field size in bytes + const size_t size; + /// The field alignment in bytes + const size_t align; + /// The field offset in bytes + const size_t offset; +}; + +/// @returns Success if the sequential fields of @p fields have the expected offsets, and aligned +/// sum match the class size @p class_size. +Result CheckAllFieldsReflected(VectorRef fields, + std::string_view class_name, + size_t class_size, + size_t class_align, + bool class_is_castable); + +/// @returns Success if the TINT_REFLECT() reflected fields of @tparam CLASS match the declaration +/// order, do not have any gaps, and fully account for the entire size of the class. +template +Result CheckAllFieldsReflected() { + static_assert(!std::has_virtual_destructor_v || std::is_base_of_v, + "TINT_ASSERT_ALL_FIELDS_REFLECTED() cannot be used on virtual classes, except " + "for types using the tint::Castable framework"); + using R = typename CLASS::Reflection; + using Fields = typename R::Fields; + Vector> fields; + AlignedStorage obj; + R::ForeachField(obj.Get(), [&](auto&& field, std::string_view name) { + using T = std::decay_t; + size_t offset = static_cast(reinterpret_cast(&field) - + reinterpret_cast(&obj)); + fields.Push({name, sizeof(T), alignof(T), offset}); + }); + return CheckAllFieldsReflected(fields, R::Name, sizeof(CLASS), alignof(CLASS), + std::is_base_of_v); +} + +} // namespace tint::reflection::detail + +namespace tint { + +/// Is true if the class T has reflected its fields with TINT_REFLECT() +template +concept HasReflection = tint::reflection::detail::HasReflection::value; + +/// Calls @p callback with each field of @p object +/// @param object the object +/// @param callback a function that is called for each field of @p object. +/// @tparam CB a function with one of the signatures: +/// `void(auto& FIELD)` +/// `void(auto& FIELD, std::string_view NAME)` +template +void ForeachField(OBJECT& object, CB&& callback) { + using T = std::decay_t; + static_assert(HasReflection, "object missing TINT_REFLECT() declaration"); + constexpr bool callback_field = std::is_invocable_v, int&>; + constexpr bool callback_field_name = + std::is_invocable_v, int&, std::string_view>; + static_assert(callback_field || callback_field_name, + "callback must have the signature of:\n" + " 'void(auto& field)'\n" + "or 'void(auto& field, std::string_view name)'"); + if constexpr (callback_field) { + T::Reflection::ForeachField(object, + [&](auto& field, std::string_view) { callback(field); }); + } else { + T::Reflection::ForeachField(object, std::forward(callback)); + } +} + +/// Calls @p callback with each field of @p object +/// @param object the object +/// @param callback a function that is called for each field of @p object. +/// @tparam CB a function with one of the signatures: +/// `void(const auto& FIELD)` +/// `void(const auto& FIELD, std::string_view NAME)` +template +void ForeachField(const OBJECT& object, CB&& callback) { + using T = std::decay_t; + static_assert(HasReflection, "object missing TINT_REFLECT() declaration"); + constexpr bool callback_field = std::is_invocable_v, const int&>; + constexpr bool callback_field_name = + std::is_invocable_v, const int&, std::string_view>; + static_assert(callback_field || callback_field_name, + "callback must have the signature of:\n" + " 'void(auto& field)'\n" + "or 'void(auto& field, std::string_view name)'"); + if constexpr (callback_field) { + T::Reflection::ForeachField(object, + [&](const auto& field, std::string_view) { callback(field); }); + } else { + T::Reflection::ForeachField(object, std::forward(callback)); + } +} + +/// Macro used by TINT_FOREACH() in TINT_REFLECT() to generate the T::Reflection::Fields tuple. +#define TINT_REFLECT_FIELD_TYPE(FIELD) decltype(Class::FIELD), + +/// Macro used by TINT_FOREACH() in TINT_REFLECT() to generate a tuple of member values. +#define TINT_REFLECT_FIELD_VALUE(FIELD) object.FIELD, + +/// Macro used by TINT_FOREACH() in TINT_REFLECT() to call the callback function with each field in +/// the variadic. +#define TINT_REFLECT_CALLBACK_FIELD(FIELD) callback(object.FIELD, #FIELD); + +// TINT_REFLECT(CLASS, ...) reflects each of the fields arguments of CLASS so that the types can be +// used with tint::ForeachField(). +#define TINT_REFLECT(CLASS, ...) \ + struct Reflection { \ + using Class = CLASS; \ + using Fields = std::tuple; \ + [[maybe_unused]] static constexpr std::string_view Name = #CLASS; \ + [[maybe_unused]] static constexpr std::monostate kIgnore{}; \ + template \ + [[maybe_unused]] static constexpr void ForeachField(OBJECT&& object, CB&& callback) { \ + TINT_FOREACH(TINT_REFLECT_CALLBACK_FIELD, __VA_ARGS__) \ + } \ + [[maybe_unused]] static constexpr auto FieldsAsTuple(const Class& object) { \ + return std::tie(TINT_FOREACH(TINT_REFLECT_FIELD_VALUE, __VA_ARGS__) kIgnore); \ + } \ + } + +/// TINT_REFLECT_EQUALS(CLASS) generates an operator== for the CLASS based on the reflected fields. +/// All reflected fields must be equality comparable. +#define TINT_REFLECT_EQUALS(CLASS) \ + bool operator==(const CLASS& other) const { \ + return CLASS::Reflection::FieldsAsTuple(*this) == CLASS::Reflection::FieldsAsTuple(other); \ + } \ + TINT_REQUIRE_SEMICOLON + +/// TINT_REFLECT_HASH_CODE(CLASS) generates a tint::HashCode implementation for the CLASS based on +/// the reflected fields. +#define TINT_REFLECT_HASH_CODE(CLASS) \ + tint::HashCode HashCode() const { \ + return Hash(CLASS::Reflection::FieldsAsTuple(*this)); \ + } \ + TINT_REQUIRE_SEMICOLON + +/// TINT_ASSERT_ALL_FIELDS_REFLECTED(...) performs a compile-time assertion that all the fields of +/// CLASS have been reflected with TINT_REFLECT(). +/// @note The order in which the fields are passed to TINT_REFLECT must match the declaration order +/// in the class. +#define TINT_ASSERT_ALL_FIELDS_REFLECTED(CLASS) \ + ASSERT_EQ(::tint::reflection::detail::CheckAllFieldsReflected(), ::tint::Success) + +/// A template that can be specialized to reflect the valid range of an enum +/// Use TINT_REFLECT_ENUM_RANGE to specialize this class +template +struct EnumRange; + +/// Declares a specialization of EnumRange for the enum ENUM with the lowest enum value MIN and +/// largest enum value MAX. Must only be used in the `tint` namespace. +#define TINT_REFLECT_ENUM_RANGE(ENUM, MIN, MAX) \ + template <> \ + struct EnumRange { \ + static constexpr ENUM kMin = ENUM::MIN; \ + static constexpr ENUM kMax = ENUM::MAX; \ + } + +} // namespace tint + +#endif // SRC_TINT_UTILS_REFLECTION_H_ diff --git a/3rdparty/dawn/src/tint/utils/result.cc b/3rdparty/dawn/src/tint/utils/result.cc new file mode 100644 index 000000000..06caa3ff6 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/result.cc @@ -0,0 +1,40 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/result.h" + +#include + +namespace tint { + +Failure::Failure() = default; + +Failure::Failure(std::string_view err) { + reason = std::string(err); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/result.h b/3rdparty/dawn/src/tint/utils/result.h new file mode 100644 index 000000000..8f90acd9e --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/result.h @@ -0,0 +1,261 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_RESULT_H_ +#define SRC_TINT_UTILS_RESULT_H_ + +#include +#include +#include +#include + +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/rtti/traits.h" +#include "src/utils/compiler.h" + +namespace tint { + +/// Empty structure that can be used as the SUCCESS_TYPE for a Result. +struct SuccessType {}; + +/// An instance of SuccessType that can be used as a generic success value for a Result. +static constexpr const SuccessType Success; + +/// The default Result error type. +struct Failure { + /// Constructor with no diagnostics + Failure(); + + /// Constructor with a single diagnostic + /// @param err the single error diagnostic + explicit Failure(std::string_view err); + + std::string reason; +}; + +/// Write the Failure to the given stream +/// @param out the output stream +/// @param failure the Failure +/// @returns the output stream +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Failure& failure) { + return out << failure.reason; +} + +/// Result is a helper for functions that need to return a value, or an failure value. +/// Result can be constructed with either a 'success' or 'failure' value. +/// @tparam SUCCESS_TYPE the 'success' value type. +/// @tparam FAILURE_TYPE the 'failure' value type. Defaults to FailureType which provides no +/// information about the failure, except that something failed. Must not be the same type +/// as SUCCESS_TYPE. +template +struct [[nodiscard]] Result { + static_assert(!std::is_same_v, + "Result must not have the same type for SUCCESS_TYPE and FAILURE_TYPE"); + + /// Default constructor initializes to invalid state + Result() : value(std::monostate{}) {} + + /// Constructor + /// @param success the success result + Result(const SUCCESS_TYPE& success) // NOLINT(runtime/explicit): + : value{success} {} + + /// Constructor + /// @param success the success result + Result(SUCCESS_TYPE&& success) // NOLINT(runtime/explicit): + : value(std::move(SUCCESS_TYPE(std::move(success)))) {} + + /// Constructor + /// @param failure the failure result + Result(const FAILURE_TYPE& failure) // NOLINT(runtime/explicit): + : value{failure} {} + + /// Constructor + /// @param failure the failure result + Result(FAILURE_TYPE&& failure) // NOLINT(runtime/explicit): + : value{std::move(failure)} {} + + /// Copy constructor with success / failure casting + /// @param other the Result to copy + template ()}), + decltype(FAILURE_TYPE{std::declval()})>> + Result(const Result& other) { // NOLINT(runtime/explicit): + if (other == Success) { + value = SUCCESS_TYPE{other.Get()}; + } else { + value = FAILURE_TYPE{other.Failure()}; + } + } + + /// @returns the success value + /// @warning attempting to call this when the Result holds an failure will result in UB. + const SUCCESS_TYPE* operator->() const { + Validate(); + return &(Get()); + } + + /// @returns the success value + /// @warning attempting to call this when the Result holds an failure will result in UB. + SUCCESS_TYPE* operator->() { + Validate(); + return &(Get()); + } + + /// @returns the success value + /// @warning attempting to call this when the Result holds an failure value will result in UB. + const SUCCESS_TYPE& Get() const { + Validate(); + return std::get(value); + } + + /// @returns the success value + /// @warning attempting to call this when the Result holds an failure value will result in UB. + SUCCESS_TYPE& Get() { + Validate(); + return std::get(value); + } + + /// @returns the success value + /// @warning attempting to call this when the Result holds an failure value will result in UB. + SUCCESS_TYPE&& Move() { + Validate(); + return std::get(std::move(value)); + } + + /// @returns the failure value + /// @warning attempting to call this when the Result holds a success value will result in UB. + const FAILURE_TYPE& Failure() const { + Validate(); + return std::get(value); + } + + /// Equality operator + /// @param other the Result to compare this Result to + /// @returns true if this Result is equal to @p other + template + bool operator==(const Result& other) const { + return value == other.value; + } + + /// Equality operator + /// @param val the value to compare this Result to + /// @returns true if this result holds a success or failure value equal to `value` + template + bool operator==(const T& val) const { + Validate(); + + using D = std::decay_t; + static constexpr bool is_success = std::is_same_v; // T == Success + static constexpr bool is_success_ty = + std::is_same_v || + (traits::IsStringLike && traits::IsStringLike); // T == SUCCESS_TYPE + static constexpr bool is_failure_ty = + std::is_same_v || + (traits::IsStringLike && traits::IsStringLike); // T == FAILURE_TYPE + + static_assert(is_success || is_success_ty || is_failure_ty, + "unsupported type for Result equality operator"); + static_assert(!(is_success_ty && is_failure_ty), + "ambiguous success / failure type for Result equality operator"); + + if constexpr (is_success) { + return std::holds_alternative(value); + } else if constexpr (is_success_ty) { + if (auto* v = std::get_if(&value)) { + return *v == val; + } + return false; + } else if constexpr (is_failure_ty) { + if (auto* v = std::get_if(&value)) { + return *v == val; + } + return false; + } + } + /// Inequality operator + /// @param val the value to compare this Result to + /// @returns false if this result holds a success or failure value equal to `value` + template + bool operator!=(const T& val) const { + return !(*this == val); + } + + private: + void Validate() const { TINT_ASSERT(!std::holds_alternative(value)); } + + /// The result. Either a success of failure value. + std::variant value; +}; + +/// Writes the result to the stream. +/// @param out the stream to write to +/// @param res the result +/// @return the stream so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, const Result& res) { + if (res == Success) { + if constexpr (traits::HasOperatorShiftLeft) { + return out << "success: " << res.Get(); + } else { + return out << "success"; + } + } else { + if constexpr (traits::HasOperatorShiftLeft) { + return out << "failure: " << res.Failure(); + } else { + return out << "failure"; + } + } +} + +/// Check that @p result is Success and propagate the failure if not. +#define TINT_CHECK_RESULT(result) \ + if (auto&& tint_check_result_value = (result); \ + DAWN_UNLIKELY(tint_check_result_value != tint::Success)) { \ + return tint_check_result_value.Failure(); \ + } \ + TINT_REQUIRE_SEMICOLON + +#define TINT_CHECK_RESULT_UNWRAP_IMPL(to, from, result) \ + auto from = (result); \ + if (DAWN_UNLIKELY(from != tint::Success)) { \ + return from.Failure(); \ + } \ + auto to = from.Move(); \ + TINT_REQUIRE_SEMICOLON +/// Check that @p result is Success and propagate the failure if not. +#define TINT_CHECK_RESULT_UNWRAP(to, result) \ + TINT_CHECK_RESULT_UNWRAP_IMPL(to, TINT_CONCAT(tint_check_result_value, __LINE__), result) + +} // namespace tint + +#endif // SRC_TINT_UTILS_RESULT_H_ diff --git a/3rdparty/dawn/src/tint/utils/rtti/castable.cc b/3rdparty/dawn/src/tint/utils/rtti/castable.cc new file mode 100644 index 000000000..5c47323eb --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/rtti/castable.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/rtti/castable.h" + +namespace tint { + +/// The unique TypeInfo for the CastableBase type +/// @return doxygen-thinks-this-static-field-is-a-function :( +template <> +const TypeInfo tint::detail::TypeInfoOf::info{ + nullptr, "CastableBase", tint::TypeCode::Of(), + tint::TypeCodeSet::OfHierarchy()}; + +CastableBase::CastableBase(const CastableBase&) = default; + +CastableBase::~CastableBase() = default; + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/rtti/castable.h b/3rdparty/dawn/src/tint/utils/rtti/castable.h new file mode 100644 index 000000000..6a9cc0d48 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/rtti/castable.h @@ -0,0 +1,568 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_RTTI_CASTABLE_H_ +#define SRC_TINT_UTILS_RTTI_CASTABLE_H_ + +#include +#include +#include +#include +#include + +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/math/crc32.h" +#include "src/tint/utils/math/hash.h" +#include "src/tint/utils/rtti/ignore.h" +#include "src/tint/utils/rtti/traits.h" + +#if defined(__clang__) +/// Temporarily disable certain warnings when using Castable API +#define TINT_CASTABLE_PUSH_DISABLE_WARNINGS() \ + _Pragma("clang diagnostic push") /**/ \ + _Pragma("clang diagnostic ignored \"-Wundefined-var-template\"") /**/ \ + TINT_REQUIRE_SEMICOLON + +/// Restore disabled warnings +#define TINT_CASTABLE_POP_DISABLE_WARNINGS() \ + _Pragma("clang diagnostic pop") /**/ \ + TINT_REQUIRE_SEMICOLON +#else +#define TINT_CASTABLE_PUSH_DISABLE_WARNINGS() TINT_REQUIRE_SEMICOLON +#define TINT_CASTABLE_POP_DISABLE_WARNINGS() TINT_REQUIRE_SEMICOLON +#endif + +TINT_CASTABLE_PUSH_DISABLE_WARNINGS(); + +// Forward declarations +namespace tint { +class CastableBase; +} // namespace tint + +namespace tint::detail { +template +struct TypeInfoOf; +} // namespace tint::detail + +namespace tint { + +/// True if all template types that are not Ignore derive from CastableBase +template +static constexpr bool IsCastable = + ((tint::traits::IsTypeOrDerived || std::is_same_v)&&...) && + !(std::is_same_v && ...); + +/// Helper macro to instantiate the TypeInfo template for `CLASS`. +#define TINT_INSTANTIATE_TYPEINFO(CLASS) \ + TINT_CASTABLE_PUSH_DISABLE_WARNINGS(); \ + template <> \ + const tint::TypeInfo tint::detail::TypeInfoOf::info{ \ + &tint::detail::TypeInfoOf::info, \ + #CLASS, \ + tint::TypeCode::Of(), \ + tint::TypeCodeSet::OfHierarchy(), \ + }; \ + TINT_CASTABLE_POP_DISABLE_WARNINGS(); \ + static_assert(std::is_same_v, \ + #CLASS " does not derive from Castable<" #CLASS "[, BASE]>") + +/// Bit flags that can be passed to the template parameter `FLAGS` of Is() and As(). +enum CastFlags { + /// Disables the static_assert() inside Is(), that compile-time-verifies that the cast is + /// possible. This flag may be useful for highly-generic template + /// code that needs to compile for template permutations that generate + /// impossible casts. + kDontErrorOnImpossibleCast = 1, +}; + +/// TypeCode is a bit pattern used by Tint's RTTI system to determine whether two types are related +/// by inheritance. +/// Each TypeCode has exactly two bits set. +struct TypeCode { + /// @returns a compile-time TypeCode for the type `T`. + template + static constexpr inline TypeCode Of() { + static_assert(IsCastable, "T is not Castable"); + static_assert(std::is_same_v>, + "Strip const / volatile decorations before calling Of"); + /// Use the compiler's "pretty" function name, which includes the template type, to obtain a + /// unique hash value. +#ifdef _MSC_VER + constexpr Bits crc = tint::CRC32(__FUNCSIG__); +#else + constexpr Bits crc = tint::CRC32(__PRETTY_FUNCTION__); +#endif + constexpr Bits bit_a = (crc & 63); + constexpr Bits bit_b = ((crc >> 6) & 63); + constexpr Bits bit_c = (bit_a == bit_b) ? ((bit_a + 1) & 63) : bit_b; + return {(static_cast(1) << bit_a) | (static_cast(1) << bit_c)}; + } + + /// The unsigned integer type that holds the bits of the TypeCode + using Bits = uint64_t; + + /// The bits pattern of the TypeCode + const Bits bits; +}; + +/// TypeCodeSet is a set of TypeCodes, and internally uses a single integer to represent its +/// contents. TypeCodeSet acts as a bloom-filter, exposing methods to query whether the set _may_ +/// contain one or more TypeCodes. If these methods return `false` then the set definitely does +/// contain the TypeCode(s), however returning `true` means the *set has a possibility* of +/// containing the TypeCodes(s). +/// @see https://en.wikipedia.org/wiki/Bloom_filter +struct TypeCodeSet { + /// @returns the TypeCodeSet that contains the TypeCode of `T` and all its ancestor types. + template + static constexpr inline TypeCodeSet OfHierarchy() { + if constexpr (std::is_same_v) { + return {TypeCode::Of().bits}; + } else { + return {TypeCode::Of().bits | TypeCodeSet::OfHierarchy().bits}; + } + } + + /// @returns the TypeCodeSet of all the types in the tuple `TUPLE`. + template + static constexpr inline TypeCodeSet OfTuple() { + constexpr auto kCount = std::tuple_size_v; + if constexpr (kCount == 0) { + return {0}; + } else if constexpr (kCount == 1) { + return {TypeCode::Of>>().bits}; + } else { + constexpr auto kMid = kCount / 2; + return {OfTuple>().bits | + OfTuple>().bits}; + } + } + + /// @returns true if this TypeCodeSet may contain the TypeCode @p type_code. + inline bool MayContain(TypeCode type_code) const { + return (bits & type_code.bits) == type_code.bits; + } + + /// @returns true if TypeCodeSet may contain any of the TypeCodes in @p type_codes. + inline bool MayContainAnyOf(TypeCodeSet type_codes) const { + // TypeCode always has exactly two bits set, so if the intersection of this TypeCodeSet and + // type_codes contains fewer than two bits set, we know there's no possibility of the same + // type being part of both sets. + Bits mask = bits & type_codes.bits; + bool has_at_least_two_bits = (mask & (mask - 1)) != 0; + return has_at_least_two_bits; + } + + /// The unsigned integer type that holds the bits of the TypeCode + using Bits = typename TypeCode::Bits; + + /// The bits pattern of the TypeCode + const Bits bits; +}; + +/// TypeInfo holds type information for a Castable type. +struct TypeInfo { + /// The base class of this type + const TypeInfo* base; + /// The type name + const char* name; + /// The type's TypeCode + const TypeCode type_code; + /// The set of this type's TypeCode and all ancestor's TypeCodes + const TypeCodeSet full_type_code; + + /// @returns true if `type` derives from the class `TO` + /// @param object the object type to test from, which must be, or derive from type `FROM`. + /// @see CastFlags + template + static inline bool Is(const tint::TypeInfo* object) { + constexpr const bool downcast = std::is_base_of::value; + constexpr const bool upcast = std::is_base_of::value; + constexpr const bool nocast = std::is_same::value; + constexpr const bool assert_is_castable = (FLAGS & kDontErrorOnImpossibleCast) == 0; + + static_assert(upcast || downcast || nocast || !assert_is_castable, "impossible cast"); + + return upcast || nocast || object->Is(); + } + + /// @returns true if this type derives from the class `T` + template + inline bool Is() const { + auto* type = &Of>(); + + if constexpr (std::is_final_v) { + // T is final, so nothing can derive from T. + // We do not need to check ancestors, only whether this type is equal to the type T. + return type == this; + } else { + return Is(type); + } + } + + /// @param type the test type info + /// @returns true if the class with this TypeInfo is of, or derives from the + /// class with the given TypeInfo. + inline bool Is(const tint::TypeInfo* type) const { + if (!full_type_code.MayContain(type->type_code)) { + return false; + } + + // Walk the base types, starting with this TypeInfo, to see if any of the pointers match + // `type`. + for (auto* ti = this; ti != nullptr; ti = ti->base) { + if (ti == type) { + return true; + } + } + return false; + } + + /// @returns the static TypeInfo for the type T + template + static const TypeInfo& Of() { + return tint::detail::TypeInfoOf>::info; + } + + /// @returns true if this TypeInfo is of, or derives from any of the types in `TUPLE`. + template + inline bool IsAnyOfTuple() const { + constexpr auto kCount = std::tuple_size_v; + if constexpr (kCount == 0) { + return false; + } else if constexpr (kCount == 1) { + return Is(&Of>()); + } else { + if (full_type_code.MayContainAnyOf(TypeCodeSet::OfTuple())) { + // Possibly one of the types in `TUPLE`. + // Split the search in two, and scan each block. + static constexpr auto kMid = kCount / 2; + return IsAnyOfTuple>() || + IsAnyOfTuple>(); + } + return false; + } + } + + /// @returns true if this TypeInfo is of, or derives from any of the types in `TYPES`. + template + inline bool IsAnyOf() const { + return IsAnyOfTuple>(); + } +}; + +namespace detail { + +/// TypeInfoOf contains a single TypeInfo field for the type T. +/// TINT_INSTANTIATE_TYPEINFO() must be defined in a .cpp file for each type `T`. +template +struct TypeInfoOf { + /// The unique TypeInfo for the type T. + static const TypeInfo info; +}; + +/// A placeholder structure used for template parameters that need a default type, but can always be +/// automatically inferred. +struct Infer; + +} // namespace detail + +/// @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 +inline bool Is(FROM* obj) { + if (obj == nullptr) { + return false; + } + return TypeInfo::Is(&obj->TypeInfo()); +} + +/// @returns true if `obj` is a valid pointer, and is of, or derives from the type `TYPE`, and +/// pred(const TYPE*) returns true +/// @param obj the object to test from +/// @param pred predicate function with signature `bool(const TYPE*)` called iff object is of, or +/// derives from the class `TYPE`. +/// @see CastFlags +template +inline bool Is(OBJ* obj, Pred&& pred) { + return Is(obj) && pred(static_cast*>(obj)); +} + +/// @returns true if `obj` is a valid pointer, and is of, or derives from any of the types in +/// `TYPES`. +/// @param obj the object to query. +template +inline bool IsAnyOf(OBJ* obj) { + if (!obj) { + return false; + } + return obj->TypeInfo().template IsAnyOf(); +} + +/// @returns obj dynamically cast to the type `TO` or `nullptr` if this object does not derive from +/// `TO`. +/// @param obj the object to cast from +/// @see CastFlags +template +inline TO* As(FROM* obj) { + auto* as_castable = static_cast(obj); + return Is(obj) ? static_cast(as_castable) : nullptr; +} + +/// @returns obj dynamically cast to the type `TO` or `nullptr` if this object does not derive from +/// `TO`. +/// @param obj the object to cast from +/// @see CastFlags +template +inline const TO* As(const FROM* obj) { + auto* as_castable = static_cast(obj); + return Is(obj) ? static_cast(as_castable) : nullptr; +} + +/// CastableBase is the base class for all Castable objects. +/// It is not encouraged to directly derive from CastableBase without using the Castable helper +/// template. +/// @see Castable +class CastableBase { + public: + /// Copy constructor + CastableBase(const CastableBase&); + + /// Destructor + virtual ~CastableBase(); + + /// Copy assignment + /// @param other the CastableBase to copy + /// @returns the new CastableBase + CastableBase& operator=(const CastableBase& other) = default; + + /// @returns the TypeInfo of the object + inline const tint::TypeInfo& TypeInfo() const { return *type_info_; } + + /// @returns true if this object is of, or derives from the class `TO` + template + inline bool Is() const { + return tint::Is(this); + } + + /// @returns true if this object is of, or derives from the class `TO` and 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 + inline bool Is(Pred&& pred) const { + return tint::Is(this, std::forward(pred)); + } + + /// @returns true if this object is of, or derives from any of the `TO` classes. + template + inline bool IsAnyOf() const { + return tint::IsAnyOf(this); + } + + /// @returns this object dynamically cast to the type `TO` or `nullptr` if this object does not + /// derive from `TO`. + /// @see CastFlags + template + inline TO* As() { + return tint::As(this); + } + + /// @returns this object dynamically cast to the type `TO` or `nullptr` if this object does not + /// derive from `TO`. + /// @see CastFlags + template + inline const TO* As() const { + return tint::As(this); + } + + protected: + CastableBase() = default; + + /// The type information for the object + const tint::TypeInfo* type_info_ = nullptr; +}; + +/// Castable is a helper to derive `CLASS` from `BASE`, automatically implementing the Is() and As() +/// methods, along with a #Base type alias. +/// +/// Example usage: +/// +/// ``` +/// class Animal : public Castable {}; +/// +/// class Sheep : public Castable {}; +/// +/// Sheep* cast_to_sheep(Animal* animal) { +/// // You can query whether a Castable is of the given type with Is(): +/// printf("animal is a sheep? %s", animal->Is() ? "yes" : "no"); +/// +/// // You can always just try the cast with As(). +/// // If the object is not of the correct type, As() will return nullptr: +/// return animal->As(); +/// } +/// ``` +template +class Castable : public BASE { + public: + /// A type alias to this Castable. Commonly used in derived type constructors to forward + /// constructor arguments to BASE. + using Base = Castable; + + /// A type alias for `BASE`. + using TrueBase = BASE; + + /// A type alias for `CLASS`. + using Class = CLASS; + + /// Constructor + /// @param arguments the arguments to forward to the base class. + template + inline explicit Castable(ARGS&&... arguments) : TrueBase(std::forward(arguments)...) { + this->type_info_ = &TypeInfo::Of(); + } + + /// @returns true if this object is of, or derives from the class `TO` + /// @see CastFlags + template + inline bool Is() const { + return tint::Is(static_cast(this)); + } + + /// @returns true if this object is of, or derives from the class `TO` and + /// 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 + inline bool Is(Pred&& pred) const { + using TO = typename std::remove_pointer>::type; + return tint::Is(static_cast(this), std::forward(pred)); + } + + /// @returns true if this object is of, or derives from any of the `TO` + /// classes. + template + inline bool IsAnyOf() const { + return tint::IsAnyOf(static_cast(this)); + } + + /// @returns this object dynamically cast to the type `TO` or `nullptr` if + /// this object does not derive from `TO`. + /// @see CastFlags + template + inline TO* As() { + return tint::TypeInfo::Is(&this->TypeInfo()) + ? static_cast(static_cast(this)) + : nullptr; + } + + /// @returns this object dynamically cast to the type `TO` or `nullptr` if + /// this object does not derive from `TO`. + /// @see CastFlags + template + inline const TO* As() const { + return tint::TypeInfo::Is(&this->TypeInfo()) + ? static_cast(static_cast(this)) + : nullptr; + } +}; + +namespace detail { +/// typename CastableCommonBaseImpl::type resolves to the common base class for +/// all of TYPES. +template +struct CastableCommonBaseImpl {}; + +/// Alias to typename CastableCommonBaseImpl::type +template +using CastableCommonBase = typename CastableCommonBaseImpl::type; + +/// CastableCommonBaseImpl template specialization for a single type +template +struct CastableCommonBaseImpl { + /// Common base class of a single type is itself + using type = T; +}; + +/// CastableCommonBaseImpl A <-> CastableBase specialization +template +struct CastableCommonBaseImpl { + /// Common base class for A and CastableBase is CastableBase + using type = CastableBase; +}; + +/// CastableCommonBaseImpl T <-> Ignore specialization +template +struct CastableCommonBaseImpl { + /// Resolves to T as the other type is ignored + using type = T; +}; + +/// CastableCommonBaseImpl Ignore <-> T specialization +template +struct CastableCommonBaseImpl { + /// Resolves to T as the other type is ignored + using type = T; +}; + +/// CastableCommonBaseImpl A <-> B specialization +template +struct CastableCommonBaseImpl { + /// The common base class for A, B and OTHERS + using type = std::conditional_t, + B, // A derives from B + CastableCommonBase>; +}; + +/// CastableCommonBaseImpl 3+ types specialization +template +struct CastableCommonBaseImpl { + /// The common base class for A, B and OTHERS + using type = CastableCommonBase, OTHERS...>; +}; + +} // namespace detail + +/// Resolves to the common most derived type that each of the types in `TYPES` derives from. +template +using CastableCommonBase = tint::detail::CastableCommonBase; + +} // namespace tint + +namespace tint { + +using tint::As; +using tint::Is; + +} // namespace tint + +TINT_CASTABLE_POP_DISABLE_WARNINGS(); + +#endif // SRC_TINT_UTILS_RTTI_CASTABLE_H_ diff --git a/3rdparty/dawn/src/tint/utils/rtti/ignore.h b/3rdparty/dawn/src/tint/utils/rtti/ignore.h new file mode 100644 index 000000000..2014d11ea --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/rtti/ignore.h @@ -0,0 +1,61 @@ + +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_RTTI_IGNORE_H_ +#define SRC_TINT_UTILS_RTTI_IGNORE_H_ + +#include + +namespace tint { + +/// Ignore is used as a special type used for skipping over types for trait helper functions. +class Ignore {}; + +} // namespace tint + +namespace std { + +/// A specialization of std::common_type where the first template argument is tint::Ignore. +/// Used so that std::common_type will ignore template arguments of type tint::Ignore. +template +struct common_type { + /// The second template type. + using type = T; +}; + +/// A specialization of std::common_type where the second template argument is tint::Ignore. +/// Used so that std::common_type will ignore template arguments of type tint::Ignore. +template +struct common_type { + /// The first template type. + using type = T; +}; + +} // namespace std + +#endif // SRC_TINT_UTILS_RTTI_IGNORE_H_ diff --git a/3rdparty/dawn/src/tint/utils/rtti/switch.cc b/3rdparty/dawn/src/tint/utils/rtti/switch.cc new file mode 100644 index 000000000..249c599a1 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/rtti/switch.cc @@ -0,0 +1,41 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/rtti/switch.h" +#include "src/tint/utils/ice/ice.h" + +namespace tint::detail { + +void ICENoSwitchPassedNullptr(const char* file, unsigned int line) { + InternalCompilerError(file, line) << "Switch() passed nullptr"; +} + +void ICENoSwitchCasesMatched(const char* file, unsigned int line, const char* type_name) { + InternalCompilerError(file, line) << "Switch() matched no cases. Type: " << type_name; +} + +} // namespace tint::detail diff --git a/3rdparty/dawn/src/tint/utils/rtti/switch.h b/3rdparty/dawn/src/tint/utils/rtti/switch.h new file mode 100644 index 000000000..eb10dee48 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/rtti/switch.h @@ -0,0 +1,380 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_RTTI_SWITCH_H_ +#define SRC_TINT_UTILS_RTTI_SWITCH_H_ + +#include +#include + +#include "src/tint/utils/macros/defer.h" +#include "src/tint/utils/memory/aligned_storage.h" +#include "src/tint/utils/rtti/castable.h" +#include "src/tint/utils/rtti/ignore.h" + +namespace tint { + +/// Default can be used as the default case for a Switch(), when all previous cases failed to match. +/// +/// Example: +/// ``` +/// Switch(object, +/// [&](TypeA*) { /* ... */ }, +/// [&](TypeB*) { /* ... */ }, +/// [&](Default) { /* If not TypeA or TypeB */ }); +/// ``` +struct Default {}; + +/// SwitchMustMatchCase is a flag that can be passed as the last argument to Switch() which will +/// trigger an ICE if none of the cases matched. Cannot be used with Default. +/// See TINT_ICE_ON_NO_MATCH +struct SwitchMustMatchCase { + /// The source file that holds the TINT_ICE_ON_NO_MATCH + const char* file = ""; + /// The source line that holds the TINT_ICE_ON_NO_MATCH + unsigned int line = 0; +}; + +/// SwitchMustMatchCase is a flag that can be passed as the last argument to Switch() which will +/// trigger an ICE if none of the cases matched. Cannot be used with Default. +/// +/// Example: +/// ``` +/// Switch(object, +/// [&](TypeA*) { /* ... */ }, +/// [&](TypeB*) { /* ... */ }, +/// TINT_ICE_ON_NO_MATCH); +/// ``` +#define TINT_ICE_ON_NO_MATCH \ + ::tint::SwitchMustMatchCase { \ + __FILE__, __LINE__ \ + } + +} // namespace tint + +namespace tint::detail { + +/// Evaluates to the Switch case type being matched by the switch case function `FN`. +/// @note does not handle the Default case +/// @see Switch(). +template +using SwitchCaseType = + std::remove_pointer_t, 0>>; + +/// Searches the list of Switch cases for a Default case, returning the index of the Default case. +/// If the a Default case is not found in the tuple, then -1 is returned. +template +constexpr int IndexOfDefaultCase() { + if constexpr (START_IDX < std::tuple_size_v) { + using T = std::decay_t>; + if constexpr (std::is_same_v) { + return -1; + } else if constexpr (std::is_same_v, Default>) { + return static_cast(START_IDX); + } else { + return IndexOfDefaultCase(); + } + } else { + return -1; + } +} + +/// Searches the list of Switch cases for a SwitchMustMatchCase flag, returning the index of the +/// SwitchMustMatchCase case. If the a SwitchMustMatchCase case is not found in the tuple, then -1 +/// is returned. +template +constexpr int IndexOfSwitchMustMatchCase() { + if constexpr (START_IDX < std::tuple_size_v) { + using T = std::decay_t>; + return std::is_same_v + ? static_cast(START_IDX) + : IndexOfSwitchMustMatchCase(); + } else { + return -1; + } +} +/// Resolves to T if T is not nullptr_t, otherwise resolves to Ignore. +template +using NullptrToIgnore = std::conditional_t, ::tint::Ignore, T>; + +/// Resolves to `const TYPE` if any of `CASE_RETURN_TYPES` are const or pointer-to-const, otherwise +/// resolves to TYPE. +template +using PropagateReturnConst = std::conditional_t< + // Are any of the pointer-stripped types const? + (std::is_const_v> || ...), + const TYPE, // Yes: Apply const to TYPE + TYPE>; // No: Passthrough + +/// SwitchReturnTypeImpl is the implementation of SwitchReturnType +template +struct SwitchReturnTypeImpl; + +/// SwitchReturnTypeImpl specialization for non-castable case types and an explicitly specified +/// return type. +template +struct SwitchReturnTypeImpl { + /// Resolves to `REQUESTED_TYPE` + using type = REQUESTED_TYPE; +}; + +/// SwitchReturnTypeImpl specialization for non-castable case types and an inferred return type. +template +struct SwitchReturnTypeImpl { + /// Resolves to the common type for all the cases return types. + using type = std::common_type_t; +}; + +/// SwitchReturnTypeImpl specialization for castable case types and an explicitly specified return +/// type. +template +struct SwitchReturnTypeImpl { + public: + /// Resolves to `const REQUESTED_TYPE*` or `REQUESTED_TYPE*` + using type = PropagateReturnConst, CASE_RETURN_TYPES...>*; +}; + +/// SwitchReturnTypeImpl specialization for castable case types and an inferred return type. +template +struct SwitchReturnTypeImpl { + private: + using InferredType = + CastableCommonBase>...>; + + public: + /// `const T*` or `T*`, where T is the common base type for all the castable case types. + using type = PropagateReturnConst*; +}; + +/// Resolves to the return type for a Switch() with the requested return type `REQUESTED_TYPE` and +/// case statement return types. If `REQUESTED_TYPE` is Infer then the return type will be inferred +/// from the case return types. +template +using SwitchReturnType = typename SwitchReturnTypeImpl< + ::tint::IsCastable>...>, + REQUESTED_TYPE, + CASE_RETURN_TYPES...>::type; + +/// SwitchCaseReturnTypeImpl is the implementation of SwitchCaseReturnType +template +struct SwitchCaseReturnTypeImpl; + +/// SwitchCaseReturnTypeImpl specialization for non-flags. +template +struct SwitchCaseReturnTypeImpl { + /// The case function's return type. + using type = ::tint::traits::ReturnType; +}; + +/// SwitchCaseReturnTypeImpl specialization for flags. +template +struct SwitchCaseReturnTypeImpl { + /// These are not functions, they have no return type. + using type = ::tint::Ignore; +}; + +/// Resolves to the return type for a Switch() case. +/// If CASE is a flag like SwitchMustMatchCase, then resolves to ::tint::Ignore +template +using SwitchCaseReturnType = typename SwitchCaseReturnTypeImpl< + CASE, + std::is_same_v, SwitchMustMatchCase>>::type; + +/// Raises an ICE error that a Switch() was passed a nullptr object and there was no default case +[[noreturn]] void ICENoSwitchPassedNullptr(const char* file, unsigned int line); + +/// Raises an ICE error that a Switch() with a TINT_ICE_ON_NO_MATCH matched no cases. +/// @param file the file holding the Switch() +/// @param line the line of the TINT_ICE_ON_NO_MATCH +/// @type_name the type name of the object passed to Switch() +[[noreturn]] void ICENoSwitchCasesMatched(const char* file, + unsigned int line, + const char* type_name); + +} // namespace tint::detail + +namespace tint { + +/// Switch is used to dispatch one of the provided callback case handler functions based on the type +/// of `object` and the parameter type of the case handlers. Switch will sequentially check the type +/// of `object` against each of the switch case handler functions, and will invoke the first case +/// handler function which has a parameter type that matches the object type. When a case handler is +/// matched, it will be called with the single argument of `object` cast to the case handler's +/// parameter type. Switch will invoke at most one case handler. Each of the case functions must +/// have the signature `R(T*)` or `R(const T*)`, where `T` is the type matched by that case and `R` +/// is the return type, consistent across all case handlers. +/// +/// An optional default case function with the signature `R(Default)` can be used as the last case. +/// This default case will be called if all previous cases failed to match. +/// +/// The last argument may be SwitchMustMatchCase, in which case the Switch will trigger an ICE if +/// none of the cases matched. SwitchMustMatchCase cannot be used with a default case. +/// +/// If `object` is nullptr and a default case is provided, then the default case will be called. If +/// `object` is nullptr and no default case is provided, then no cases will be called. +/// +/// Example: +/// ``` +/// Switch(object, +/// [&](TypeA*) { /* ... */ }, +/// [&](TypeB*) { /* ... */ }); +/// +/// Switch(object, +/// [&](TypeA*) { /* ... */ }, +/// [&](TypeB*) { /* ... */ }, +/// [&](Default) { /* Called if object is not TypeA or TypeB */ }); +/// +/// Switch(object, +/// [&](TypeA*) { /* ... */ }, +/// [&](TypeB*) { /* ... */ }, +/// SwitchMustMatchCase); /* ICE if object is not TypeA or TypeB */ +/// ``` +/// +/// @param object the object who's type is used to +/// @param args the switch cases followed by an optional TINT_ICE_ON_NO_MATCH +/// @return the value returned by the called case. If no cases matched, then the zero value for the +/// consistent case type. +template +inline auto Switch(T* object, ARGS&&... args) { + TINT_BEGIN_DISABLE_WARNING(UNUSED_VALUE); + + using ArgsTuple = std::tuple; + static constexpr int kMustMatchCaseIndex = + ::tint::detail::IndexOfSwitchMustMatchCase(); + static constexpr bool kHasMustMatchCase = kMustMatchCaseIndex >= 0; + static constexpr int kDefaultIndex = ::tint::detail::IndexOfDefaultCase(); + static constexpr bool kHasDefaultCase = kDefaultIndex >= 0; + using ReturnType = + ::tint::detail::SwitchReturnType...>; + static constexpr bool kHasReturnType = !std::is_same_v; + + // Static assertions + static constexpr bool kDefaultIsOK = + kDefaultIndex == -1 || kDefaultIndex == static_cast(sizeof...(ARGS) - 1); + static constexpr bool kMustMatchCaseIsOK = + kMustMatchCaseIndex == -1 || kMustMatchCaseIndex == static_cast(sizeof...(ARGS) - 1); + static constexpr bool kReturnIsOK = + kHasDefaultCase || !kHasReturnType || std::is_constructible_v; + static_assert(kDefaultIsOK, "Default case must be last in Switch()"); + static_assert(kMustMatchCaseIsOK, "SwitchMustMatchCase must be last argument in Switch()"); + static_assert(!kHasDefaultCase || !kHasMustMatchCase, + "SwitchMustMatchCase cannot be used with a Default case"); + static_assert(kReturnIsOK, + "Switch() requires either a Default case or a return type that is either void or " + "default-constructable"); + + if (!object) { // Object is nullptr, so no cases can match + if constexpr (kHasMustMatchCase) { + const SwitchMustMatchCase& info = (args, ...); + ::tint::detail::ICENoSwitchPassedNullptr(info.file, info.line); + if constexpr (kHasReturnType) { + return ReturnType{}; + } else { + return; + } + } else if constexpr (kHasDefaultCase) { + // Evaluate default case. + const auto& default_case = (args, ...); + return static_cast(default_case(Default{})); + } else { + // No default case, no case can match. + if constexpr (kHasReturnType) { + return ReturnType{}; + } else { + return; + } + } + } + + AlignedStorage> return_storage; + auto* result = &return_storage.Get(); + + const ::tint::TypeInfo& type_info = object->TypeInfo(); + + // Examines the parameter type of the case function. + // If the parameter is a pointer type that `object` is of, or derives from, then that case + // function is called with `object` cast to that type, and `try_case` returns true. + // If the parameter is of type `Default`, then that case function is called and `try_case` + // returns true. + // Otherwise `try_case` returns false. + // If the case function is called and it returns a value, then this is copy constructed to the + // `result` pointer. + auto try_case = [&](auto&& case_fn) { + using CaseFunc = std::decay_t; + bool success = false; + if constexpr (std::is_same_v) { + ::tint::detail::ICENoSwitchCasesMatched(case_fn.file, case_fn.line, type_info.name); + } else { + using CaseType = ::tint::detail::SwitchCaseType; + if constexpr (std::is_same_v) { + if constexpr (kHasReturnType) { + new (result) ReturnType(static_cast(case_fn(Default{}))); + } else { + case_fn(Default{}); + } + success = true; + } else { + if (type_info.Is()) { + auto* v = static_cast(object); + if constexpr (kHasReturnType) { + new (result) ReturnType(static_cast(case_fn(v))); + } else { + case_fn(v); + } + success = true; + } + } + } + return success; + }; + + // Use a logical-or fold expression to try each of the cases in turn, until one matches the + // object type or a Default is reached. `handled` is true if a case function was called. + bool handled = ((try_case(std::forward(args)) || ...)); + + if constexpr (kHasReturnType) { + if constexpr (kHasDefaultCase) { + // Default case means there must be a returned value. + // No need to check handled, no requirement for a zero-initializer of ReturnType. + TINT_DEFER(result->~ReturnType()); + return *result; + } else { + if (handled) { + TINT_DEFER(result->~ReturnType()); + return *result; + } + return ReturnType{}; + } + } + + TINT_END_DISABLE_WARNING(UNUSED_VALUE); +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_RTTI_SWITCH_H_ diff --git a/3rdparty/dawn/src/tint/utils/rtti/traits.h b/3rdparty/dawn/src/tint/utils/rtti/traits.h new file mode 100644 index 000000000..a9827e0f6 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/rtti/traits.h @@ -0,0 +1,189 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_RTTI_TRAITS_H_ +#define SRC_TINT_UTILS_RTTI_TRAITS_H_ + +#include +#include +#include +#include +#include + +// Predeclarations +namespace tint { +class StringStream; +} + +namespace tint::traits { + +/// NthTypeOf returns the `N`th type in `Types` +template +using NthTypeOf = typename std::tuple_element>::type; + +/// Signature describes the signature of a function. +template +struct Signature { + /// The return type of the function signature + using ret = RETURN; + /// The parameters of the function signature held in a std::tuple + using parameters = std::tuple; + /// The type of the Nth parameter of function signature + template + using parameter = NthTypeOf; + /// The total number of parameters + static constexpr std::size_t parameter_count = sizeof...(PARAMETERS); +}; + +/// SignatureOf is a traits helper that infers the signature of the function, +/// method, static method, lambda, or function-like object `F`. +template +struct SignatureOf { + /// The signature of the function-like object `F` + using type = typename SignatureOf::type; +}; + +/// SignatureOf specialization for a regular function or static method. +template +struct SignatureOf { + /// The signature of the function-like object `F` + using type = Signature, typename std::decay_t...>; +}; + +/// SignatureOf specialization for a non-static method. +template +struct SignatureOf { + /// The signature of the function-like object `F` + using type = Signature, typename std::decay_t...>; +}; + +/// SignatureOf specialization for a non-static, const method. +template +struct SignatureOf { + /// The signature of the function-like object `F` + using type = Signature, typename std::decay_t...>; +}; + +/// SignatureOfT is an alias to `typename SignatureOf::type`. +template +using SignatureOfT = typename SignatureOf>::type; + +/// ParameterType is an alias to `typename SignatureOf::type::parameter`. +template +using ParameterType = typename SignatureOfT>::template parameter; + +/// LastParameterType returns the type of the last parameter of `F`. `F` must have at least one +/// parameter. +template +using LastParameterType = ParameterType>::parameter_count - 1>; + +/// ReturnType is an alias to `typename SignatureOf::type::ret`. +template +using ReturnType = typename SignatureOfT>::ret; + +/// @returns the std::index_sequence with all the indices shifted by OFFSET. +template +constexpr auto Shift(std::index_sequence) { + return std::integer_sequence{}; +} + +/// @returns a std::integer_sequence with the integers `[OFFSET..OFFSET+COUNT)` +template +constexpr auto Range() { + return Shift(std::make_index_sequence{}); +} + +namespace detail { + +/// @returns a nullptr of the tuple type `TUPLE` swizzled by `INDICES`. +/// @note: This function is intended to be used in a `decltype()` expression, +/// and returns a pointer-to-tuple as the tuple may hold non-constructable +/// types. +template +constexpr auto* SwizzlePtrTy(std::index_sequence) { + using Swizzled = std::tuple...>; + return static_cast(nullptr); +} + +/// Base template for IsTypeIn +template +struct IsTypeIn; + +/// Specialization for IsTypeIn +template typename TypeContainer, typename... Ts> +struct IsTypeIn> : std::disjunction...> {}; + +} // namespace detail + +/// Resolves to the slice of the tuple `t` with the tuple elements +/// `[OFFSET..OFFSET+COUNT)` +template +using SliceTuple = + std::remove_pointer_t(Range()))>; + +/// Evaluates to the decayed pointer element type, or the decayed type T if T is not a pointer. +template +using PtrElTy = std::decay_t>>; + +//////////////////////////////////////////////////////////////////////////////// +/// Concepts +//////////////////////////////////////////////////////////////////////////////// + +/// Returns true iff decayed T and decayed U are the same. +template +concept IsType = std::is_same_v, std::decay_t>; + +/// Evaluates to true if T is one of the types in the TypeContainer's template arguments. +/// Works for std::variant, std::tuple, std::pair, or any typename template where all parameters are +/// types. +template +concept IsTypeIn = traits::detail::IsTypeIn::value; + +/// IsTypeOrDerived is true iff `T` is of type `BASE`, or derives from `BASE`. +template +concept IsTypeOrDerived = + std::is_base_of_v> || std::is_same_v>; + +template +concept IsOStream = std::is_same_v || std::is_same_v || + std::is_same_v; + +/// Evaluates to true if `T` decayed is a `std::string`, `std::string_view`, `const char*` or +/// `char*` +template +concept IsStringLike = + std::is_same_v, std::string> || + std::is_same_v, std::string_view> || + std::is_same_v, const char*> || std::is_same_v, char*>; + +/// Is true if operator<<(LHS, RHS) exists +template +concept HasOperatorShiftLeft = requires(LHS os, RHS a) { os << a; }; + +} // namespace tint::traits + +#endif // SRC_TINT_UTILS_RTTI_TRAITS_H_ diff --git a/3rdparty/dawn/src/tint/utils/strconv/float_to_string.cc b/3rdparty/dawn/src/tint/utils/strconv/float_to_string.cc new file mode 100644 index 000000000..be915e8d5 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/strconv/float_to_string.cc @@ -0,0 +1,193 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "src/tint/utils/strconv/float_to_string.h" + +#include +#include +#include + +#include "src/tint/utils/ice/ice.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint::strconv { + +namespace { + +template +struct Traits; + +template <> +struct Traits { + using uint_t = uint32_t; + static constexpr int kExponentBias = 127; + static constexpr uint_t kExponentMask = 0x7f800000; + static constexpr uint_t kMantissaMask = 0x007fffff; + static constexpr uint_t kSignMask = 0x80000000; + static constexpr int kMantissaBits = 23; +}; + +template <> +struct Traits { + using uint_t = uint64_t; + static constexpr int kExponentBias = 1023; + static constexpr uint_t kExponentMask = 0x7ff0000000000000; + static constexpr uint_t kMantissaMask = 0x000fffffffffffff; + static constexpr uint_t kSignMask = 0x8000000000000000; + static constexpr int kMantissaBits = 52; +}; + +template +std::string ToString(F f) { + StringStream s; + s << f; + return s.str(); +} + +template +std::string ToBitPreservingString(F f) { + using T = Traits; + using uint_t = typename T::uint_t; + + // For the NaN case, avoid handling the number as a floating point value. + // Some machines will modify the top bit in the mantissa of a NaN. + + std::stringstream ss; + + typename T::uint_t float_bits = 0u; + static_assert(sizeof(float_bits) == sizeof(f)); + std::memcpy(&float_bits, &f, sizeof(float_bits)); + + // Handle the sign. + if (float_bits & T::kSignMask) { + // If `f` is -0.0 print -0.0. + ss << '-'; + // Strip sign bit. + float_bits = float_bits & (~T::kSignMask); + } + + switch (std::fpclassify(f)) { + case FP_ZERO: + case FP_NORMAL: + std::memcpy(&f, &float_bits, sizeof(float_bits)); + ss << ToString(f); + break; + + default: { + // Infinity, NaN, and Subnormal + // TODO(dneto): It's unclear how Infinity and NaN should be handled. + // See https://github.com/gpuweb/gpuweb/issues/1769 + + // std::hexfloat prints 'nan' and 'inf' instead of an explicit representation like we + // want. Split it out manually. + int mantissa_nibbles = (T::kMantissaBits + 3) / 4; + + const int biased_exponent = + static_cast((float_bits & T::kExponentMask) >> T::kMantissaBits); + int exponent = biased_exponent - T::kExponentBias; + uint_t mantissa = float_bits & T::kMantissaMask; + + ss << "0x"; + + if (exponent == T::kExponentBias + 1) { + if (mantissa == 0) { + // Infinity case. + ss << "1p+" << exponent; + } else { + // NaN case. + // Emit the mantissa bits as if they are left-justified after the binary point. + // This is what SPIRV-Tools hex float emitter does, and it's a justifiable + // choice independent of the bit width of the mantissa. + mantissa <<= (4 - (T::kMantissaBits % 4)); + // Remove trailing zeroes, for tidiness. + while (0 == (0xf & mantissa)) { + mantissa >>= 4; + mantissa_nibbles--; + } + ss << "1." << std::hex << std::setfill('0') << std::setw(mantissa_nibbles) + << mantissa << "p+" << std::dec << exponent; + } + } else { + // Subnormal, and not zero. + TINT_ASSERT(mantissa != 0); + const auto kTopBit = static_cast(1u) << T::kMantissaBits; + + // Shift left until we get 1.x + while (0 == (kTopBit & mantissa)) { + mantissa <<= 1; + exponent--; + } + // Emit the leading 1, and remove it from the mantissa. + ss << "1"; + mantissa = mantissa ^ kTopBit; + exponent++; + + // Left-justify mantissa to whole nibble. + mantissa <<= (4 - (T::kMantissaBits % 4)); + + // Emit the fractional part. + if (mantissa) { + // Remove trailing zeroes, for tidiness + while (0 == (0xf & mantissa)) { + mantissa >>= 4; + mantissa_nibbles--; + } + ss << "." << std::hex << std::setfill('0') << std::setw(mantissa_nibbles) + << mantissa; + } + // Emit the exponent + ss << "p" << std::showpos << std::dec << exponent; + } + } + } + return ss.str(); +} + +} // namespace + +std::string FloatToString(float f) { + return ToString(f); +} + +std::string FloatToBitPreservingString(float f) { + return ToBitPreservingString(f); +} + +std::string DoubleToString(double f) { + return ToString(f); +} + +std::string DoubleToBitPreservingString(double f) { + return ToBitPreservingString(f); +} + +} // namespace tint::strconv diff --git a/3rdparty/dawn/src/tint/utils/strconv/float_to_string.h b/3rdparty/dawn/src/tint/utils/strconv/float_to_string.h new file mode 100644 index 000000000..c27252317 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/strconv/float_to_string.h @@ -0,0 +1,63 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_STRCONV_FLOAT_TO_STRING_H_ +#define SRC_TINT_UTILS_STRCONV_FLOAT_TO_STRING_H_ + +#include + +namespace tint::strconv { + +/// Converts the float `f` to a string using fixed-point notation (not +/// scientific). The float will be printed with the full precision required to +/// describe the float. All trailing `0`s will be omitted after the last +/// non-zero fractional number, unless the fractional is zero, in which case the +/// number will end with `.0`. +/// @return the float f formatted to a string +std::string FloatToString(float f); + +/// Converts the double `f` to a string using fixed-point notation (not +/// scientific). The double will be printed with the full precision required to +/// describe the double. All trailing `0`s will be omitted after the last +/// non-zero fractional number, unless the fractional is zero, in which case the +/// number will end with `.0`. +/// @return the double f formatted to a string +std::string DoubleToString(double f); + +/// Converts the float `f` to a string, using hex float notation for infinities, +/// NaNs, or subnormal numbers. Otherwise behaves as FloatToString. +/// @return the float f formatted to a string +std::string FloatToBitPreservingString(float f); + +/// Converts the double `f` to a string, using hex double notation for infinities, +/// NaNs, or subnormal numbers. Otherwise behaves as FloatToString. +/// @return the double f formatted to a string +std::string DoubleToBitPreservingString(double f); + +} // namespace tint::strconv + +#endif // SRC_TINT_UTILS_STRCONV_FLOAT_TO_STRING_H_ diff --git a/3rdparty/dawn/src/tint/utils/strconv/parse_num.cc b/3rdparty/dawn/src/tint/utils/strconv/parse_num.cc new file mode 100644 index 000000000..b9a06edf2 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/strconv/parse_num.cc @@ -0,0 +1,115 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/strconv/parse_num.h" + +#include + +#include "absl/strings/charconv.h" + +namespace tint::strconv { + +namespace { + +// The unsafe buffer warnings here are intrinsic to how the underlying API being called operates, so +// cannot be easily avoided. +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +template +Result Parse(std::string_view number) { + T val = 0; + if constexpr (std::is_floating_point_v) { + auto result = absl::from_chars(number.data(), number.data() + number.size(), val); + if (result.ec == std::errc::result_out_of_range) { + return ParseNumberError::kResultOutOfRange; + } + if (result.ec != std::errc() || result.ptr != number.data() + number.size()) { + return ParseNumberError::kUnparsable; + } + } else { + auto result = std::from_chars(number.data(), number.data() + number.size(), val); + if (result.ec == std::errc::result_out_of_range) { + return ParseNumberError::kResultOutOfRange; + } + if (result.ec != std::errc() || result.ptr != number.data() + number.size()) { + return ParseNumberError::kUnparsable; + } + } + return val; +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +} // namespace + +Result ParseFloat(std::string_view str) { + return Parse(str); +} + +Result ParseDouble(std::string_view str) { + return Parse(str); +} + +Result ParseInt(std::string_view str) { + return Parse(str); +} + +Result ParseUint(std::string_view str) { + return Parse(str); +} + +Result ParseInt64(std::string_view str) { + return Parse(str); +} + +Result ParseUint64(std::string_view str) { + return Parse(str); +} + +Result ParseInt32(std::string_view str) { + return Parse(str); +} + +Result ParseUint32(std::string_view str) { + return Parse(str); +} + +Result ParseInt16(std::string_view str) { + return Parse(str); +} + +Result ParseUint16(std::string_view str) { + return Parse(str); +} + +Result ParseInt8(std::string_view str) { + return Parse(str); +} + +Result ParseUint8(std::string_view str) { + return Parse(str); +} + +} // namespace tint::strconv diff --git a/3rdparty/dawn/src/tint/utils/strconv/parse_num.h b/3rdparty/dawn/src/tint/utils/strconv/parse_num.h new file mode 100644 index 000000000..5b0026962 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/strconv/parse_num.h @@ -0,0 +1,145 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_STRCONV_PARSE_NUM_H_ +#define SRC_TINT_UTILS_STRCONV_PARSE_NUM_H_ + +#include + +#include "src/tint/utils/macros/compiler.h" +#include "src/tint/utils/result.h" + +namespace tint::strconv { + +/// Error returned by the number parsing functions +enum class ParseNumberError : uint8_t { + /// The number was unparsable + kUnparsable, + /// The parsed number is not representable by the target datatype + kResultOutOfRange, +}; + +/// @param str the string +/// @returns the string @p str parsed as a float +Result ParseFloat(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a double +Result ParseDouble(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a int +Result ParseInt(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a unsigned int +Result ParseUint(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a int64_t +Result ParseInt64(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a uint64_t +Result ParseUint64(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a int32_t +Result ParseInt32(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a uint32_t +Result ParseUint32(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a int16_t +Result ParseInt16(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a uint16_t +Result ParseUint16(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a int8_t +Result ParseInt8(std::string_view str); + +/// @param str the string +/// @returns the string @p str parsed as a uint8_t +Result ParseUint8(std::string_view str); + +/// Disables the false-positive unreachable-code compiler warnings +TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE); + +/// @param str the string +/// @returns the string @p str parsed as a the number @p T +template +inline Result ParseNumber(std::string_view str) { + if constexpr (std::is_same_v) { + return ParseFloat(str); + } + if constexpr (std::is_same_v) { + return ParseDouble(str); + } + if constexpr (std::is_same_v) { + return ParseInt(str); + } + if constexpr (std::is_same_v) { + return ParseUint(str); + } + if constexpr (std::is_same_v) { + return ParseInt64(str); + } + if constexpr (std::is_same_v) { + return ParseUint64(str); + } + if constexpr (std::is_same_v) { + return ParseInt32(str); + } + if constexpr (std::is_same_v) { + return ParseUint32(str); + } + if constexpr (std::is_same_v) { + return ParseInt16(str); + } + if constexpr (std::is_same_v) { + return ParseUint16(str); + } + if constexpr (std::is_same_v) { + return ParseInt8(str); + } + if constexpr (std::is_same_v) { + return ParseUint8(str); + } + return ParseNumberError::kUnparsable; +} + +/// Re-enables the unreachable-code compiler warnings +TINT_END_DISABLE_WARNING(UNREACHABLE_CODE); + +} // namespace tint::strconv + +#endif // SRC_TINT_UTILS_STRCONV_PARSE_NUM_H_ diff --git a/3rdparty/dawn/src/tint/utils/symbol/generation_id.cc b/3rdparty/dawn/src/tint/utils/symbol/generation_id.cc new file mode 100644 index 000000000..fd452cd2c --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/symbol/generation_id.cc @@ -0,0 +1,48 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/symbol/generation_id.h" + +#include + +namespace tint { + +namespace { + +std::atomic next_generation_id{1}; + +} // namespace + +GenerationID::GenerationID() = default; + +GenerationID::GenerationID(uint32_t id) : val(id) {} + +GenerationID GenerationID::New() { + return GenerationID(next_generation_id++); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/symbol/generation_id.h b/3rdparty/dawn/src/tint/utils/symbol/generation_id.h new file mode 100644 index 000000000..b25e664e5 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/symbol/generation_id.h @@ -0,0 +1,65 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_SYMBOL_GENERATION_ID_H_ +#define SRC_TINT_UTILS_SYMBOL_GENERATION_ID_H_ + +#include + +#include "src/tint/utils/rtti/traits.h" + +namespace tint { + +/// A GenerationID is a unique identifier of a generation. +/// +/// GenerationID can be used to ensure that objects referenced by the generation are owned +/// exclusively by that generation and have accidentally not leaked from another generation. +class GenerationID { + public: + /// Constructor + GenerationID(); + + /// @returns a new globally unique GenerationID + static GenerationID New(); + + /// Equality operator + /// @param rhs the other GenerationID + /// @returns true if the GenerationIDs are equal + bool operator==(const GenerationID& rhs) const { return val == rhs.val; } + + /// @returns true if this GenerationID is valid + explicit operator bool() const { return val != 0; } + + private: + explicit GenerationID(uint32_t); + + uint32_t val = 0; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_SYMBOL_GENERATION_ID_H_ diff --git a/3rdparty/dawn/src/tint/utils/symbol/symbol.cc b/3rdparty/dawn/src/tint/utils/symbol/symbol.cc new file mode 100644 index 000000000..8de12e9d0 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/symbol/symbol.cc @@ -0,0 +1,102 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/symbol/symbol.h" + +#include + +#include "src/tint/utils/ice/ice.h" + +namespace tint { +namespace { + +void AssertGenerationIDsEqual(GenerationID a, + GenerationID b, + const char* msg, + const char* file, + size_t line) { + if (a == b) { + return; // matched + } + if (!a || !b) { + return; // a or b were not valid + } + tint::InternalCompilerError(file, line) << msg; +} + +} // namespace + +/// TINT_ASSERT_GENERATION_IDS_EQUAL(A, B) is a macro that asserts +/// that the generation identifiers for A and B are equal, if both A and B have +/// valid generation identifiers. +#define TINT_ASSERT_GENERATION_IDS_EQUAL(a, b) \ + AssertGenerationIDsEqual(a, b, "TINT_ASSERT_GENERATION_IDS_EQUAL(" #a ", " #b ")", __FILE__, \ + __LINE__) + +Symbol::Symbol() = default; + +Symbol::Symbol(uint32_t val, GenerationID pid, std::string_view name) + : val_(val), generation_id_(pid), name_(name) {} + +Symbol::Symbol(const Symbol& o) = default; + +Symbol::Symbol(Symbol&& o) = default; + +Symbol::~Symbol() = default; + +Symbol& Symbol::operator=(const Symbol& o) = default; + +Symbol& Symbol::operator=(Symbol&& o) = default; + +bool Symbol::operator==(const Symbol& other) const { + TINT_ASSERT_GENERATION_IDS_EQUAL(generation_id_, other.generation_id_); + return val_ == other.val_; +} + +bool Symbol::operator!=(const Symbol& other) const { + TINT_ASSERT_GENERATION_IDS_EQUAL(generation_id_, other.generation_id_); + return val_ != other.val_; +} + +bool Symbol::operator<(const Symbol& other) const { + TINT_ASSERT_GENERATION_IDS_EQUAL(generation_id_, other.generation_id_); + return val_ < other.val_; +} + +std::string Symbol::to_str() const { + return "$" + std::to_string(val_); +} + +std::string_view Symbol::NameView() const { + return name_; +} + +std::string Symbol::Name() const { + return std::string(name_); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/symbol/symbol.h b/3rdparty/dawn/src/tint/utils/symbol/symbol.h new file mode 100644 index 000000000..40a013c5b --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/symbol/symbol.h @@ -0,0 +1,127 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_SYMBOL_SYMBOL_H_ +#define SRC_TINT_UTILS_SYMBOL_SYMBOL_H_ + +#include + +#include "src/tint/utils/symbol/generation_id.h" + +namespace tint { + +/// A symbol representing a string in the system +class Symbol { + public: + /// Constructor + /// An invalid symbol + Symbol(); + /// Constructor + /// @param val the symbol value + /// @param pid the identifier of the program that owns this Symbol + /// @param name the name this symbol represents + Symbol(uint32_t val, GenerationID pid, std::string_view name); + + /// Copy constructor + /// @param o the symbol to copy + Symbol(const Symbol& o); + /// Move constructor + /// @param o the symbol to move + Symbol(Symbol&& o); + /// Destructor + ~Symbol(); + + /// Copy assignment + /// @param o the other symbol + /// @returns the symbol after doing the copy + Symbol& operator=(const Symbol& o); + /// Move assignment + /// @param o the other symbol + /// @returns teh symbol after doing the move + Symbol& operator=(Symbol&& o); + + /// Equality operator + /// @param o the other symbol + /// @returns true if the symbols are the same + bool operator==(const Symbol& o) const; + + /// Inequality operator + /// @param o the other symbol + /// @returns true if the symbols are the different + bool operator!=(const Symbol& o) const; + + /// Less-than operator + /// @param o the other symbol + /// @returns true if this symbol is ordered before symbol `o` + bool operator<(const Symbol& o) const; + + /// @returns true if the symbol is valid + bool IsValid() const { return val_ != static_cast(-1); } + + /// @returns true if the symbol is valid + explicit operator bool() const { return IsValid(); } + + /// @returns the value for the symbol + uint32_t value() const { return val_; } + + /// Convert the symbol to a string + /// @return the string representation of the symbol + std::string to_str() const; + + /// Converts the symbol to the registered name + /// @returns the string_view representing the name of the symbol + std::string_view NameView() const; + + /// Converts the symbol to the registered name + /// @returns the string representing the name of the symbol + std::string Name() const; + + private: + uint32_t val_ = static_cast(-1); + GenerationID generation_id_; + std::string_view name_; +}; + +} // namespace tint + +namespace std { + +/// Custom std::hash specialization for tint::Symbol so symbols can be used as +/// keys for std::unordered_map and std::unordered_set. +template <> +class hash { + public: + /// @param sym the symbol to return + /// @return the Symbol internal value + inline std::size_t operator()(const tint::Symbol& sym) const { + return static_cast(sym.value()); + } +}; + +} // namespace std + +#endif // SRC_TINT_UTILS_SYMBOL_SYMBOL_H_ diff --git a/3rdparty/dawn/src/tint/utils/symbol/symbol_table.cc b/3rdparty/dawn/src/tint/utils/symbol/symbol_table.cc new file mode 100644 index 000000000..f4a3e8ff9 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/symbol/symbol_table.cc @@ -0,0 +1,108 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include "src/tint/utils/symbol/symbol_table.h" + +#include "src/tint/utils/ice/ice.h" + +namespace tint { + +SymbolTable::SymbolTable() : generation_id_(GenerationID::New()) {} + +SymbolTable::SymbolTable(GenerationID gen_id) : generation_id_(gen_id) {} + +SymbolTable::SymbolTable(SymbolTable&&) = default; + +SymbolTable::~SymbolTable() = default; + +SymbolTable& SymbolTable::operator=(SymbolTable&&) = default; + +Symbol SymbolTable::Register(std::string_view name) { + TINT_ASSERT(!name.empty()); + + auto& it = name_to_symbol_.GetOrAddZeroEntry(name); + if (it.value) { + return Symbol{it.value, generation_id_, it.key}; + } + + auto view = Allocate(name); + it.key = view; + it.value = next_symbol_++; + return Symbol{it.value, generation_id_, view}; +} + +Symbol SymbolTable::Get(std::string_view name) const { + if (auto* entry = name_to_symbol_.GetEntry(name)) { + return Symbol{entry->value, generation_id_, entry->key}; + } + return Symbol{}; +} + +Symbol SymbolTable::New(std::string_view prefix_view /* = "" */) { + std::string prefix; + if (prefix_view.empty()) { + prefix = "tint_symbol"; + } else { + prefix = std::string(prefix_view); + } + + auto& it = name_to_symbol_.GetOrAddZeroEntry(prefix); + if (it.value == 0) { + // prefix is a unique name + auto view = Allocate(prefix); + it.key = view; + it.value = next_symbol_++; + return Symbol{it.value, generation_id_, view}; + } + + size_t& i = last_prefix_to_index_.GetOrAddZero(prefix); + std::string name; + do { + ++i; + name = prefix + "_" + std::to_string(i); + } while (name_to_symbol_.Contains(name)); + + auto view = Allocate(name); + auto id = name_to_symbol_.Add(view, next_symbol_++); + return Symbol{id.value, generation_id_, view}; +} + +std::string_view SymbolTable::Allocate(std::string_view name) { + static_assert(sizeof(char) == 1); + char* name_mem = Bitcast(name_allocator_.Allocate(name.length() + 1)); + TINT_ASSERT(name_mem != nullptr) << "failed to allocate memory for symbol's string"; + + memcpy(name_mem, name.data(), name.length() + 1); + return {name_mem, name.length()}; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/symbol/symbol_table.h b/3rdparty/dawn/src/tint/utils/symbol/symbol_table.h new file mode 100644 index 000000000..89f746a33 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/symbol/symbol_table.h @@ -0,0 +1,118 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_SYMBOL_SYMBOL_TABLE_H_ +#define SRC_TINT_UTILS_SYMBOL_SYMBOL_TABLE_H_ + +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/memory/bump_allocator.h" +#include "src/tint/utils/symbol/symbol.h" + +namespace tint { + +/// Holds mappings from symbols to their associated string names +class SymbolTable { + public: + /// Constructor + SymbolTable(); + /// Move Constructor + SymbolTable(SymbolTable&&); + /// Destructor + ~SymbolTable(); + + /// Move assignment + /// @param other the symbol table to move + /// @returns the symbol table + SymbolTable& operator=(SymbolTable&& other); + + /// @returns a symbol table to hold symbols which point to the allocated names in @p o. + /// The symbol table after Wrap is intended to temporarily extend the objects of an existing + /// immutable SymbolTable. + /// @warning As the copied objects are owned by @p o, @p o must not be destructed or assigned + /// while using this symbol table. + /// @param o the immutable SymbolTable to extend + static SymbolTable Wrap(const SymbolTable& o) { + SymbolTable out(o.generation_id_); + out.next_symbol_ = o.next_symbol_; + out.name_to_symbol_ = o.name_to_symbol_; + out.last_prefix_to_index_ = o.last_prefix_to_index_; + out.generation_id_ = o.generation_id_; + return out; + } + + /// Registers a name into the symbol table, returning the Symbol. + /// @param name the name to register + /// @returns the symbol representing the given name + Symbol Register(std::string_view name); + + /// Returns the symbol for the given `name` + /// @param name the name to lookup + /// @returns the symbol for the name or Symbol() if not found. + Symbol Get(std::string_view name) const; + + /// Returns a new unique symbol with the given name, possibly suffixed with a + /// unique number. + /// @param name the symbol name + /// @returns a new, unnamed symbol with the given name. If the name is already + /// taken then this will be suffixed with an underscore and a unique numerical + /// value + Symbol New(std::string_view name = ""); + + /// Foreach calls the callback function `F` for each symbol in the table. + /// @param callback must be a function or function-like object with the + /// signature: `void(Symbol)` + template + void Foreach(F&& callback) const { + for (auto& it : name_to_symbol_) { + callback(Symbol{it.value, generation_id_, it.key}); + } + } + + GenerationID GenIDForTesting() const { return generation_id_; } + + private: + explicit SymbolTable(GenerationID gen_id); + SymbolTable(const SymbolTable&) = delete; + SymbolTable& operator=(const SymbolTable& other) = delete; + + std::string_view Allocate(std::string_view name); + + // The value to be associated to the next registered symbol table entry. + uint32_t next_symbol_ = 1; + + Hashmap name_to_symbol_; + Hashmap last_prefix_to_index_; + GenerationID generation_id_; + + tint::BumpAllocator name_allocator_; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_SYMBOL_SYMBOL_TABLE_H_ diff --git a/3rdparty/dawn/src/tint/utils/system/env.h b/3rdparty/dawn/src/tint/utils/system/env.h new file mode 100644 index 000000000..bcf2b4604 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/system/env.h @@ -0,0 +1,42 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_SYSTEM_ENV_H_ +#define SRC_TINT_UTILS_SYSTEM_ENV_H_ + +#include + +namespace tint { + +/// @param name the name of the environment variable +/// @returns the environment variable value with the given name, or an empty string if the variable +/// was not found. +std::string GetEnvVar(std::string_view name); + +} // namespace tint + +#endif // SRC_TINT_UTILS_SYSTEM_ENV_H_ diff --git a/3rdparty/dawn/src/tint/utils/system/executable_path.h b/3rdparty/dawn/src/tint/utils/system/executable_path.h new file mode 100644 index 000000000..bb04d306e --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/system/executable_path.h @@ -0,0 +1,43 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_SYSTEM_EXECUTABLE_PATH_H_ +#define SRC_TINT_UTILS_SYSTEM_EXECUTABLE_PATH_H_ + +#include + +namespace tint { + +// Returns the path of the currently running executable +std::string ExecutablePath(); + +// Returns the directory of the currently running executable +std::string ExecutableDirectory(); + +} // namespace tint + +#endif // SRC_TINT_UTILS_SYSTEM_EXECUTABLE_PATH_H_ diff --git a/3rdparty/dawn/src/tint/utils/system/terminal.h b/3rdparty/dawn/src/tint/utils/system/terminal.h new file mode 100644 index 000000000..2374496b8 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/system/terminal.h @@ -0,0 +1,49 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_SYSTEM_TERMINAL_H_ +#define SRC_TINT_UTILS_SYSTEM_TERMINAL_H_ + +#include +#include + +namespace tint { + +/// Detects whether the terminal at @p out supports color output. +/// @param out the file to print to. +/// @return true if the terminal supports colors. +bool TerminalSupportsColors(FILE* out); + +/// Attempts to detect whether the terminal at @p out is dark. +/// @param out the file to print to. +/// @returns true if the terminal is dark, false if the terminal is light, or nullopt if +/// unknown. +std::optional TerminalIsDark(FILE* out); + +} // namespace tint + +#endif // SRC_TINT_UTILS_SYSTEM_TERMINAL_H_ diff --git a/3rdparty/dawn/src/tint/utils/templates/enums.tmpl.inc b/3rdparty/dawn/src/tint/utils/templates/enums.tmpl.inc new file mode 100644 index 000000000..db426705e --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/templates/enums.tmpl.inc @@ -0,0 +1,236 @@ +{{- (Globals).Put "enum_override_names" Map -}} + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "OverrideEnumName" -}} +{{- /* Overrides the C++ name for a sem.Enum. */ -}} +{{- /* Arguments: */ -}} +{{- /* * 'Enum' the sem::Enum */ -}} +{{- /* * 'Name' the new C++ name for enum */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum_override_names := (Globals).Get "enum_override_names" -}} +{{- $enum_override_names.Put $.Enum $.Name -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "EnumName" -}} +{{- /* Prints the C++ name for the given sem.Enum argument. */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum_override_names := (Globals).Get "enum_override_names" -}} +{{- $override := $enum_override_names.Get $ -}} +{{ if $override -}} +{{ $override -}} +{{ else -}} +{{ PascalCase $.Name}} +{{- end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "EnumCase" -}} +{{- /* Prints the 'Enum::kEntry' name for the provided sem.EnumEntry */ -}} +{{- /* argument. */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- Eval "EnumName" $.Enum}}::k{{PascalCase $.Name}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "EnumFirst" -}} +{{- /* Prints the name of the first enum entry */ -}} +{{- /* ------------------------------------------------------------------ */ -}} + kUndefined +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "EnumLast" -}} +{{- /* Prints the name of the last enum entry */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum := $ -}} +{{- $item := index $enum.Entries (Sum -1 (len $enum.Entries)) -}} + k{{PascalCase $item.Name}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "DeclareEnum" -}} +{{- /* Declares the 'enum class' for the provided sem.Enum argument. */ -}} +{{- /* The argument can also be a key-value pair with the following keys: */ -}} +{{- /* "Enum" - the sem.Enum argument */ -}} +{{- /* "EmitOStream" - (default: true) should operator<< be emitted? */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum := $ -}} +{{- $emit_ostream := true -}} +{{- if Is $ "Map" -}} +{{- $enum = $.Enum -}} +{{- $emit_ostream = $.EmitOStream -}} +{{- end }} + +{{- $name := Eval "EnumName" $enum -}} +enum class {{$name}} : uint8_t { + kUndefined, +{{- range $entry := $enum.Entries }} + k{{PascalCase $entry.Name}},{{if $entry.IsInternal}} // Tint-internal enum entry - not parsed{{end}} +{{- end }} +}; + +/// @param value the enum value +/// @returns the string for the given enum value +std::string_view ToString({{$name}} value); + +{{- if $emit_ostream}} + +/// @param out the stream to write to +/// @param value the {{$name}} +/// @returns @p out so calls can be chained +template + requires(traits::IsOStream) +auto& operator<<(STREAM& out, {{$name}} value) { + return out << ToString(value); +} +{{- end}} + +/// Parse{{$name}} parses a {{$name}} from a string. +/// @param str the string to parse +/// @returns the parsed enum, or {{$name}}::kUndefined if the string could not be parsed. +{{$name}} Parse{{$name}}(std::string_view str); + +constexpr std::string_view k{{$name}}Strings[] = { +{{- range $entry := $enum.Entries }} +{{- if not $entry.IsInternal}} + "{{$entry.Name}}", +{{- end }} +{{- end }} +}; + +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "ParseEnum" -}} +{{- /* Implements the 'ParseEnum' function for the provided sem.Enum */ -}} +{{- /* argument. */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum := Eval "EnumName" $ -}} +/// Parse{{$enum}} parses a {{$enum}} from a string. +/// @param str the string to parse +/// @returns the parsed enum, or {{$enum}}::kUndefined if the string could not be parsed. +{{$enum}} Parse{{$enum}}(std::string_view str) { +{{- range $entry := $.PublicEntries }} + if (str == "{{$entry.Name}}") { + return {{template "EnumCase" $entry}}; + } +{{- end }} + return {{$enum}}::kUndefined; +} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "EnumOStream" -}} +{{- /* Implements the stream 'operator<<()' function to print the */ -}} +{{- /* provided sem.Enum. */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum := Eval "EnumName" $ -}} +std::string_view ToString({{$enum}} value) { + switch (value) { + case {{$enum}}::kUndefined: + return "undefined"; +{{- range $entry := $.Entries }} + case {{template "EnumCase" $entry}}: + return "{{$entry.Name}}"; +{{- end }} + } + return ""; +} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "TestParsePrintEnum" -}} +{{- /* Implements unit tests for parsing and printing the provided */ -}} +{{- /* sem.Enum argument. */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum := Eval "EnumName" $ -}} +namespace parse_print_tests { + +struct {{$enum}}Case { + const char* string; + {{$enum}} value; +}; + +inline std::ostream& operator<<(std::ostream& out, {{$enum}}Case c) { + return out << "'" << std::string(c.string) << "'"; +} + +static constexpr {{$enum}}Case kValid{{$enum}}Cases[] = { +{{- range $entry := $.PublicEntries }} + {"{{$entry.Name}}", {{template "EnumCase" $entry}}}, +{{- end }} +}; + +static constexpr {{$enum}}Case kInvalid{{$enum}}Cases[] = { +{{- $exclude := $.NameSet -}} +{{- range $entry := $.PublicEntries }} + {"{{Scramble $entry.Name $exclude}}", {{$enum}}::kUndefined}, + {"{{Scramble $entry.Name $exclude}}", {{$enum}}::kUndefined}, + {"{{Scramble $entry.Name $exclude}}", {{$enum}}::kUndefined}, +{{- end }} +}; + +using {{$enum}}ParseTest = testing::TestWithParam<{{$enum}}Case>; + +TEST_P({{$enum}}ParseTest, Parse) { + const char* string = GetParam().string; + {{$enum}} expect = GetParam().value; + EXPECT_EQ(expect, Parse{{$enum}}(string)); +} + +INSTANTIATE_TEST_SUITE_P(Valid{{$enum}}Cases, {{$enum}}ParseTest, testing::ValuesIn(kValid{{$enum}}Cases)); +INSTANTIATE_TEST_SUITE_P(Invalid{{$enum}}Cases, {{$enum}}ParseTest, testing::ValuesIn(kInvalid{{$enum}}Cases)); + +using {{$enum}}PrintTest = testing::TestWithParam<{{$enum}}Case>; + +TEST_P({{$enum}}PrintTest, Print) { + {{$enum}} value = GetParam().value; + const char* expect = GetParam().string; + EXPECT_EQ(expect, ToString(value)); +} + +INSTANTIATE_TEST_SUITE_P(Valid{{$enum}}Cases, {{$enum}}PrintTest, testing::ValuesIn(kValid{{$enum}}Cases)); + +} // namespace parse_print_tests + +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "BenchmarkParseEnum" -}} +{{- /* Implements a micro-benchmark for parsing the provided sem.Enum */ -}} +{{- /* argument. */ -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $enum := Eval "EnumName" $ -}} +void {{$enum}}Parser(::benchmark::State& state) { + const char* kStrings[] = { +{{- $exclude := $.NameSet -}} +{{- range $entry := $.PublicEntries }} + "{{Scramble $entry.Name $exclude}}", + "{{Scramble $entry.Name $exclude}}", + "{{Scramble $entry.Name $exclude}}", + "{{$entry.Name}}", + "{{Scramble $entry.Name $exclude}}", + "{{Scramble $entry.Name $exclude}}", + "{{Scramble $entry.Name $exclude}}", +{{- end }} + }; + for (auto _ : state) { + for (auto* str : kStrings) { + auto result = Parse{{$enum}}(str); + benchmark::DoNotOptimize(result); + } + } +} // NOLINT(readability/fn_size) + +BENCHMARK({{$enum}}Parser); +{{- end -}} diff --git a/3rdparty/dawn/src/tint/utils/templates/intrinsic_table_data.tmpl.inc b/3rdparty/dawn/src/tint/utils/templates/intrinsic_table_data.tmpl.inc new file mode 100644 index 000000000..1a75518fe --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/templates/intrinsic_table_data.tmpl.inc @@ -0,0 +1,513 @@ +{{- /* +-------------------------------------------------------------------------------- +Template file for use with tools/src/cmd/gen to generate the constant data that +is held in a core::intrinsic::TableData. + +To update the generated file, run: + ./tools/run gen + +See: +* tools/src/cmd/gen for structures used by this template +* https://golang.org/pkg/text/template/ for documentation on the template syntax +-------------------------------------------------------------------------------- +*/ -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "Data" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $I := $.Intrinsics -}} + +namespace { + +using ConstEvalFunctionIndex = tint::core::intrinsic::ConstEvalFunctionIndex; +using IntrinsicInfo = tint::core::intrinsic::IntrinsicInfo; +using MatcherIndicesIndex = tint::core::intrinsic::MatcherIndicesIndex; +using MatchState = tint::core::intrinsic::MatchState; +using Number = tint::core::intrinsic::Number; +using NumberMatcher = tint::core::intrinsic::NumberMatcher; +using NumberMatcherIndex = tint::core::intrinsic::NumberMatcherIndex; +using OverloadFlag = tint::core::intrinsic::OverloadFlag; +using OverloadFlags = tint::core::intrinsic::OverloadFlags; +using OverloadIndex = tint::core::intrinsic::OverloadIndex; +using OverloadInfo = tint::core::intrinsic::OverloadInfo; +using ParameterIndex = tint::core::intrinsic::ParameterIndex; +using ParameterInfo = tint::core::intrinsic::ParameterInfo; +using StringStream = tint::StringStream; +using TemplateIndex = tint::core::intrinsic::TemplateIndex; +using Type = tint::core::type::Type; +using TypeMatcher = tint::core::intrinsic::TypeMatcher; +using TypeMatcherIndex = tint::core::intrinsic::TypeMatcherIndex; + +template +using TemplateNumberMatcher = tint::core::intrinsic::TemplateNumberMatcher; + +template +using TemplateTypeMatcher = tint::core::intrinsic::TemplateTypeMatcher; + +{{ with $I.Sem -}} +{{ range .Types -}} +{{ template "Type" . }} +{{ end -}} +{{ range .TypeMatchers -}} +{{ template "TypeMatcher" . }} +{{ end -}} +{{ range .EnumMatchers -}} +{{ template "EnumMatcher" . }} +{{ end -}} +{{- end -}} + +{{- with $I.Table -}} +{{- template "Matchers" $I }} + +{{- if .MatcherIndices}} + +constexpr MatcherIndex kMatcherIndices[] = { +{{- range $i, $idx := .MatcherIndices }} + /* [{{$i}}] */ MatcherIndex({{$idx}}), +{{- end }} +}; + +static_assert(MatcherIndicesIndex::CanIndex(kMatcherIndices), + "MatcherIndicesIndex is not large enough to index kMatcherIndices"); +{{- end}} +{{- if .Parameters}} + +constexpr ParameterInfo kParameters[] = { +{{- range $i, $p := .Parameters }} + { + /* [{{$i}}] */ + /* usage */ core::ParameterUsage:: +{{- if $p.Usage }}k{{PascalCase $p.Usage}} +{{- else }}kNone +{{- end }}, + /* matcher_indices */ +{{- if ge $p.MatcherIndicesOffset 0 }} MatcherIndicesIndex({{$p.MatcherIndicesOffset}}) +{{- else }} MatcherIndicesIndex(/* invalid */) +{{- end }}, + }, +{{- end }} +}; + +static_assert(ParameterIndex::CanIndex(kParameters), + "ParameterIndex is not large enough to index kParameters"); +{{- end}} +{{- if .Templates}} + +constexpr TemplateInfo kTemplates[] = { +{{- range $i, $t := .Templates }} + { + /* [{{$i}}] */ + /* name */ "{{$t.Name}}", + /* matcher_indices */ +{{- if ge $t.MatcherIndicesOffset 0 }} MatcherIndicesIndex({{$t.MatcherIndicesOffset}}) +{{- else }} MatcherIndicesIndex(/* invalid */) +{{- end }}, + /* kind */ TemplateInfo::Kind::k{{$t.Kind}}, + }, +{{- end }} +}; + +static_assert(TemplateIndex::CanIndex(kTemplates), + "TemplateIndex is not large enough to index kTemplates"); +{{- end }} + +{{- if .ConstEvalFunctions}} +{{/* newline */}} +constexpr core::constant::Eval::Function kConstEvalFunctions[] = { +{{- range $i, $f := .ConstEvalFunctions }} + /* [{{$i}}] */ &core::constant::Eval::{{template "OperatorName" $f}}, +{{- end }} +}; + +static_assert(ConstEvalFunctionIndex::CanIndex(kConstEvalFunctions), + "ConstEvalFunctionIndex is not large enough to index kConstEvalFunctions"); +{{- end}} + +constexpr OverloadInfo kOverloads[] = { +{{- range $i, $o := .Overloads }} + { + /* [{{$i}}] */ + /* flags */ OverloadFlags(OverloadFlag::kIs{{Title $o.Kind}} +{{- range $i, $u := $o.CanBeUsedInStage.List -}} + , OverloadFlag::kSupports{{Title $u}}Pipeline +{{- end }} +{{- if $o.MustUse}}, OverloadFlag::kMustUse{{end}} +{{- if $o.MemberFunction}}, OverloadFlag::kMemberFunction{{end}} +{{- if $o.IsDeprecated}}, OverloadFlag::kIsDeprecated{{end -}} + ), + /* num_parameters */ {{$o.NumParameters}}, + /* num_explicit_templates */ {{$o.NumExplicitTemplates}}, + /* num_templates */ {{$o.NumTemplates}}, + /* templates */ +{{- if ge $o.TemplatesOffset 0 }} TemplateIndex({{$o.TemplatesOffset}}) +{{- else }} TemplateIndex(/* invalid */) +{{- end }}, + /* parameters */ +{{- if ge $o.ParametersOffset 0 }} ParameterIndex({{$o.ParametersOffset}}) +{{- else }} ParameterIndex(/* invalid */) +{{- end }}, + /* return_matcher_indices */ +{{- if ge $o.ReturnMatcherIndicesOffset 0 }} MatcherIndicesIndex({{$o.ReturnMatcherIndicesOffset}}) +{{- else }} MatcherIndicesIndex(/* invalid */) +{{- end }}, + /* const_eval_fn */ +{{- if ge $o.ConstEvalFunctionOffset 0 }} ConstEvalFunctionIndex({{$o.ConstEvalFunctionOffset}}) +{{- else }} ConstEvalFunctionIndex(/* invalid */) +{{- end }}, + }, +{{- end }} +}; + +static_assert(OverloadIndex::CanIndex(kOverloads), + "OverloadIndex is not large enough to index kOverloads"); + +constexpr IntrinsicInfo kBuiltins[] = { +{{- range $i, $b := .Builtins }} + { + /* [{{$i}}] */ +{{- range $b.OverloadDescriptions }} + /* {{.}} */ +{{- end }} + /* num overloads */ {{$b.NumOverloads}}, + /* overloads */ OverloadIndex({{$b.OverloadsOffset}}), + }, +{{- end }} +}; + +{{- if .UnaryOperators}} +{{/* newline */}} +constexpr IntrinsicInfo kUnaryOperators[] = { +{{- range $i, $o := .UnaryOperators }} + { + /* [{{$i}}] */ +{{- range $o.OverloadDescriptions }} + /* {{.}} */ +{{- end }} + /* num overloads */ {{$o.NumOverloads}}, + /* overloads */ OverloadIndex({{$o.OverloadsOffset}}), + }, +{{- end }} +}; +{{- end }} + +{{- $unary_ops := Map }} +{{- range $i, $o := .UnaryOperators }} +{{- $unary_ops.Put $o.Name true }} +constexpr uint8_t kUnaryOperator{{ template "OperatorName" $o.Name}} = {{$i}}; +{{- end }} + +{{- if .BinaryOperators}} +{{/* newline */}} +constexpr IntrinsicInfo kBinaryOperators[] = { +{{- range $i, $o := .BinaryOperators }} + { + /* [{{$i}}] */ +{{- range $o.OverloadDescriptions }} + /* {{.}} */ +{{- end }} + /* num overloads */ {{$o.NumOverloads}}, + /* overloads */ OverloadIndex({{$o.OverloadsOffset}}), + }, +{{- end }} +}; +{{- end }} + +{{- $bin_ops := Map }} +{{- range $i, $o := .BinaryOperators }} +{{- $bin_ops.Put $o.Name true }} +constexpr uint8_t kBinaryOperator{{ template "OperatorName" $o.Name}} = {{$i}}; +{{- end }} + +{{- if .ConstructorsAndConverters}} +{{/* newline */}} +constexpr IntrinsicInfo kConstructorsAndConverters[] = { +{{- range $i, $o := .ConstructorsAndConverters }} + { + /* [{{$i}}] */ +{{- range $o.OverloadDescriptions }} + /* {{.}} */ +{{- end }} + /* num overloads */ {{$o.NumOverloads}}, + /* overloads */ OverloadIndex({{$o.OverloadsOffset}}), + }, +{{- end }} +}; +{{- end }} + +} // anonymous namespace + +const core::intrinsic::TableData {{$.Name}}{ + /* templates */ {{if .Templates}}kTemplates{{else}}Empty{{end}}, + /* type_matcher_indices */ {{if .MatcherIndices}}kMatcherIndices{{else}}Empty{{end}}, + /* type_matchers */ {{if .TMatchers}}kTypeMatchers{{else}}Empty{{end}}, + /* number_matchers */ {{if .NMatchers}}kNumberMatchers{{else}}Empty{{end}}, + /* parameters */ {{if .Parameters}}kParameters{{else}}Empty{{end}}, + /* overloads */ kOverloads, + /* const_eval_functions */ {{if .ConstEvalFunctions}}kConstEvalFunctions{{else}}Empty{{end}}, + /* ctor_conv */ {{if .ConstructorsAndConverters}}kConstructorsAndConverters{{else}}Empty{{end}}, + /* builtins */ kBuiltins, +{{- range $op := List "+" "-" "*" "/" "%" "^" "&" "|" "&&" "||" "==" "!=" "<" ">" "<=" ">=" "<<" ">>"}} +{{- $N := Eval "OperatorName" $op }} + /* binary '{{$op}}' */ {{if $bin_ops.Get .}}kBinaryOperators[kBinaryOperator{{$N}}]{{else}}tint::core::intrinsic::kNoOverloads{{end}}, +{{- end}} +{{- range $op := List "!" "~" "-" "*" "&"}} +{{- $N := Eval "OperatorName" $op }} + /* unary '{{$op}}' */ {{if $unary_ops.Get .}}kUnaryOperators[kUnaryOperator{{$N}}]{{else}}tint::core::intrinsic::kNoOverloads{{end}}, +{{- end}} +}; + +{{ end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "Type" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $name := PascalCase .Name -}} +/// TypeMatcher for 'type {{.Name}}' +constexpr TypeMatcher k{{$name}}Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { +{{- range .TemplateParams }} +{{- template "DeclareLocalTemplateParam" . }} +{{- end }} + if (!Match{{$name}}(state, ty{{range .TemplateParams}}, {{.GetName}}{{end}})) { + return nullptr; + } +{{- range .TemplateParams }} + {{.Name}} = {{ template "MatchTemplateParam" .}}({{.Name}}); + if ({{ template "IsTemplateParamInvalid" .}}) { + return nullptr; + } +{{- end }} + return Build{{$name}}(state, ty{{range .TemplateParams}}, {{.GetName}}{{end}}); + }, +/* print */ []([[maybe_unused]] MatchState* state, StyledText& out) { +{{- range .TemplateParams }} +{{- template "DeclareLocalTemplateParamName" . }} +{{- end }} + +{{- if .DisplayName }} + out << style::Type({{range $i, $n := SplitDisplayName .DisplayName}}{{if $i}}, {{end}}{{$n}}{{end}}); +{{- else if .TemplateParams }} + out << style::Type("{{.Name}}", "<", {{template "AppendTemplateParamNames" .TemplateParams}}, ">"); +{{- else }} + out << style::Type("{{.Name}}"); +{{- end }} + } +}; + +{{ end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "TypeMatcher" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $name := PascalCase .Name -}} +/// TypeMatcher for 'match {{.Name}}' +constexpr TypeMatcher k{{$name}}Matcher { +/* match */ [](MatchState& state, const Type* ty) -> const Type* { +{{- range .PrecedenceSortedTypes }} + if (Match{{PascalCase .Name}}(state, ty)) { + return Build{{PascalCase .Name}}(state, ty); + } +{{- end }} + return nullptr; + }, +/* print */ [](MatchState*, StyledText& out) { + // Note: We pass nullptr to the Matcher.print() functions, as matchers do not support + // template arguments, nor can they match sub-types. As such, they have no use for the MatchState. +{{ range .Types -}} +{{- if IsFirstIn . $.Types }} k{{PascalCase .Name}}Matcher.print(nullptr, out); +{{- else if IsLastIn . $.Types }} out << style::Plain(" or "); k{{PascalCase .Name}}Matcher.print(nullptr, out); +{{- else }} out << style::Plain(", "); k{{PascalCase .Name}}Matcher.print(nullptr, out); +{{- end -}} +{{- end -}} + } +}; +{{ end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "EnumMatcher" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- $class := PascalCase .Name -}} +{{- $enum := PascalCase .Enum.Name -}} +{{- $NS := .Enum.NS -}} +/// EnumMatcher for 'match {{.Name}}' +constexpr NumberMatcher k{{$class}}Matcher { +{{ if eq 1 (len .Options) -}} +{{- $option := index .Options 0 }} +{{- $entry := printf "k%v" (PascalCase $option.Name) -}} +/* match */ [](MatchState&, Number number) -> Number { + if (number.IsAny() || number.Value() == static_cast({{$NS}}::{{$enum}}::{{$entry}})) { + return Number(static_cast({{$NS}}::{{$enum}}::{{$entry}})); + } + return Number::invalid; + }, +{{- else -}} +/* match */ [](MatchState&, Number number) -> Number { + switch (static_cast<{{$NS}}::{{$enum}}>(number.Value())) { +{{- range .Options }} + case {{$NS}}::{{$enum}}::k{{PascalCase .Name}}: +{{- end }} + return number; + default: + return Number::invalid; + } + }, +{{- end }} +/* print */ [](MatchState*, StyledText& out) { + out +{{- range .Options -}} +{{- if IsFirstIn . $.Options }}<< style::Enum("{{.Name}}") +{{- else if IsLastIn . $.Options }}<< style::Plain(" or ") << style::Enum("{{.Name}}") +{{- else }}<< style::Plain(", ") << style::Enum("{{.Name}}") +{{- end -}} +{{- end -}}; + } +}; +{{ end -}} + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "Matchers" -}} +{{- /* ------------------------------------------------------------------ */ -}} +/// Type and number matchers +{{- $t_names := Map -}} +{{- $n_names := Map -}} +{{- range Iterate $.Sem.MaxTemplates -}} +{{- $t_names.Put . (printf "TemplateTypeMatcher<%v>::matcher" .) -}} +{{- $n_names.Put . (printf "TemplateNumberMatcher<%v>::matcher" .) }} +{{- end }} +{{- range $.Sem.Types -}} +{{- $name := printf "k%vMatcher" (PascalCase .Name) -}} +{{- $t_names.Put . $name }} +{{- end }} +{{- range $.Sem.TypeMatchers -}} +{{- $name := printf "k%vMatcher" (PascalCase .Name) -}} +{{- $t_names.Put . $name }} +{{- end }} +{{- range $.Sem.EnumMatchers -}} +{{- $name := printf "k%vMatcher" (PascalCase .Name) -}} +{{- $n_names.Put . $name }} +{{- end }} + +{{- if $.Table.TMatchers}} + +/// The template types, types, and type matchers +constexpr TypeMatcher kTypeMatchers[] = { +{{- range $i, $m := $.Table.TMatchers }} + /* [{{$i}}] */ +{{- if $m }} {{$t_names.Get $m}}, +{{- else }} {{$t_names.Get $i}}, +{{- end }} +{{- end }} +}; +{{- end}} +{{- if $.Table.NMatchers}} + +/// The template numbers, and number matchers +constexpr NumberMatcher kNumberMatchers[] = { +{{- range $i, $m := $.Table.NMatchers }} + /* [{{$i}}] */ +{{- if $m }} {{$n_names.Get $m}}, +{{- else }} {{$n_names.Get $i}}, +{{- end }} +{{- end }} +}; +{{- end}} + +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "DeclareLocalTemplateParam" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- if IsTemplateTypeParam . }} + const Type* {{.Name}} = nullptr; +{{- else if IsTemplateNumberParam . }} + Number {{.Name}} = Number::invalid; +{{- else if IsTemplateEnumParam . }} + Number {{.Name}} = Number::invalid; +{{- end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "DeclareLocalTemplateParamName" -}} +{{- /* ------------------------------------------------------------------ */ -}} + StyledText {{.Name}}; +{{- if IsTemplateTypeParam . }} + state->PrintType({{.Name}}); +{{- else if IsTemplateNumberParam . }} + state->PrintNum({{.Name}}); +{{- else if IsTemplateEnumParam . }} + state->PrintNum({{.Name}}); +{{- end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "MatchTemplateParam" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- if IsTemplateTypeParam . -}} + state.Type +{{- else if IsTemplateNumberParam . -}} + state.Num +{{- else if IsTemplateEnumParam . -}} + state.Num +{{- end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "IsTemplateParamInvalid" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- if IsTemplateTypeParam . -}} + {{.Name}} == nullptr +{{- else if IsTemplateNumberParam . -}} + !{{.Name}}.IsValid() +{{- else if IsTemplateEnumParam . -}} + !{{.Name}}.IsValid() +{{- end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "AppendTemplateParamNames" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- range $i, $ := . -}} +{{- if $i }}, ", ", {{.Name}} +{{- else }}{{.Name}} +{{- end -}} +{{- end -}} +{{- end -}} + + +{{- /* ------------------------------------------------------------------ */ -}} +{{- define "OperatorName" -}} +{{- /* ------------------------------------------------------------------ */ -}} +{{- if eq . "<<" -}}ShiftLeft +{{- else if eq . "&" -}}And +{{- else if eq . "|" -}}Or +{{- else if eq . "^" -}}Xor +{{- else if eq . "&&" -}}LogicalAnd +{{- else if eq . "||" -}}LogicalOr +{{- else if eq . "==" -}}Equal +{{- else if eq . "!" -}}Not +{{- else if eq . "!=" -}}NotEqual +{{- else if eq . "~" -}}Complement +{{- else if eq . "<" -}}LessThan +{{- else if eq . ">" -}}GreaterThan +{{- else if eq . "<=" -}}LessThanEqual +{{- else if eq . ">=" -}}GreaterThanEqual +{{- else if eq . "<<" -}}ShiftLeft +{{- else if eq . ">>" -}}ShiftRight +{{- else if eq . "+" -}}Plus +{{- else if eq . "-" -}}Minus +{{- else if eq . "*" -}}Star +{{- else if eq . "/" -}}Divide +{{- else if eq . "%" -}}Modulo +{{- else -}}{{.}} +{{- end -}} +{{- end -}} diff --git a/3rdparty/dawn/src/tint/utils/text/base64.cc b/3rdparty/dawn/src/tint/utils/text/base64.cc new file mode 100644 index 000000000..7ae85cc36 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/base64.cc @@ -0,0 +1,71 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "src/tint/utils/text/base64.h" + +namespace tint { + +Vector DecodeBase64FromComments(std::string_view wgsl) { + Vector out; + size_t block_nesting = 0; + bool line_comment = false; + for (size_t i = 0, n = wgsl.length(); i < n; i++) { + char curr = wgsl[i]; + if (curr == '\n') { + line_comment = false; + continue; + } + + char next = (i + 1) < n ? wgsl[i + 1] : 0; + if (curr == '/' && next == '*') { + block_nesting++; + i++; // skip '*' + continue; + } + if (block_nesting > 0 && curr == '*' && next == '/') { + block_nesting--; + i++; // skip '/' + continue; + } + if (block_nesting == 0 && curr == '/' && next == '/') { + line_comment = true; + i++; // skip '/' + continue; + } + + if (block_nesting > 0 || line_comment) { + if (auto v = DecodeBase64(curr)) { + out.Push(std::byte{*v}); + } + } + } + return out; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/base64.h b/3rdparty/dawn/src/tint/utils/text/base64.h new file mode 100644 index 000000000..1047c3355 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/base64.h @@ -0,0 +1,68 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_BASE64_H_ +#define SRC_TINT_UTILS_TEXT_BASE64_H_ + +#include +#include + +#include "src/tint/utils/containers/vector.h" + +namespace tint { + +/// Decodes a byte from a base64 encoded character +/// @param c the character to decode +/// @return the decoded value, or std::nullopt if the character is padding ('=') or an invalid +/// character. +inline std::optional DecodeBase64(char c) { + if (c >= 'A' && c <= 'Z') { + return static_cast(c - 'A'); + } + if (c >= 'a' && c <= 'z') { + return static_cast(26 + c - 'a'); + } + if (c >= '0' && c <= '9') { + return static_cast(52 + c - '0'); + } + if (c == '+') { + return 62; + } + if (c == '/') { + return 63; + } + return std::nullopt; +} +/// DecodeBase64FromComments parses all the comments from the WGSL source string as a base64 byte +/// stream. Non-base64 characters are skipped +/// @param wgsl the WGSL source +/// @return the base64 decoded bytes +Vector DecodeBase64FromComments(std::string_view wgsl); + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_BASE64_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/color_mode.cc b/3rdparty/dawn/src/tint/utils/text/color_mode.cc new file mode 100644 index 000000000..4765f5a97 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/color_mode.cc @@ -0,0 +1,65 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/text/color_mode.h" + +#include "src/tint/utils/system/env.h" +#include "src/tint/utils/system/terminal.h" +#include "src/tint/utils/text/styled_text_printer.h" +#include "src/tint/utils/text/styled_text_theme.h" + +namespace tint { + +ColorMode ColorModeDefault() { + if (!tint::TerminalSupportsColors(stdout)) { + return ColorMode::kPlain; + } + if (auto res = tint::TerminalIsDark(stdout)) { + return *res ? ColorMode::kDark : ColorMode::kLight; + } + if (auto env = tint::GetEnvVar("DARK_BACKGROUND_COLOR"); !env.empty()) { + return env != "0" ? ColorMode::kDark : ColorMode::kLight; + } + if (auto env = tint::GetEnvVar("LIGHT_BACKGROUND_COLOR"); !env.empty()) { + return env != "0" ? ColorMode::kLight : ColorMode::kDark; + } + return ColorMode::kDark; +} + +std::unique_ptr CreatePrinter(ColorMode mode) { + switch (mode) { + case ColorMode::kLight: + return tint::StyledTextPrinter::Create(stderr, tint::StyledTextTheme::kDefaultLight); + case ColorMode::kDark: + return tint::StyledTextPrinter::Create(stderr, tint::StyledTextTheme::kDefaultDark); + case ColorMode::kPlain: + break; + } + return tint::StyledTextPrinter::CreatePlain(stderr); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/color_mode.h b/3rdparty/dawn/src/tint/utils/text/color_mode.h new file mode 100644 index 000000000..c4c5b5e9d --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/color_mode.h @@ -0,0 +1,52 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_COLOR_MODE_H_ +#define SRC_TINT_UTILS_TEXT_COLOR_MODE_H_ + +#include +#include + +/// Forward declarations +namespace tint { +class StyledTextPrinter; +} + +namespace tint { + +/// An enumerator of color-output modes +enum class ColorMode : uint8_t { kPlain, kDark, kLight }; + +/// @returns the default ColorMode when no mode is specified. +ColorMode ColorModeDefault(); + +/// @returns an appropriate printer for the given color mode. +std::unique_ptr CreatePrinter(ColorMode mode); + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_COLOR_MODE_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/string.cc b/3rdparty/dawn/src/tint/utils/text/string.cc new file mode 100644 index 000000000..47d7a90ce --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/string.cc @@ -0,0 +1,106 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "src/tint/utils/containers/transform.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/text/string.h" +#include "src/tint/utils/text/styled_text.h" + +namespace tint { + +size_t Distance(std::string_view str_a, std::string_view str_b) { + const auto len_a = str_a.size(); + const auto len_b = str_b.size(); + + Vector mat; + mat.Resize((len_a + 1) * (len_b + 1)); + + auto at = [&](size_t a, size_t b) -> size_t& { return mat[a + b * (len_a + 1)]; }; + + at(0, 0) = 0; + for (size_t a = 1; a <= len_a; a++) { + at(a, 0) = a; + } + for (size_t b = 1; b <= len_b; b++) { + at(0, b) = b; + } + for (size_t b = 1; b <= len_b; b++) { + for (size_t a = 1; a <= len_a; a++) { + bool eq = str_a[a - 1] == str_b[b - 1]; + at(a, b) = std::min({ + at(a - 1, b) + 1, + at(a, b - 1) + 1, + at(a - 1, b - 1) + (eq ? 0 : 1), + }); + } + } + return at(len_a, len_b); +} + +void SuggestAlternatives(std::string_view got, + Slice strings, + StyledText& ss, + const SuggestAlternativeOptions& options /* = {} */) { + // If the string typed was within kSuggestionDistance of one of the possible enum values, + // suggest that. Don't bother with suggestions if the string was extremely long. + auto default_style = ss.Style(); + constexpr size_t kSuggestionDistance = 5; + constexpr size_t kSuggestionMaxLength = 64; + if (!got.empty() && got.size() < kSuggestionMaxLength) { + size_t candidate_dist = kSuggestionDistance; + std::string_view candidate; + for (auto str : strings) { + auto dist = tint::Distance(str, got); + if (dist < candidate_dist) { + candidate = str; + candidate_dist = dist; + } + } + if (!candidate.empty()) { + ss << "Did you mean " << options.alternatives_style << options.prefix << candidate + << default_style << "?"; + if (options.list_possible_values) { + ss << "\n"; + } + } + } + + if (options.list_possible_values) { + // List all the possible enumerator values + ss << "Possible values: "; + for (auto str : strings) { + if (str != strings[0]) { + ss << ", "; + } + ss << options.alternatives_style << options.prefix << str << default_style; + } + } +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/string.h b/3rdparty/dawn/src/tint/utils/text/string.h new file mode 100644 index 000000000..c2f9a1b88 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/string.h @@ -0,0 +1,169 @@ +// Copyright 2021 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_STRING_H_ +#define SRC_TINT_UTILS_TEXT_STRING_H_ + +#include +#include + +#include "src/tint/utils/containers/slice.h" +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/text_style.h" + +/// Forward declaration +namespace tint { +class StyledText; +} + +namespace tint { + +/// @param value the boolean value to be printed as a string +/// @returns value printed as a string via the stream `<<` operator +inline std::string ToString(bool value) { + return value ? "true" : "false"; +} + +/// @param value the value to be printed as a string +/// @returns value printed as a string via the stream `<<` operator +template +std::string ToString(const T& value) { + StringStream s; + s << value; + return s.str(); +} + +/// @param value the variant to be printed as a string +/// @returns value printed as a string via the stream `<<` operator +template +std::string ToString(const std::variant& value) { + StringStream s; + s << std::visit([&](auto& v) { return ToString(v); }, value); + return s.str(); +} + +/// @param a the first string +/// @param b the second string +/// @returns the Levenshtein distance between @p a and @p b +size_t Distance(std::string_view a, std::string_view b); + +/// Options for SuggestAlternatives() +struct SuggestAlternativeOptions { + /// The prefix to apply to the strings when printing + std::string_view prefix; + /// The text style for alternatives + TextStyle alternatives_style = style::Code; + /// List all the possible values + bool list_possible_values = true; +}; + +/// Suggest alternatives for an unrecognized string from a list of possible values. +/// @param got the unrecognized string +/// @param strings the list of possible values +/// @param ss the stream to write the suggest and list of possible values to +/// @param options options for the suggestion +void SuggestAlternatives(std::string_view got, + Slice strings, + StyledText& ss, + const SuggestAlternativeOptions& options = {}); + +/// @param str the input string +/// @param pred the predicate function +/// @return @p str with characters passing the predicate function @p pred removed from the start of +/// the string. +template +std::string_view TrimLeft(std::string_view str, PREDICATE&& pred) { + while (!str.empty() && pred(str.front())) { + str = str.substr(1); + } + return str; +} + +/// @param str the input string +/// @param pred the predicate function +/// @return @p str with characters passing the predicate function @p pred removed from the end of +/// the string. +template +std::string_view TrimRight(std::string_view str, PREDICATE&& pred) { + while (!str.empty() && pred(str.back())) { + str = str.substr(0, str.length() - 1); + } + return str; +} + +/// @param str the input string +/// @param suffix the suffix to trim from @p str +/// @return @p str with the suffix removed, if @p str has the suffix. +inline std::string_view TrimSuffix(std::string_view str, std::string_view suffix) { + return str.ends_with(suffix) ? str.substr(0, str.length() - suffix.length()) : str; +} + +/// @param str the input string +/// @return @p str with all whitespace (' ') removed from the start and end of the string. +inline std::string_view TrimSpace(std::string_view str) { + auto IsSpace = [](char c) -> bool { + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; + }; + return TrimLeft(TrimRight(str, IsSpace), IsSpace); +} + +/// @param str the input string +/// @param delimiter the delimiter +/// @return @p str split at each occurrence of @p delimiter +inline Vector Split(std::string_view str, std::string_view delimiter) { + Vector out; + while (str.length() > delimiter.length()) { + auto pos = str.find(delimiter); + if (pos == std::string_view::npos) { + break; + } + out.Push(str.substr(0, pos)); + str = str.substr(pos + delimiter.length()); + } + out.Push(str); + return out; +} + +/// @param parts the input parts +/// @param delimiter the delimiter +/// @return @p parts joined as a string, delimited with @p delimiter +template +inline std::string Join(const Vector& parts, std::string_view delimiter) { + StringStream s; + for (auto& part : parts) { + if (part != parts.Front()) { + s << delimiter; + } + s << part; + } + return s.str(); +} + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_STRING_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/string_stream.cc b/3rdparty/dawn/src/tint/utils/text/string_stream.cc new file mode 100644 index 000000000..daccc5213 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/string_stream.cc @@ -0,0 +1,80 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/text/string_stream.h" + +namespace tint { + +StringStream::StringStream() { + Reset(); +} + +StringStream::StringStream(const StringStream& other) { + Reset(); + sstream_ << other.str(); +} + +StringStream::~StringStream() = default; + +StringStream& StringStream::operator=(const StringStream& other) { + Reset(); + return *this << other.str(); +} + +void StringStream::Reset() { + sstream_.str(""); + sstream_.clear(); + sstream_.flags(sstream_.flags() | std::ios_base::showpoint | std::ios_base::fixed); + sstream_.imbue(std::locale::classic()); + sstream_.precision(9); +} + +StringStream& operator<<(StringStream& out, CodePoint code_point) { + if (code_point < 0x7f) { + // See https://en.cppreference.com/w/cpp/language/escape + switch (code_point) { + case '\a': + return out << R"('\a')"; + case '\b': + return out << R"('\b')"; + case '\f': + return out << R"('\f')"; + case '\n': + return out << R"('\n')"; + case '\r': + return out << R"('\r')"; + case '\t': + return out << R"('\t')"; + case '\v': + return out << R"('\v')"; + } + return out << "'" << static_cast(code_point) << "'"; + } + return out << "'U+" << std::hex << code_point.value << "'"; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/string_stream.h b/3rdparty/dawn/src/tint/utils/text/string_stream.h new file mode 100644 index 000000000..49b3d2f7c --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/string_stream.h @@ -0,0 +1,218 @@ +// Copyright 2023 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_STRING_STREAM_H_ +#define SRC_TINT_UTILS_TEXT_STRING_STREAM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/tint/utils/text/unicode.h" + +namespace tint { + +/// Stringstream wrapper which automatically resets the locale and sets floating point emission +/// settings needed for Tint. +class StringStream { + using SetWRetTy = decltype(std::setw(std::declval())); + using SetPrecisionRetTy = decltype(std::setprecision(std::declval())); + using SetFillRetTy = decltype(std::setfill(std::declval())); + + /// Evaluates to true if `T` is the return type of std::setw, std:setprecision or std::setfill. + template + static constexpr bool IsSetType = std::is_same_v> || + std::is_same_v> || + std::is_same_v>; + + public: + /// Constructor + StringStream(); + /// Copy constructor + StringStream(const StringStream&); + /// Destructor + ~StringStream(); + + /// Copy assignment operator + StringStream& operator=(const StringStream&); + + /// @returns the format flags for the stream + std::ios_base::fmtflags flags() const { return sstream_.flags(); } + + /// @param flags the flags to set + /// @returns the original format flags + std::ios_base::fmtflags flags(std::ios_base::fmtflags flags) { return sstream_.flags(flags); } + + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + template >, bool> = true> + StringStream& operator<<(T&& value) { + return EmitValue(std::forward(value)); + } + + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + StringStream& operator<<(const char* value) { return EmitValue(value); } + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + StringStream& operator<<(const std::string& value) { return EmitValue(value); } + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + StringStream& operator<<(std::string_view value) { return EmitValue(value); } + + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + StringStream& operator<<(const void* value) { return EmitValue(value); } + + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + template >, bool> = true> + StringStream& operator<<(T&& value) { + return EmitFloat(std::forward(value)); + } + + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + template + StringStream& EmitValue(T&& value) { + sstream_ << std::forward(value); + return *this; + } + + /// Emit `value` to the stream + /// @param value the value to emit + /// @returns a reference to this + template + StringStream& EmitFloat(const T& value) { + // Try printing the float in fixed point, with a smallish limit on the precision + std::stringstream fixed; + fixed.flags(fixed.flags() | std::ios_base::showpoint | std::ios_base::fixed); + fixed.imbue(std::locale::classic()); + fixed.precision(20); + fixed << value; + + std::string str = fixed.str(); + + // If this string can be parsed without loss of information, use it. + // (Use double here to dodge a bug in older libc++ versions which would incorrectly read + // back FLT_MAX as INF.) + double roundtripped; + fixed >> roundtripped; + + // Strip trailing zeros from the number. + auto float_equal_no_warning = std::equal_to(); + if (float_equal_no_warning(value, static_cast(roundtripped))) { + while (str.length() >= 2 && str[str.size() - 1] == '0' && str[str.size() - 2] != '.') { + str.pop_back(); + } + + sstream_ << str; + return *this; + } + + // Resort to scientific, with the minimum precision needed to preserve the whole float + std::stringstream sci; + sci.imbue(std::locale::classic()); + sci.precision(std::numeric_limits::max_digits10); + sci << value; + sstream_ << sci.str(); + + return *this; + } + + /// Swaps streams + /// @param other stream to swap too + void swap(StringStream& other) { sstream_.swap(other.sstream_); } + + /// repeat queues the character c to be written to the printer n times. + /// @param c the character to print `n` times + /// @param n the number of times to print character `c` + void repeat(char c, size_t n) { std::fill_n(std::ostream_iterator(sstream_), n, c); } + + /// The callback to emit a `endl` to the stream + using StdEndl = std::ostream& (*)(std::ostream&); + + /// @param manipulator the callback to emit too + /// @returns a reference to this + StringStream& operator<<(StdEndl manipulator) { + // call the function, and return it's value + manipulator(sstream_); + return *this; + } + + /// @param manipulator the callback to emit too + /// @returns a reference to this + StringStream& operator<<(decltype(std::hex) manipulator) { + // call the function, and return it's value + manipulator(sstream_); + return *this; + } + + /// @param value the value to emit + /// @returns a reference to this + template , int> = 0> + StringStream& operator<<(T&& value) { + // call the function, and return it's value + sstream_ << std::forward(value); + return *this; + } + + /// @returns the number of UTF-8 code units (bytes) have been written to the string. + size_t Length() { return static_cast(sstream_.tellp()); } + + /// @returns the string contents of the stream + std::string str() const { return sstream_.str(); } + + private: + void Reset(); + std::stringstream sstream_; +}; + +/// Writes the CodePoint to the stream. +/// @param out the stream to write to +/// @param codepoint the CodePoint to write +/// @returns out so calls can be chained +StringStream& operator<<(StringStream& out, CodePoint codepoint); + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_STRING_STREAM_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text.cc b/3rdparty/dawn/src/tint/utils/text/styled_text.cc new file mode 100644 index 000000000..b6ad72ec2 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text.cc @@ -0,0 +1,100 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/text/styled_text.h" +#include +#include "src/tint/utils/text/styled_text_printer.h" +#include "src/tint/utils/text/text_style.h" + +namespace tint { + +StyledText::StyledText() = default; + +StyledText::StyledText(const StyledText&) = default; + +StyledText::StyledText(const std::string& text) { + stream_ << text; +} + +StyledText::StyledText(std::string_view text) { + stream_ << text; +} + +StyledText::StyledText(StyledText&&) = default; + +StyledText& StyledText::operator=(const StyledText& other) = default; + +StyledText& StyledText::operator=(std::string_view text) { + Clear(); + return *this << text; +} + +void StyledText::Clear() { + *this = StyledText{}; +} + +StyledText& StyledText::SetStyle(TextStyle style) { + if (spans_.Back().style == style) { + return *this; + } + if (spans_.Back().length == 0) { + spans_.Pop(); + } + if (spans_.IsEmpty() || spans_.Back().style != style) { + spans_.Push(Span{style}); + } + return *this; +} + +std::string StyledText::Plain() const { + StringStream ss; + bool is_code_no_quote = false; + Walk([&](std::string_view text, TextStyle style) { + if (is_code_no_quote != (style.IsCode() && !style.IsNoQuote())) { + ss << "'"; + } + is_code_no_quote = style.IsCode() && !style.IsNoQuote(); + + ss << text; + }); + if (is_code_no_quote) { + ss << "'"; + } + return ss.str(); +} + +void StyledText::Append(const StyledText& other) { + other.Walk([&](std::string_view text, TextStyle style) { *this << style << text; }); +} + +StyledText& StyledText::Repeat(char c, size_t n) { + stream_.repeat(c, n); + spans_.Back().length += n; + return *this; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text.h b/3rdparty/dawn/src/tint/utils/text/styled_text.h new file mode 100644 index 000000000..556099bf6 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text.h @@ -0,0 +1,154 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_STYLED_TEXT_H_ +#define SRC_TINT_UTILS_TEXT_STYLED_TEXT_H_ + +#include +#include +#include +#include +#include + +#include "src/tint/utils/containers/vector.h" +#include "src/tint/utils/text/string_stream.h" +#include "src/tint/utils/text/text_style.h" + +// Forward declarations +namespace tint { +class StyledTextPrinter; +} + +namespace tint { + +/// StyledText is a string builder with support for styled text spans. +class StyledText { + public: + /// Constructor - empty string + StyledText(); + + /// Copy constructor + StyledText(const StyledText&); + + /// Constructor from unstyled text + explicit StyledText(const std::string&); + + /// Constructor from unstyled text + explicit StyledText(std::string_view); + + /// Move constructor + StyledText(StyledText&&); + + /// Assignment copy operator + StyledText& operator=(const StyledText& other); + + /// Assignment operator from unstyled text + StyledText& operator=(std::string_view text); + + /// Clears the text and restore the default style + void Clear(); + + /// @returns the TextStyle of all future writes to this StyledText + TextStyle Style() const { return spans_.Back().style; } + + /// Sets the style for all future writes to this StyledText + StyledText& SetStyle(TextStyle style); + + /// @returns the unstyled text. + std::string Plain() const; + + /// Appends the styled text of @p other to this StyledText. + /// @note: Unlike `operator<<(const StyledText&)`, this StyledText's previous style will *not* + /// be automatically restored. + void Append(const StyledText& other); + + /// repeat queues the character @p c to be written to the StyledText n times. + /// @param c the character to print @p n times + /// @param n the number of times to print character @p c + /// @returns this StyledText so calls can be chained. + StyledText& Repeat(char c, size_t n); + + /// operator<<() appends @p value to this StyledText. + /// @p value which is one of: + /// * a TextStyle, which sets the style of all future appends. Note that this fully replaces + /// the old style (no style combinations / overlays). + /// * a ScopedTextStyle, which will will use the span's style for each value, and then this + /// StyledText's previous style will be restored. + /// * a StyledText, which will be appended to this StyledText, and then this StyledText's + /// previous style will be restored. + /// * any other type will be stringified and appended to this StyledText using the current + /// TextStyle. + template + StyledText& operator<<(VALUE&& value) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + SetStyle(std::forward(value)); + } else if constexpr (std::is_same_v) { + auto old_style = Style(); + Append(value); + *this << old_style; + } else if constexpr (IsScopedTextStyle) { + auto old_style = Style(); + std::apply([&](auto&&... values) { ((*this << value.style << values), ...); }, + value.values); + *this << old_style; + } else { + size_t offset = stream_.Length(); + stream_ << value; + spans_.Back().length += stream_.Length() - offset; + } + return *this; + } + + /// Walk calls @p callback with each styled span in the StyledText. + /// @param callback a function with the signature: void(std::string_view, TextStyle) + template + void Walk(CB&& callback) const { + std::string text = stream_.str(); + size_t offset = 0; + for (auto& span : spans_) { + callback(text.substr(offset, span.length), span.style); + offset += span.length; + } + } + + /// @returns the number of UTF-8 code units (bytes) have been written to the string. + size_t Length() { return stream_.Length(); } + + private: + struct Span { + TextStyle style; + size_t length = 0; + }; + + StringStream stream_; + Vector spans_{Span{}}; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_STYLED_TEXT_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text_printer.cc b/3rdparty/dawn/src/tint/utils/text/styled_text_printer.cc new file mode 100644 index 000000000..496f8b07b --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text_printer.cc @@ -0,0 +1,66 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include + +#include "src/tint/utils/system/terminal.h" +#include "src/tint/utils/text/styled_text_printer.h" + +namespace tint { +namespace { + +class Plain : public StyledTextPrinter { + public: + explicit Plain(FILE* f) : file_(f) {} + + void Print(const StyledText& text) override { + auto plain = text.Plain(); + fwrite(plain.data(), 1, plain.size(), file_); + } + + private: + FILE* const file_; +}; + +} // namespace + +std::unique_ptr StyledTextPrinter::CreatePlain(FILE* out) { + return std::make_unique(out); +} +std::unique_ptr StyledTextPrinter::Create(FILE* out) { + bool is_dark = TerminalIsDark(out).value_or(true); + return Create(out, is_dark ? StyledTextTheme::kDefaultDark : StyledTextTheme::kDefaultLight); +} + +StyledTextPrinter::~StyledTextPrinter() = default; + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text_printer.h b/3rdparty/dawn/src/tint/utils/text/styled_text_printer.h new file mode 100644 index 000000000..a22453766 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text_printer.h @@ -0,0 +1,83 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_STYLED_TEXT_PRINTER_H_ +#define SRC_TINT_UTILS_TEXT_STYLED_TEXT_PRINTER_H_ + +#include +#include + +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/styled_text_theme.h" + +/// Forward declarations +namespace tint { +class TextStyle; +} + +namespace tint { + +/// StyledTextPrinter is the interface for printing text with a style. +class StyledTextPrinter { + public: + /// @returns a Printer using the default theme. + /// @param out the file to print to. + static std::unique_ptr Create(FILE* out); + + /// @returns a Printer using the theme @p theme. + /// @param out the file to print to. + /// @param theme the custom theme to use. + static std::unique_ptr Create(FILE* out, const StyledTextTheme& theme); + + /// @returns a Printer that emits non-styled text. + /// @param out the file to print to. + static std::unique_ptr CreatePlain(FILE* out); + + /// Enumerator of ANSI terminal color support. + enum class ANSIColors { + k8Bit, // Palette of 256 colors 'xterm-256color' + k24Bit, // 8-bit per [R,G,B] + }; + + /// @returns a Printer that uses ANSI escape sequences and theme @p theme. + /// @param out the file to print to. + /// @param theme the custom theme to use. + static std::unique_ptr CreateANSI(FILE* out, + const StyledTextTheme& theme, + ANSIColors colors); + + /// Destructor + virtual ~StyledTextPrinter(); + + /// Prints the styled text to the printer. + /// @param text the text to print. + virtual void Print(const StyledText& text) = 0; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_STYLED_TEXT_PRINTER_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text_printer_ansi.cc b/3rdparty/dawn/src/tint/utils/text/styled_text_printer_ansi.cc new file mode 100644 index 000000000..03475ad8d --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text_printer_ansi.cc @@ -0,0 +1,241 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/439062058): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + +#include +#include + +#include "src/tint/utils/containers/hashmap.h" +#include "src/tint/utils/text/styled_text.h" +#include "src/tint/utils/text/styled_text_printer.h" +#include "src/tint/utils/text/styled_text_theme.h" +#include "src/tint/utils/text/text_style.h" + +namespace tint { +namespace { + +template +bool Equal(const std::optional& lhs, const std::optional& rhs) { + if (lhs.has_value() != rhs.has_value()) { + return false; + } + if (!lhs.has_value()) { + return true; + } + return lhs.value() == rhs.value(); +} + +#define ESCAPE "\u001b" + +class Printer24Bit : public StyledTextPrinter { + public: + Printer24Bit(FILE* f, const StyledTextTheme& t) : file_(f), theme_(t) {} + + void Print(const StyledText& style_text) override { + StyledTextTheme::Attributes current; + + style_text.Walk([&](std::string_view text, TextStyle text_style) { + auto style = theme_.Get(text_style); + if (!Equal(current.foreground, style.foreground)) { + current.foreground = style.foreground; + if (current.foreground.has_value()) { + fprintf(file_, ESCAPE "[38;2;%d;%d;%dm", // + static_cast(style.foreground->r), + static_cast(style.foreground->g), + static_cast(style.foreground->b)); + } else { + fprintf(file_, ESCAPE "[39m"); + } + } + if (!Equal(current.background, style.background)) { + current.background = style.background; + if (current.background.has_value()) { + fprintf(file_, ESCAPE "[48;2;%d;%d;%dm", // + static_cast(style.background->r), + static_cast(style.background->g), + static_cast(style.background->b)); + } else { + fprintf(file_, ESCAPE "[49m"); + } + } + if (!Equal(current.underlined, style.underlined)) { + current.underlined = style.underlined; + if (current.underlined == true) { + fprintf(file_, ESCAPE "[4m"); + } else { + fprintf(file_, ESCAPE "[24m"); + } + } + if (!Equal(current.bold, style.bold)) { + current.bold = style.bold; + if (current.bold == true) { + fprintf(file_, ESCAPE "[1m"); + } else { + fprintf(file_, ESCAPE "[22m"); + } + } + fwrite(text.data(), 1, text.size(), file_); + }); + fprintf(file_, ESCAPE "[m"); + fflush(file_); + } + + private: + FILE* const file_; + const StyledTextTheme& theme_; +}; + +class Printer8Bit : public StyledTextPrinter { + public: + static constexpr std::array kPalette = { + 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xc0c0c0, 0x808080, + 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff, 0x000000, 0x00005f, + 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, 0x005f87, 0x005faf, 0x005fd7, + 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af, 0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, + 0x00af87, 0x00afaf, 0x00afd7, 0x00afff, 0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7, + 0x00d7ff, 0x00ff00, 0x00ff5f, 0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, + 0x5f0087, 0x5f00af, 0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, 0x5f5f87, 0x5f5faf, 0x5f5fd7, + 0x5f5fff, 0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f, + 0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af, 0x5fd7d7, + 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff, 0x870000, 0x87005f, + 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f, 0x875f87, 0x875faf, 0x875fd7, + 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af, 0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, + 0x87af87, 0x87afaf, 0x87afd7, 0x87afff, 0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, + 0x87d7ff, 0x87ff00, 0x87ff5f, 0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, + 0xaf0087, 0xaf00af, 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, + 0xaf5fff, 0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f, + 0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af, 0xafd7d7, + 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff, 0xd70000, 0xd7005f, + 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f, 0xd75f87, 0xd75faf, 0xd75fd7, + 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af, 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, + 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff, 0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, + 0xd7d7ff, 0xd7ff00, 0xd7ff5f, 0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, + 0xff0087, 0xff00af, 0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, + 0xff5fff, 0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f, + 0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af, 0xffd7d7, + 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff, 0x080808, 0x121212, + 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e, 0x585858, 0x606060, 0x666666, + 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, + 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee, + }; + + Printer8Bit(FILE* f, const StyledTextTheme& t) : file_(f), theme_(t) {} + + void Print(const StyledText& style_text) override { + StyledTextTheme::Attributes current; + + style_text.Walk([&](std::string_view text, TextStyle text_style) { + auto style = theme_.Get(text_style); + if (!Equal(current.foreground, style.foreground)) { + current.foreground = style.foreground; + if (current.foreground.has_value()) { + uint8_t color = Quantize(*style.foreground); + fprintf(file_, ESCAPE "[38;5;%dm", static_cast(color)); + } else { + fprintf(file_, ESCAPE "[39m"); + } + } + if (!Equal(current.background, style.background)) { + current.background = style.background; + if (current.background.has_value()) { + uint8_t color = Quantize(*style.background); + fprintf(file_, ESCAPE "[48;5;%dm", static_cast(color)); + } else { + fprintf(file_, ESCAPE "[49m"); + } + } + if (!Equal(current.underlined, style.underlined)) { + current.underlined = style.underlined; + if (current.underlined == true) { + fprintf(file_, ESCAPE "[4m"); + } else { + fprintf(file_, ESCAPE "[24m"); + } + } + if (!Equal(current.bold, style.bold)) { + current.bold = style.bold; + if (current.bold == true) { + fprintf(file_, ESCAPE "[1m"); + } else { + fprintf(file_, ESCAPE "[22m"); + } + } + fwrite(text.data(), 1, text.size(), file_); + }); + fprintf(file_, ESCAPE "[m"); + fflush(file_); + } + + private: + uint8_t Quantize(const StyledTextTheme::Color& color) { + return colors_.GetOrAdd(color, [&] { + uint8_t best_color = 0; + int best_score = std::numeric_limits::max(); + for (size_t i = 0; i < 256; i++) { + int r = static_cast((kPalette[i] >> 16) & 0xff); + int g = static_cast((kPalette[i] >> 8) & 0xff); + int b = static_cast((kPalette[i] >> 0) & 0xff); + int diff = std::abs(r - static_cast(color.r)) + + std::abs(g - static_cast(color.g)) + + std::abs(b - static_cast(color.b)); + if (diff == 0) { + return static_cast(i); + } + if (diff < best_score) { + best_score = diff; + best_color = static_cast(i); + } + } + return best_color; + }); + } + + FILE* const file_; + const StyledTextTheme& theme_; + Hashmap colors_; +}; +} // namespace + +std::unique_ptr StyledTextPrinter::CreateANSI(FILE* out, + const StyledTextTheme& theme, + ANSIColors colors) { + switch (colors) { + case ANSIColors::k24Bit: + return std::make_unique(out, theme); + case ANSIColors::k8Bit: + return std::make_unique(out, theme); + } + + // Should be unreachable. + return std::make_unique(out, theme); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text_theme.cc b/3rdparty/dawn/src/tint/utils/text/styled_text_theme.cc new file mode 100644 index 000000000..0b209a1bc --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text_theme.cc @@ -0,0 +1,370 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/text/styled_text_theme.h" +#include "src/tint/utils/text/text_style.h" + +namespace tint { + +const StyledTextTheme StyledTextTheme::kDefaultDark{ + /* compare_match */ StyledTextTheme::Attributes{ + /* foreground */ std::nullopt, + /* background */ Color{20, 100, 20}, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* compare_mismatch */ + StyledTextTheme::Attributes{ + /* foreground */ std::nullopt, + /* background */ Color{120, 20, 20}, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_success */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 200, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_warning */ + StyledTextTheme::Attributes{ + /* foreground */ Color{200, 200, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_failure */ + StyledTextTheme::Attributes{ + /* foreground */ Color{200, 0, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_fatal */ + StyledTextTheme::Attributes{ + /* foreground */ Color{200, 0, 200}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_code */ + StyledTextTheme::Attributes{ + /* foreground */ Color{212, 212, 212}, + /* background */ Color{43, 43, 43}, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_keyword */ + StyledTextTheme::Attributes{ + /* foreground */ Color{197, 134, 192}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_variable */ + StyledTextTheme::Attributes{ + /* foreground */ Color{156, 220, 254}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_type */ + StyledTextTheme::Attributes{ + /* foreground */ Color{78, 201, 176}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_function */ + StyledTextTheme::Attributes{ + /* foreground */ Color{220, 220, 170}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_enum */ + StyledTextTheme::Attributes{ + /* foreground */ Color{79, 193, 255}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_literal */ + StyledTextTheme::Attributes{ + /* foreground */ Color{181, 206, 168}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_attribute */ + StyledTextTheme::Attributes{ + /* foreground */ Color{156, 220, 254}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_comment */ + StyledTextTheme::Attributes{ + /* foreground */ Color{106, 153, 85}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_label */ + StyledTextTheme::Attributes{ + /* foreground */ Color{180, 140, 140}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_instruction */ + StyledTextTheme::Attributes{ + /* foreground */ Color{220, 220, 170}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_squiggle */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 200, 255}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, +}; + +const StyledTextTheme StyledTextTheme::kDefaultLight{ + /* compare_match */ StyledTextTheme::Attributes{ + /* foreground */ std::nullopt, + /* background */ Color{190, 240, 190}, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* compare_mismatch */ + StyledTextTheme::Attributes{ + /* foreground */ std::nullopt, + /* background */ Color{240, 190, 190}, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_success */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 200, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_warning */ + StyledTextTheme::Attributes{ + /* foreground */ Color{200, 200, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_failure */ + StyledTextTheme::Attributes{ + /* foreground */ Color{200, 0, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* severity_fatal */ + StyledTextTheme::Attributes{ + /* foreground */ Color{200, 0, 200}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_code */ + StyledTextTheme::Attributes{ + /* foreground */ Color{10, 10, 10}, + /* background */ Color{248, 248, 248}, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_keyword */ + StyledTextTheme::Attributes{ + /* foreground */ Color{175, 0, 219}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_variable */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 16, 128}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_type */ + StyledTextTheme::Attributes{ + /* foreground */ Color{38, 127, 153}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_function */ + StyledTextTheme::Attributes{ + /* foreground */ Color{121, 94, 38}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_enum */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 112, 193}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_literal */ + StyledTextTheme::Attributes{ + /* foreground */ Color{9, 134, 88}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_attribute */ + StyledTextTheme::Attributes{ + /* foreground */ Color{156, 220, 254}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_comment */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 128, 0}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_label */ + StyledTextTheme::Attributes{ + /* foreground */ Color{180, 140, 140}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_instruction */ + StyledTextTheme::Attributes{ + /* foreground */ Color{121, 94, 38}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, + /* kind_squiggle */ + StyledTextTheme::Attributes{ + /* foreground */ Color{0, 200, 255}, + /* background */ std::nullopt, + /* bold */ std::nullopt, + /* underlined */ std::nullopt, + }, +}; + +StyledTextTheme::Attributes StyledTextTheme::Get(TextStyle text_style) const { + Attributes out; + out.bold = false; + out.underlined = false; + + auto apply = [&](const Attributes& in) { + if (in.foreground) { + out.foreground = in.foreground; + } + if (in.background) { + out.background = in.background; + } + if (in.bold) { + out.bold = in.bold; + } + if (in.underlined) { + out.underlined = in.underlined; + } + }; + + if (text_style.HasSeverity()) { + if (text_style.IsSuccess()) { + apply(severity_success); + } else if (text_style.IsWarning()) { + apply(severity_warning); + } else if (text_style.IsError()) { + apply(severity_failure); + } else if (text_style.IsFatal()) { + apply(severity_fatal); + } + } + + if (text_style.HasKind()) { + if (text_style.IsCode()) { + apply(kind_code); + + if (text_style.IsKeyword()) { + apply(kind_keyword); + } else if (text_style.IsVariable()) { + apply(kind_variable); + } else if (text_style.IsType()) { + apply(kind_type); + } else if (text_style.IsFunction()) { + apply(kind_function); + } else if (text_style.IsEnum()) { + apply(kind_enum); + } else if (text_style.IsLiteral()) { + apply(kind_literal); + } else if (text_style.IsAttribute()) { + apply(kind_attribute); + } else if (text_style.IsComment()) { + apply(kind_comment); + } else if (text_style.IsLabel()) { + apply(kind_label); + } else if (text_style.IsInstruction()) { + apply(kind_instruction); + } + } + if (text_style.IsSquiggle()) { + apply(kind_squiggle); + } + } + + if (text_style.HasCompare()) { + if (text_style.IsMatch()) { + apply(compare_match); + } else { + apply(compare_mismatch); + } + } + + if (text_style.IsBold()) { + out.bold = true; + } + if (text_style.IsUnderlined()) { + out.underlined = true; + } + + return out; +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/styled_text_theme.h b/3rdparty/dawn/src/tint/utils/text/styled_text_theme.h new file mode 100644 index 000000000..a184b5548 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/styled_text_theme.h @@ -0,0 +1,119 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_STYLED_TEXT_THEME_H_ +#define SRC_TINT_UTILS_TEXT_STYLED_TEXT_THEME_H_ + +#include +#include + +#include "src/tint/utils/math/hash.h" + +/// Forward declarations +namespace tint { +class TextStyle; +} + +namespace tint { + +/// StyledTextTheme describes the display theming for TextStyles +struct StyledTextTheme { + /// The default dark theme + static const StyledTextTheme kDefaultDark; + /// The default light theme + static const StyledTextTheme kDefaultLight; + + /// Color holds a 24-bit RGB color + struct Color { + uint8_t r = 0; + uint8_t g = 0; + uint8_t b = 0; + + /// Equality operator + bool operator==(const Color& other) const { + return r == other.r && g == other.g && b == other.b; + } + /// @returns a hash code of this Color + tint::HashCode HashCode() const { return Hash(r, g, b); } + }; + + /// Attributes holds a number of optional attributes for a style of text. + /// Attributes that are std::nullopt do not change the default style. + struct Attributes { + std::optional foreground; + std::optional background; + std::optional bold; + std::optional underlined; + }; + + /// @returns Attributes from the text style @p text_style + Attributes Get(TextStyle text_style) const; + + /// The theme's attributes for a compare-match + Attributes compare_match; + /// The theme's attributes for a compare-mismatch + Attributes compare_mismatch; + + /// The theme's attributes for a success severity + Attributes severity_success; + /// The theme's attributes for a warning severity + Attributes severity_warning; + /// The theme's attributes for a failure severity + Attributes severity_failure; + /// The theme's attributes for a fatal severity + Attributes severity_fatal; + + /// The theme's attributes for a code text style + Attributes kind_code; + /// The theme's attributes for a keyword token. This is applied on top #kind_code. + Attributes kind_keyword; + /// The theme's attributes for a variable token. This is applied on top #kind_code. + Attributes kind_variable; + /// The theme's attributes for a type token. This is applied on top #kind_code. + Attributes kind_type; + /// The theme's attributes for a function token. This is applied on top #kind_code. + Attributes kind_function; + /// The theme's attributes for a enum token. This is applied on top #kind_code. + Attributes kind_enum; + /// The theme's attributes for a literal token. This is applied on top #kind_code. + Attributes kind_literal; + /// The theme's attributes for a attribute token. This is applied on top #kind_code. + Attributes kind_attribute; + /// The theme's attributes for a comment token. This is applied on top #kind_code. + Attributes kind_comment; + /// The theme's attributes for a label token. This is applied on top #kind_code. + Attributes kind_label; + /// The theme's attributes for a instruction token. This is applied on top #kind_code. + Attributes kind_instruction; + + /// The theme's attributes for a squiggle-highlight. + Attributes kind_squiggle; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_STYLED_TEXT_THEME_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/text_style.h b/3rdparty/dawn/src/tint/utils/text/text_style.h new file mode 100644 index 000000000..2006e5d38 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/text_style.h @@ -0,0 +1,219 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ +#define SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ + +#include +#include +#include + +// Forward declarations +namespace tint { +template +struct ScopedTextStyle; +} + +namespace tint { + +/// TextStyle is a styling that can be applied to span of a StyledText. +class TextStyle { + public: + /// Bits is the integer type used to store the text style. + using Bits = uint16_t; + + /// Bit patterns + + static constexpr Bits kStyleMask /* */ = 0b00'00000'0000'00'111; + static constexpr Bits kStyleUnderlined /* */ = 0b00'00000'0000'00'001; + static constexpr Bits kStyleBold /* */ = 0b00'00000'0000'00'010; + static constexpr Bits kStyleNoQuote /* */ = 0b00'00000'0000'00'100; + + static constexpr Bits kCompareMask /* */ = 0b00'00000'0000'11'000; + static constexpr Bits kCompareMatch /* */ = 0b00'00000'0000'01'000; + static constexpr Bits kCompareMismatch /* */ = 0b00'00000'0000'10'000; + + static constexpr Bits kSeverityMask /* */ = 0b00'00000'1111'00'000; + static constexpr Bits kSeverityDefault /* */ = 0b00'00000'0000'00'000; + static constexpr Bits kSeveritySuccess /* */ = 0b00'00000'0001'00'000; + static constexpr Bits kSeverityWarning /* */ = 0b00'00000'0010'00'000; + static constexpr Bits kSeverityError /* */ = 0b00'00000'0011'00'000; + static constexpr Bits kSeverityFatal /* */ = 0b00'00000'0100'00'000; + + static constexpr Bits kKindMask /* */ = 0b00'11111'0000'00'000; + static constexpr Bits kKindCode /* */ = 0b00'00001'0000'00'000; + static constexpr Bits kKindKeyword /* */ = 0b00'00011'0000'00'000; // includes kKindCode + static constexpr Bits kKindVariable /* */ = 0b00'00101'0000'00'000; // includes kKindCode + static constexpr Bits kKindType /* */ = 0b00'00111'0000'00'000; // includes kKindCode + static constexpr Bits kKindFunction /* */ = 0b00'01001'0000'00'000; // includes kKindCode + static constexpr Bits kKindEnum /* */ = 0b00'01011'0000'00'000; // includes kKindCode + static constexpr Bits kKindLiteral /* */ = 0b00'01101'0000'00'000; // includes kKindCode + static constexpr Bits kKindAttribute /* */ = 0b00'01111'0000'00'000; // includes kKindCode + static constexpr Bits kKindComment /* */ = 0b00'10001'0000'00'000; // includes kKindCode + static constexpr Bits kKindLabel /* */ = 0b00'10011'0000'00'000; // includes kKindCode + static constexpr Bits kKindInstruction /* */ = 0b00'10101'0000'00'000; // includes kKindCode + static constexpr Bits kKindSquiggle /* */ = 0b00'00010'0000'00'000; + + /// Getters + + constexpr bool IsBold() const { return (bits & kStyleBold) != 0; } + constexpr bool IsUnderlined() const { return (bits & kStyleUnderlined) == kStyleUnderlined; } + constexpr bool IsNoQuote() const { return (bits & kStyleNoQuote) == kStyleNoQuote; } + + constexpr bool HasCompare() const { return (bits & kCompareMask) != 0; } + constexpr bool IsMatch() const { return (bits & kCompareMask) == kCompareMatch; } + constexpr bool IsMismatch() const { return (bits & kCompareMask) == kCompareMismatch; } + + constexpr bool HasSeverity() const { return (bits & kSeverityMask) != 0; } + constexpr bool IsSuccess() const { return (bits & kSeverityMask) == kSeveritySuccess; } + constexpr bool IsWarning() const { return (bits & kSeverityMask) == kSeverityWarning; } + constexpr bool IsError() const { return (bits & kSeverityMask) == kSeverityError; } + constexpr bool IsFatal() const { return (bits & kSeverityMask) == kSeverityFatal; } + + constexpr bool HasKind() const { return (bits & kKindMask) != 0; } + constexpr bool IsCode() const { return (bits & kKindCode) == kKindCode; } + constexpr bool IsKeyword() const { return (bits & kKindMask) == kKindKeyword; } + constexpr bool IsVariable() const { return (bits & kKindMask) == kKindVariable; } + constexpr bool IsType() const { return (bits & kKindMask) == kKindType; } + constexpr bool IsFunction() const { return (bits & kKindMask) == kKindFunction; } + constexpr bool IsEnum() const { return (bits & kKindMask) == kKindEnum; } + constexpr bool IsLiteral() const { return (bits & kKindMask) == kKindLiteral; } + constexpr bool IsAttribute() const { return (bits & kKindMask) == kKindAttribute; } + constexpr bool IsComment() const { return (bits & kKindMask) == kKindComment; } + constexpr bool IsLabel() const { return (bits & kKindMask) == kKindLabel; } + constexpr bool IsInstruction() const { return (bits & kKindMask) == kKindInstruction; } + constexpr bool IsSquiggle() const { return (bits & kKindMask) == kKindSquiggle; } + + /// Equality operator + constexpr bool operator==(TextStyle other) const { return bits == other.bits; } + + /// Inequality operator + constexpr bool operator!=(TextStyle other) const { return bits != other.bits; } + + /// @returns the combination of this TextStyle and @p other. + /// If both this TextStyle and @p other have a compare style, severity style or kind style, then + /// the style collision will resolve by using the style of @p other. + constexpr TextStyle operator+(TextStyle other) const { + Bits out = other.bits; + out |= bits & kStyleMask; + if (HasCompare() && !other.HasCompare()) { + out |= bits & kCompareMask; + } + if (HasSeverity() && !other.HasSeverity()) { + out |= bits & kSeverityMask; + } + if (HasKind() && !other.HasKind()) { + out |= bits & kKindMask; + } + return TextStyle{out}; + } + + /// @returns a new ScopedTextStyle of @p values using with this TextStyle + template + inline ScopedTextStyle operator()(VALUES&&... values) const; + + /// The style bit pattern + Bits bits = 0; +}; + +/// ScopedTextStyle is a span of text, styled with a TextStyle +template +struct ScopedTextStyle { + std::tuple values; + TextStyle style; +}; + +template +ScopedTextStyle TextStyle::operator()(VALUES&&... values) const { + return ScopedTextStyle{std::forward_as_tuple(values...), *this}; +} + +namespace detail { +template +struct IsScopedTextStyle : std::false_type {}; +template +struct IsScopedTextStyle > : std::true_type {}; +} // namespace detail + +/// Resolves to true iff T is a ScopedTextStyle. +template +static constexpr bool IsScopedTextStyle = detail::IsScopedTextStyle::value; + +} // namespace tint + +namespace tint::style { + +/// Plain renders text without any styling +static constexpr TextStyle Plain = TextStyle{}; +/// Bold renders text with a heavy weight +static constexpr TextStyle Bold = TextStyle{TextStyle::kStyleBold}; +/// Underlined renders text with an underline +static constexpr TextStyle Underlined = TextStyle{TextStyle::kStyleUnderlined}; +/// Code renders without a single quote when printed as plain text. +static constexpr TextStyle NoQuote = TextStyle{TextStyle::kStyleNoQuote}; +/// Match renders text with the compare-match style +static constexpr TextStyle Match = TextStyle{TextStyle::kCompareMatch}; +/// Mismatch renders text with the compare-mismatch style +static constexpr TextStyle Mismatch = TextStyle{TextStyle::kCompareMismatch}; +/// Success renders text with the styling for a successful status +static constexpr TextStyle Success = TextStyle{TextStyle::kSeveritySuccess}; +/// Warning renders text with the styling for a warning status +static constexpr TextStyle Warning = TextStyle{TextStyle::kSeverityWarning}; +/// Error renders text with the styling for a error status +static constexpr TextStyle Error = TextStyle{TextStyle::kSeverityError}; +/// Fatal renders text with the styling for a fatal status +static constexpr TextStyle Fatal = TextStyle{TextStyle::kSeverityFatal}; +/// Code renders text with a 'code' style +static constexpr TextStyle Code = TextStyle{TextStyle::kKindCode}; +/// Keyword renders text with a 'code' style that represents a 'keyword' token +static constexpr TextStyle Keyword = TextStyle{TextStyle::kKindKeyword}; +/// Variable renders text with a 'code' style that represents a 'variable' token +static constexpr TextStyle Variable = TextStyle{TextStyle::kKindVariable}; +/// Type renders text with a 'code' style that represents a 'type' token +static constexpr TextStyle Type = TextStyle{TextStyle::kKindType}; +/// Function renders text with a 'code' style that represents a 'function' token +static constexpr TextStyle Function = TextStyle{TextStyle::kKindFunction}; +/// Enum renders text with a 'code' style that represents a 'enum' token +static constexpr TextStyle Enum = TextStyle{TextStyle::kKindEnum}; +/// Literal renders text with a 'code' style that represents a 'literal' token +static constexpr TextStyle Literal = TextStyle{TextStyle::kKindLiteral}; +/// Attribute renders text with a 'code' style that represents an 'attribute' token +static constexpr TextStyle Attribute = TextStyle{TextStyle::kKindAttribute}; +/// Comment renders text with a 'code' style that represents an 'comment' token +static constexpr TextStyle Comment = TextStyle{TextStyle::kKindComment}; +/// Label renders text with a 'code' style that represents an 'label' token +static constexpr TextStyle Label = TextStyle{TextStyle::kKindLabel}; +/// Instruction renders text with a 'code' style that represents an 'instruction' token +static constexpr TextStyle Instruction = TextStyle{TextStyle::kKindInstruction}; +/// Squiggle renders text with a squiggle-highlight style (`^^^^^`) +static constexpr TextStyle Squiggle = TextStyle{TextStyle::kKindSquiggle}; + +} // namespace tint::style + +#endif // SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ diff --git a/3rdparty/dawn/src/tint/utils/text/unicode.cc b/3rdparty/dawn/src/tint/utils/text/unicode.cc new file mode 100644 index 000000000..450f81d12 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/unicode.cc @@ -0,0 +1,539 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/text/unicode.h" + +#include +#include + +#include "src/tint/utils/macros/compiler.h" + +namespace tint { +namespace { + +struct CodePointRange { + uint32_t first; // First code point in the interval + uint32_t last; // Last code point in the interval (inclusive) +}; + +inline bool operator<(CodePoint code_point, CodePointRange range) { + return code_point < range.first; +} +inline bool operator<(CodePointRange range, CodePoint code_point) { + return range.last < code_point; +} + +// Interval ranges of all code points in the Unicode 14 XID_Start set +// This array needs to be in ascending order. +constexpr CodePointRange kXIDStartRanges[] = { + {0x00041, 0x0005a}, {0x00061, 0x0007a}, {0x000aa, 0x000aa}, {0x000b5, 0x000b5}, + {0x000ba, 0x000ba}, {0x000c0, 0x000d6}, {0x000d8, 0x000f6}, {0x000f8, 0x002c1}, + {0x002c6, 0x002d1}, {0x002e0, 0x002e4}, {0x002ec, 0x002ec}, {0x002ee, 0x002ee}, + {0x00370, 0x00374}, {0x00376, 0x00377}, {0x0037b, 0x0037d}, {0x0037f, 0x0037f}, + {0x00386, 0x00386}, {0x00388, 0x0038a}, {0x0038c, 0x0038c}, {0x0038e, 0x003a1}, + {0x003a3, 0x003f5}, {0x003f7, 0x00481}, {0x0048a, 0x0052f}, {0x00531, 0x00556}, + {0x00559, 0x00559}, {0x00560, 0x00588}, {0x005d0, 0x005ea}, {0x005ef, 0x005f2}, + {0x00620, 0x0064a}, {0x0066e, 0x0066f}, {0x00671, 0x006d3}, {0x006d5, 0x006d5}, + {0x006e5, 0x006e6}, {0x006ee, 0x006ef}, {0x006fa, 0x006fc}, {0x006ff, 0x006ff}, + {0x00710, 0x00710}, {0x00712, 0x0072f}, {0x0074d, 0x007a5}, {0x007b1, 0x007b1}, + {0x007ca, 0x007ea}, {0x007f4, 0x007f5}, {0x007fa, 0x007fa}, {0x00800, 0x00815}, + {0x0081a, 0x0081a}, {0x00824, 0x00824}, {0x00828, 0x00828}, {0x00840, 0x00858}, + {0x00860, 0x0086a}, {0x00870, 0x00887}, {0x00889, 0x0088e}, {0x008a0, 0x008c9}, + {0x00904, 0x00939}, {0x0093d, 0x0093d}, {0x00950, 0x00950}, {0x00958, 0x00961}, + {0x00971, 0x00980}, {0x00985, 0x0098c}, {0x0098f, 0x00990}, {0x00993, 0x009a8}, + {0x009aa, 0x009b0}, {0x009b2, 0x009b2}, {0x009b6, 0x009b9}, {0x009bd, 0x009bd}, + {0x009ce, 0x009ce}, {0x009dc, 0x009dd}, {0x009df, 0x009e1}, {0x009f0, 0x009f1}, + {0x009fc, 0x009fc}, {0x00a05, 0x00a0a}, {0x00a0f, 0x00a10}, {0x00a13, 0x00a28}, + {0x00a2a, 0x00a30}, {0x00a32, 0x00a33}, {0x00a35, 0x00a36}, {0x00a38, 0x00a39}, + {0x00a59, 0x00a5c}, {0x00a5e, 0x00a5e}, {0x00a72, 0x00a74}, {0x00a85, 0x00a8d}, + {0x00a8f, 0x00a91}, {0x00a93, 0x00aa8}, {0x00aaa, 0x00ab0}, {0x00ab2, 0x00ab3}, + {0x00ab5, 0x00ab9}, {0x00abd, 0x00abd}, {0x00ad0, 0x00ad0}, {0x00ae0, 0x00ae1}, + {0x00af9, 0x00af9}, {0x00b05, 0x00b0c}, {0x00b0f, 0x00b10}, {0x00b13, 0x00b28}, + {0x00b2a, 0x00b30}, {0x00b32, 0x00b33}, {0x00b35, 0x00b39}, {0x00b3d, 0x00b3d}, + {0x00b5c, 0x00b5d}, {0x00b5f, 0x00b61}, {0x00b71, 0x00b71}, {0x00b83, 0x00b83}, + {0x00b85, 0x00b8a}, {0x00b8e, 0x00b90}, {0x00b92, 0x00b95}, {0x00b99, 0x00b9a}, + {0x00b9c, 0x00b9c}, {0x00b9e, 0x00b9f}, {0x00ba3, 0x00ba4}, {0x00ba8, 0x00baa}, + {0x00bae, 0x00bb9}, {0x00bd0, 0x00bd0}, {0x00c05, 0x00c0c}, {0x00c0e, 0x00c10}, + {0x00c12, 0x00c28}, {0x00c2a, 0x00c39}, {0x00c3d, 0x00c3d}, {0x00c58, 0x00c5a}, + {0x00c5d, 0x00c5d}, {0x00c60, 0x00c61}, {0x00c80, 0x00c80}, {0x00c85, 0x00c8c}, + {0x00c8e, 0x00c90}, {0x00c92, 0x00ca8}, {0x00caa, 0x00cb3}, {0x00cb5, 0x00cb9}, + {0x00cbd, 0x00cbd}, {0x00cdd, 0x00cde}, {0x00ce0, 0x00ce1}, {0x00cf1, 0x00cf2}, + {0x00d04, 0x00d0c}, {0x00d0e, 0x00d10}, {0x00d12, 0x00d3a}, {0x00d3d, 0x00d3d}, + {0x00d4e, 0x00d4e}, {0x00d54, 0x00d56}, {0x00d5f, 0x00d61}, {0x00d7a, 0x00d7f}, + {0x00d85, 0x00d96}, {0x00d9a, 0x00db1}, {0x00db3, 0x00dbb}, {0x00dbd, 0x00dbd}, + {0x00dc0, 0x00dc6}, {0x00e01, 0x00e30}, {0x00e32, 0x00e32}, {0x00e40, 0x00e46}, + {0x00e81, 0x00e82}, {0x00e84, 0x00e84}, {0x00e86, 0x00e8a}, {0x00e8c, 0x00ea3}, + {0x00ea5, 0x00ea5}, {0x00ea7, 0x00eb0}, {0x00eb2, 0x00eb2}, {0x00ebd, 0x00ebd}, + {0x00ec0, 0x00ec4}, {0x00ec6, 0x00ec6}, {0x00edc, 0x00edf}, {0x00f00, 0x00f00}, + {0x00f40, 0x00f47}, {0x00f49, 0x00f6c}, {0x00f88, 0x00f8c}, {0x01000, 0x0102a}, + {0x0103f, 0x0103f}, {0x01050, 0x01055}, {0x0105a, 0x0105d}, {0x01061, 0x01061}, + {0x01065, 0x01066}, {0x0106e, 0x01070}, {0x01075, 0x01081}, {0x0108e, 0x0108e}, + {0x010a0, 0x010c5}, {0x010c7, 0x010c7}, {0x010cd, 0x010cd}, {0x010d0, 0x010fa}, + {0x010fc, 0x01248}, {0x0124a, 0x0124d}, {0x01250, 0x01256}, {0x01258, 0x01258}, + {0x0125a, 0x0125d}, {0x01260, 0x01288}, {0x0128a, 0x0128d}, {0x01290, 0x012b0}, + {0x012b2, 0x012b5}, {0x012b8, 0x012be}, {0x012c0, 0x012c0}, {0x012c2, 0x012c5}, + {0x012c8, 0x012d6}, {0x012d8, 0x01310}, {0x01312, 0x01315}, {0x01318, 0x0135a}, + {0x01380, 0x0138f}, {0x013a0, 0x013f5}, {0x013f8, 0x013fd}, {0x01401, 0x0166c}, + {0x0166f, 0x0167f}, {0x01681, 0x0169a}, {0x016a0, 0x016ea}, {0x016ee, 0x016f8}, + {0x01700, 0x01711}, {0x0171f, 0x01731}, {0x01740, 0x01751}, {0x01760, 0x0176c}, + {0x0176e, 0x01770}, {0x01780, 0x017b3}, {0x017d7, 0x017d7}, {0x017dc, 0x017dc}, + {0x01820, 0x01878}, {0x01880, 0x018a8}, {0x018aa, 0x018aa}, {0x018b0, 0x018f5}, + {0x01900, 0x0191e}, {0x01950, 0x0196d}, {0x01970, 0x01974}, {0x01980, 0x019ab}, + {0x019b0, 0x019c9}, {0x01a00, 0x01a16}, {0x01a20, 0x01a54}, {0x01aa7, 0x01aa7}, + {0x01b05, 0x01b33}, {0x01b45, 0x01b4c}, {0x01b83, 0x01ba0}, {0x01bae, 0x01baf}, + {0x01bba, 0x01be5}, {0x01c00, 0x01c23}, {0x01c4d, 0x01c4f}, {0x01c5a, 0x01c7d}, + {0x01c80, 0x01c88}, {0x01c90, 0x01cba}, {0x01cbd, 0x01cbf}, {0x01ce9, 0x01cec}, + {0x01cee, 0x01cf3}, {0x01cf5, 0x01cf6}, {0x01cfa, 0x01cfa}, {0x01d00, 0x01dbf}, + {0x01e00, 0x01f15}, {0x01f18, 0x01f1d}, {0x01f20, 0x01f45}, {0x01f48, 0x01f4d}, + {0x01f50, 0x01f57}, {0x01f59, 0x01f59}, {0x01f5b, 0x01f5b}, {0x01f5d, 0x01f5d}, + {0x01f5f, 0x01f7d}, {0x01f80, 0x01fb4}, {0x01fb6, 0x01fbc}, {0x01fbe, 0x01fbe}, + {0x01fc2, 0x01fc4}, {0x01fc6, 0x01fcc}, {0x01fd0, 0x01fd3}, {0x01fd6, 0x01fdb}, + {0x01fe0, 0x01fec}, {0x01ff2, 0x01ff4}, {0x01ff6, 0x01ffc}, {0x02071, 0x02071}, + {0x0207f, 0x0207f}, {0x02090, 0x0209c}, {0x02102, 0x02102}, {0x02107, 0x02107}, + {0x0210a, 0x02113}, {0x02115, 0x02115}, {0x02118, 0x0211d}, {0x02124, 0x02124}, + {0x02126, 0x02126}, {0x02128, 0x02128}, {0x0212a, 0x02139}, {0x0213c, 0x0213f}, + {0x02145, 0x02149}, {0x0214e, 0x0214e}, {0x02160, 0x02188}, {0x02c00, 0x02ce4}, + {0x02ceb, 0x02cee}, {0x02cf2, 0x02cf3}, {0x02d00, 0x02d25}, {0x02d27, 0x02d27}, + {0x02d2d, 0x02d2d}, {0x02d30, 0x02d67}, {0x02d6f, 0x02d6f}, {0x02d80, 0x02d96}, + {0x02da0, 0x02da6}, {0x02da8, 0x02dae}, {0x02db0, 0x02db6}, {0x02db8, 0x02dbe}, + {0x02dc0, 0x02dc6}, {0x02dc8, 0x02dce}, {0x02dd0, 0x02dd6}, {0x02dd8, 0x02dde}, + {0x03005, 0x03007}, {0x03021, 0x03029}, {0x03031, 0x03035}, {0x03038, 0x0303c}, + {0x03041, 0x03096}, {0x0309d, 0x0309f}, {0x030a1, 0x030fa}, {0x030fc, 0x030ff}, + {0x03105, 0x0312f}, {0x03131, 0x0318e}, {0x031a0, 0x031bf}, {0x031f0, 0x031ff}, + {0x03400, 0x04dbf}, {0x04e00, 0x0a48c}, {0x0a4d0, 0x0a4fd}, {0x0a500, 0x0a60c}, + {0x0a610, 0x0a61f}, {0x0a62a, 0x0a62b}, {0x0a640, 0x0a66e}, {0x0a67f, 0x0a69d}, + {0x0a6a0, 0x0a6ef}, {0x0a717, 0x0a71f}, {0x0a722, 0x0a788}, {0x0a78b, 0x0a7ca}, + {0x0a7d0, 0x0a7d1}, {0x0a7d3, 0x0a7d3}, {0x0a7d5, 0x0a7d9}, {0x0a7f2, 0x0a801}, + {0x0a803, 0x0a805}, {0x0a807, 0x0a80a}, {0x0a80c, 0x0a822}, {0x0a840, 0x0a873}, + {0x0a882, 0x0a8b3}, {0x0a8f2, 0x0a8f7}, {0x0a8fb, 0x0a8fb}, {0x0a8fd, 0x0a8fe}, + {0x0a90a, 0x0a925}, {0x0a930, 0x0a946}, {0x0a960, 0x0a97c}, {0x0a984, 0x0a9b2}, + {0x0a9cf, 0x0a9cf}, {0x0a9e0, 0x0a9e4}, {0x0a9e6, 0x0a9ef}, {0x0a9fa, 0x0a9fe}, + {0x0aa00, 0x0aa28}, {0x0aa40, 0x0aa42}, {0x0aa44, 0x0aa4b}, {0x0aa60, 0x0aa76}, + {0x0aa7a, 0x0aa7a}, {0x0aa7e, 0x0aaaf}, {0x0aab1, 0x0aab1}, {0x0aab5, 0x0aab6}, + {0x0aab9, 0x0aabd}, {0x0aac0, 0x0aac0}, {0x0aac2, 0x0aac2}, {0x0aadb, 0x0aadd}, + {0x0aae0, 0x0aaea}, {0x0aaf2, 0x0aaf4}, {0x0ab01, 0x0ab06}, {0x0ab09, 0x0ab0e}, + {0x0ab11, 0x0ab16}, {0x0ab20, 0x0ab26}, {0x0ab28, 0x0ab2e}, {0x0ab30, 0x0ab5a}, + {0x0ab5c, 0x0ab69}, {0x0ab70, 0x0abe2}, {0x0ac00, 0x0d7a3}, {0x0d7b0, 0x0d7c6}, + {0x0d7cb, 0x0d7fb}, {0x0f900, 0x0fa6d}, {0x0fa70, 0x0fad9}, {0x0fb00, 0x0fb06}, + {0x0fb13, 0x0fb17}, {0x0fb1d, 0x0fb1d}, {0x0fb1f, 0x0fb28}, {0x0fb2a, 0x0fb36}, + {0x0fb38, 0x0fb3c}, {0x0fb3e, 0x0fb3e}, {0x0fb40, 0x0fb41}, {0x0fb43, 0x0fb44}, + {0x0fb46, 0x0fbb1}, {0x0fbd3, 0x0fc5d}, {0x0fc64, 0x0fd3d}, {0x0fd50, 0x0fd8f}, + {0x0fd92, 0x0fdc7}, {0x0fdf0, 0x0fdf9}, {0x0fe71, 0x0fe71}, {0x0fe73, 0x0fe73}, + {0x0fe77, 0x0fe77}, {0x0fe79, 0x0fe79}, {0x0fe7b, 0x0fe7b}, {0x0fe7d, 0x0fe7d}, + {0x0fe7f, 0x0fefc}, {0x0ff21, 0x0ff3a}, {0x0ff41, 0x0ff5a}, {0x0ff66, 0x0ff9d}, + {0x0ffa0, 0x0ffbe}, {0x0ffc2, 0x0ffc7}, {0x0ffca, 0x0ffcf}, {0x0ffd2, 0x0ffd7}, + {0x0ffda, 0x0ffdc}, {0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, + {0x1003c, 0x1003d}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, + {0x10140, 0x10174}, {0x10280, 0x1029c}, {0x102a0, 0x102d0}, {0x10300, 0x1031f}, + {0x1032d, 0x1034a}, {0x10350, 0x10375}, {0x10380, 0x1039d}, {0x103a0, 0x103c3}, + {0x103c8, 0x103cf}, {0x103d1, 0x103d5}, {0x10400, 0x1049d}, {0x104b0, 0x104d3}, + {0x104d8, 0x104fb}, {0x10500, 0x10527}, {0x10530, 0x10563}, {0x10570, 0x1057a}, + {0x1057c, 0x1058a}, {0x1058c, 0x10592}, {0x10594, 0x10595}, {0x10597, 0x105a1}, + {0x105a3, 0x105b1}, {0x105b3, 0x105b9}, {0x105bb, 0x105bc}, {0x10600, 0x10736}, + {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10780, 0x10785}, {0x10787, 0x107b0}, + {0x107b2, 0x107ba}, {0x10800, 0x10805}, {0x10808, 0x10808}, {0x1080a, 0x10835}, + {0x10837, 0x10838}, {0x1083c, 0x1083c}, {0x1083f, 0x10855}, {0x10860, 0x10876}, + {0x10880, 0x1089e}, {0x108e0, 0x108f2}, {0x108f4, 0x108f5}, {0x10900, 0x10915}, + {0x10920, 0x10939}, {0x10980, 0x109b7}, {0x109be, 0x109bf}, {0x10a00, 0x10a00}, + {0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a60, 0x10a7c}, + {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35}, + {0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48}, + {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10d00, 0x10d23}, {0x10e80, 0x10ea9}, + {0x10eb0, 0x10eb1}, {0x10f00, 0x10f1c}, {0x10f27, 0x10f27}, {0x10f30, 0x10f45}, + {0x10f70, 0x10f81}, {0x10fb0, 0x10fc4}, {0x10fe0, 0x10ff6}, {0x11003, 0x11037}, + {0x11071, 0x11072}, {0x11075, 0x11075}, {0x11083, 0x110af}, {0x110d0, 0x110e8}, + {0x11103, 0x11126}, {0x11144, 0x11144}, {0x11147, 0x11147}, {0x11150, 0x11172}, + {0x11176, 0x11176}, {0x11183, 0x111b2}, {0x111c1, 0x111c4}, {0x111da, 0x111da}, + {0x111dc, 0x111dc}, {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286}, + {0x11288, 0x11288}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, + {0x112b0, 0x112de}, {0x11305, 0x1130c}, {0x1130f, 0x11310}, {0x11313, 0x11328}, + {0x1132a, 0x11330}, {0x11332, 0x11333}, {0x11335, 0x11339}, {0x1133d, 0x1133d}, + {0x11350, 0x11350}, {0x1135d, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144a}, + {0x1145f, 0x11461}, {0x11480, 0x114af}, {0x114c4, 0x114c5}, {0x114c7, 0x114c7}, + {0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11644, 0x11644}, + {0x11680, 0x116aa}, {0x116b8, 0x116b8}, {0x11700, 0x1171a}, {0x11740, 0x11746}, + {0x11800, 0x1182b}, {0x118a0, 0x118df}, {0x118ff, 0x11906}, {0x11909, 0x11909}, + {0x1190c, 0x11913}, {0x11915, 0x11916}, {0x11918, 0x1192f}, {0x1193f, 0x1193f}, + {0x11941, 0x11941}, {0x119a0, 0x119a7}, {0x119aa, 0x119d0}, {0x119e1, 0x119e1}, + {0x119e3, 0x119e3}, {0x11a00, 0x11a00}, {0x11a0b, 0x11a32}, {0x11a3a, 0x11a3a}, + {0x11a50, 0x11a50}, {0x11a5c, 0x11a89}, {0x11a9d, 0x11a9d}, {0x11ab0, 0x11af8}, + {0x11c00, 0x11c08}, {0x11c0a, 0x11c2e}, {0x11c40, 0x11c40}, {0x11c72, 0x11c8f}, + {0x11d00, 0x11d06}, {0x11d08, 0x11d09}, {0x11d0b, 0x11d30}, {0x11d46, 0x11d46}, + {0x11d60, 0x11d65}, {0x11d67, 0x11d68}, {0x11d6a, 0x11d89}, {0x11d98, 0x11d98}, + {0x11ee0, 0x11ef2}, {0x11fb0, 0x11fb0}, {0x12000, 0x12399}, {0x12400, 0x1246e}, + {0x12480, 0x12543}, {0x12f90, 0x12ff0}, {0x13000, 0x1342e}, {0x14400, 0x14646}, + {0x16800, 0x16a38}, {0x16a40, 0x16a5e}, {0x16a70, 0x16abe}, {0x16ad0, 0x16aed}, + {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, + {0x16e40, 0x16e7f}, {0x16f00, 0x16f4a}, {0x16f50, 0x16f50}, {0x16f93, 0x16f9f}, + {0x16fe0, 0x16fe1}, {0x16fe3, 0x16fe3}, {0x17000, 0x187f7}, {0x18800, 0x18cd5}, + {0x18d00, 0x18d08}, {0x1aff0, 0x1aff3}, {0x1aff5, 0x1affb}, {0x1affd, 0x1affe}, + {0x1b000, 0x1b122}, {0x1b150, 0x1b152}, {0x1b164, 0x1b167}, {0x1b170, 0x1b2fb}, + {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, + {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d49e, 0x1d49f}, {0x1d4a2, 0x1d4a2}, + {0x1d4a5, 0x1d4a6}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bb, 0x1d4bb}, + {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, + {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, + {0x1d546, 0x1d546}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, + {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, + {0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, + {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1df00, 0x1df1e}, {0x1e100, 0x1e12c}, + {0x1e137, 0x1e13d}, {0x1e14e, 0x1e14e}, {0x1e290, 0x1e2ad}, {0x1e2c0, 0x1e2eb}, + {0x1e7e0, 0x1e7e6}, {0x1e7e8, 0x1e7eb}, {0x1e7ed, 0x1e7ee}, {0x1e7f0, 0x1e7fe}, + {0x1e800, 0x1e8c4}, {0x1e900, 0x1e943}, {0x1e94b, 0x1e94b}, {0x1ee00, 0x1ee03}, + {0x1ee05, 0x1ee1f}, {0x1ee21, 0x1ee22}, {0x1ee24, 0x1ee24}, {0x1ee27, 0x1ee27}, + {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee39, 0x1ee39}, {0x1ee3b, 0x1ee3b}, + {0x1ee42, 0x1ee42}, {0x1ee47, 0x1ee47}, {0x1ee49, 0x1ee49}, {0x1ee4b, 0x1ee4b}, + {0x1ee4d, 0x1ee4f}, {0x1ee51, 0x1ee52}, {0x1ee54, 0x1ee54}, {0x1ee57, 0x1ee57}, + {0x1ee59, 0x1ee59}, {0x1ee5b, 0x1ee5b}, {0x1ee5d, 0x1ee5d}, {0x1ee5f, 0x1ee5f}, + {0x1ee61, 0x1ee62}, {0x1ee64, 0x1ee64}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, + {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee7e, 0x1ee7e}, {0x1ee80, 0x1ee89}, + {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, + {0x20000, 0x2a6df}, {0x2a700, 0x2b738}, {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, + {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}, {0x30000, 0x3134a}, +}; + +// The additional code point interval ranges for the Unicode 14 XID_Continue +// set. This extends the values in kXIDStartRanges. +// This array needs to be in ascending order. +constexpr CodePointRange kXIDContinueRanges[] = { + {0x00030, 0x00039}, {0x0005f, 0x0005f}, {0x000b7, 0x000b7}, {0x00300, 0x0036f}, + {0x00387, 0x00387}, {0x00483, 0x00487}, {0x00591, 0x005bd}, {0x005bf, 0x005bf}, + {0x005c1, 0x005c2}, {0x005c4, 0x005c5}, {0x005c7, 0x005c7}, {0x00610, 0x0061a}, + {0x0064b, 0x00669}, {0x00670, 0x00670}, {0x006d6, 0x006dc}, {0x006df, 0x006e4}, + {0x006e7, 0x006e8}, {0x006ea, 0x006ed}, {0x006f0, 0x006f9}, {0x00711, 0x00711}, + {0x00730, 0x0074a}, {0x007a6, 0x007b0}, {0x007c0, 0x007c9}, {0x007eb, 0x007f3}, + {0x007fd, 0x007fd}, {0x00816, 0x00819}, {0x0081b, 0x00823}, {0x00825, 0x00827}, + {0x00829, 0x0082d}, {0x00859, 0x0085b}, {0x00898, 0x0089f}, {0x008ca, 0x008e1}, + {0x008e3, 0x00903}, {0x0093a, 0x0093c}, {0x0093e, 0x0094f}, {0x00951, 0x00957}, + {0x00962, 0x00963}, {0x00966, 0x0096f}, {0x00981, 0x00983}, {0x009bc, 0x009bc}, + {0x009be, 0x009c4}, {0x009c7, 0x009c8}, {0x009cb, 0x009cd}, {0x009d7, 0x009d7}, + {0x009e2, 0x009e3}, {0x009e6, 0x009ef}, {0x009fe, 0x009fe}, {0x00a01, 0x00a03}, + {0x00a3c, 0x00a3c}, {0x00a3e, 0x00a42}, {0x00a47, 0x00a48}, {0x00a4b, 0x00a4d}, + {0x00a51, 0x00a51}, {0x00a66, 0x00a71}, {0x00a75, 0x00a75}, {0x00a81, 0x00a83}, + {0x00abc, 0x00abc}, {0x00abe, 0x00ac5}, {0x00ac7, 0x00ac9}, {0x00acb, 0x00acd}, + {0x00ae2, 0x00ae3}, {0x00ae6, 0x00aef}, {0x00afa, 0x00aff}, {0x00b01, 0x00b03}, + {0x00b3c, 0x00b3c}, {0x00b3e, 0x00b44}, {0x00b47, 0x00b48}, {0x00b4b, 0x00b4d}, + {0x00b55, 0x00b57}, {0x00b62, 0x00b63}, {0x00b66, 0x00b6f}, {0x00b82, 0x00b82}, + {0x00bbe, 0x00bc2}, {0x00bc6, 0x00bc8}, {0x00bca, 0x00bcd}, {0x00bd7, 0x00bd7}, + {0x00be6, 0x00bef}, {0x00c00, 0x00c04}, {0x00c3c, 0x00c3c}, {0x00c3e, 0x00c44}, + {0x00c46, 0x00c48}, {0x00c4a, 0x00c4d}, {0x00c55, 0x00c56}, {0x00c62, 0x00c63}, + {0x00c66, 0x00c6f}, {0x00c81, 0x00c83}, {0x00cbc, 0x00cbc}, {0x00cbe, 0x00cc4}, + {0x00cc6, 0x00cc8}, {0x00cca, 0x00ccd}, {0x00cd5, 0x00cd6}, {0x00ce2, 0x00ce3}, + {0x00ce6, 0x00cef}, {0x00d00, 0x00d03}, {0x00d3b, 0x00d3c}, {0x00d3e, 0x00d44}, + {0x00d46, 0x00d48}, {0x00d4a, 0x00d4d}, {0x00d57, 0x00d57}, {0x00d62, 0x00d63}, + {0x00d66, 0x00d6f}, {0x00d81, 0x00d83}, {0x00dca, 0x00dca}, {0x00dcf, 0x00dd4}, + {0x00dd6, 0x00dd6}, {0x00dd8, 0x00ddf}, {0x00de6, 0x00def}, {0x00df2, 0x00df3}, + {0x00e31, 0x00e31}, {0x00e33, 0x00e3a}, {0x00e47, 0x00e4e}, {0x00e50, 0x00e59}, + {0x00eb1, 0x00eb1}, {0x00eb3, 0x00ebc}, {0x00ec8, 0x00ecd}, {0x00ed0, 0x00ed9}, + {0x00f18, 0x00f19}, {0x00f20, 0x00f29}, {0x00f35, 0x00f35}, {0x00f37, 0x00f37}, + {0x00f39, 0x00f39}, {0x00f3e, 0x00f3f}, {0x00f71, 0x00f84}, {0x00f86, 0x00f87}, + {0x00f8d, 0x00f97}, {0x00f99, 0x00fbc}, {0x00fc6, 0x00fc6}, {0x0102b, 0x0103e}, + {0x01040, 0x01049}, {0x01056, 0x01059}, {0x0105e, 0x01060}, {0x01062, 0x01064}, + {0x01067, 0x0106d}, {0x01071, 0x01074}, {0x01082, 0x0108d}, {0x0108f, 0x0109d}, + {0x0135d, 0x0135f}, {0x01369, 0x01371}, {0x01712, 0x01715}, {0x01732, 0x01734}, + {0x01752, 0x01753}, {0x01772, 0x01773}, {0x017b4, 0x017d3}, {0x017dd, 0x017dd}, + {0x017e0, 0x017e9}, {0x0180b, 0x0180d}, {0x0180f, 0x01819}, {0x018a9, 0x018a9}, + {0x01920, 0x0192b}, {0x01930, 0x0193b}, {0x01946, 0x0194f}, {0x019d0, 0x019da}, + {0x01a17, 0x01a1b}, {0x01a55, 0x01a5e}, {0x01a60, 0x01a7c}, {0x01a7f, 0x01a89}, + {0x01a90, 0x01a99}, {0x01ab0, 0x01abd}, {0x01abf, 0x01ace}, {0x01b00, 0x01b04}, + {0x01b34, 0x01b44}, {0x01b50, 0x01b59}, {0x01b6b, 0x01b73}, {0x01b80, 0x01b82}, + {0x01ba1, 0x01bad}, {0x01bb0, 0x01bb9}, {0x01be6, 0x01bf3}, {0x01c24, 0x01c37}, + {0x01c40, 0x01c49}, {0x01c50, 0x01c59}, {0x01cd0, 0x01cd2}, {0x01cd4, 0x01ce8}, + {0x01ced, 0x01ced}, {0x01cf4, 0x01cf4}, {0x01cf7, 0x01cf9}, {0x01dc0, 0x01dff}, + {0x0203f, 0x02040}, {0x02054, 0x02054}, {0x020d0, 0x020dc}, {0x020e1, 0x020e1}, + {0x020e5, 0x020f0}, {0x02cef, 0x02cf1}, {0x02d7f, 0x02d7f}, {0x02de0, 0x02dff}, + {0x0302a, 0x0302f}, {0x03099, 0x0309a}, {0x0a620, 0x0a629}, {0x0a66f, 0x0a66f}, + {0x0a674, 0x0a67d}, {0x0a69e, 0x0a69f}, {0x0a6f0, 0x0a6f1}, {0x0a802, 0x0a802}, + {0x0a806, 0x0a806}, {0x0a80b, 0x0a80b}, {0x0a823, 0x0a827}, {0x0a82c, 0x0a82c}, + {0x0a880, 0x0a881}, {0x0a8b4, 0x0a8c5}, {0x0a8d0, 0x0a8d9}, {0x0a8e0, 0x0a8f1}, + {0x0a8ff, 0x0a909}, {0x0a926, 0x0a92d}, {0x0a947, 0x0a953}, {0x0a980, 0x0a983}, + {0x0a9b3, 0x0a9c0}, {0x0a9d0, 0x0a9d9}, {0x0a9e5, 0x0a9e5}, {0x0a9f0, 0x0a9f9}, + {0x0aa29, 0x0aa36}, {0x0aa43, 0x0aa43}, {0x0aa4c, 0x0aa4d}, {0x0aa50, 0x0aa59}, + {0x0aa7b, 0x0aa7d}, {0x0aab0, 0x0aab0}, {0x0aab2, 0x0aab4}, {0x0aab7, 0x0aab8}, + {0x0aabe, 0x0aabf}, {0x0aac1, 0x0aac1}, {0x0aaeb, 0x0aaef}, {0x0aaf5, 0x0aaf6}, + {0x0abe3, 0x0abea}, {0x0abec, 0x0abed}, {0x0abf0, 0x0abf9}, {0x0fb1e, 0x0fb1e}, + {0x0fe00, 0x0fe0f}, {0x0fe20, 0x0fe2f}, {0x0fe33, 0x0fe34}, {0x0fe4d, 0x0fe4f}, + {0x0ff10, 0x0ff19}, {0x0ff3f, 0x0ff3f}, {0x0ff9e, 0x0ff9f}, {0x101fd, 0x101fd}, + {0x102e0, 0x102e0}, {0x10376, 0x1037a}, {0x104a0, 0x104a9}, {0x10a01, 0x10a03}, + {0x10a05, 0x10a06}, {0x10a0c, 0x10a0f}, {0x10a38, 0x10a3a}, {0x10a3f, 0x10a3f}, + {0x10ae5, 0x10ae6}, {0x10d24, 0x10d27}, {0x10d30, 0x10d39}, {0x10eab, 0x10eac}, + {0x10f46, 0x10f50}, {0x10f82, 0x10f85}, {0x11000, 0x11002}, {0x11038, 0x11046}, + {0x11066, 0x11070}, {0x11073, 0x11074}, {0x1107f, 0x11082}, {0x110b0, 0x110ba}, + {0x110c2, 0x110c2}, {0x110f0, 0x110f9}, {0x11100, 0x11102}, {0x11127, 0x11134}, + {0x11136, 0x1113f}, {0x11145, 0x11146}, {0x11173, 0x11173}, {0x11180, 0x11182}, + {0x111b3, 0x111c0}, {0x111c9, 0x111cc}, {0x111ce, 0x111d9}, {0x1122c, 0x11237}, + {0x1123e, 0x1123e}, {0x112df, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303}, + {0x1133b, 0x1133c}, {0x1133e, 0x11344}, {0x11347, 0x11348}, {0x1134b, 0x1134d}, + {0x11357, 0x11357}, {0x11362, 0x11363}, {0x11366, 0x1136c}, {0x11370, 0x11374}, + {0x11435, 0x11446}, {0x11450, 0x11459}, {0x1145e, 0x1145e}, {0x114b0, 0x114c3}, + {0x114d0, 0x114d9}, {0x115af, 0x115b5}, {0x115b8, 0x115c0}, {0x115dc, 0x115dd}, + {0x11630, 0x11640}, {0x11650, 0x11659}, {0x116ab, 0x116b7}, {0x116c0, 0x116c9}, + {0x1171d, 0x1172b}, {0x11730, 0x11739}, {0x1182c, 0x1183a}, {0x118e0, 0x118e9}, + {0x11930, 0x11935}, {0x11937, 0x11938}, {0x1193b, 0x1193e}, {0x11940, 0x11940}, + {0x11942, 0x11943}, {0x11950, 0x11959}, {0x119d1, 0x119d7}, {0x119da, 0x119e0}, + {0x119e4, 0x119e4}, {0x11a01, 0x11a0a}, {0x11a33, 0x11a39}, {0x11a3b, 0x11a3e}, + {0x11a47, 0x11a47}, {0x11a51, 0x11a5b}, {0x11a8a, 0x11a99}, {0x11c2f, 0x11c36}, + {0x11c38, 0x11c3f}, {0x11c50, 0x11c59}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6}, + {0x11d31, 0x11d36}, {0x11d3a, 0x11d3a}, {0x11d3c, 0x11d3d}, {0x11d3f, 0x11d45}, + {0x11d47, 0x11d47}, {0x11d50, 0x11d59}, {0x11d8a, 0x11d8e}, {0x11d90, 0x11d91}, + {0x11d93, 0x11d97}, {0x11da0, 0x11da9}, {0x11ef3, 0x11ef6}, {0x16a60, 0x16a69}, + {0x16ac0, 0x16ac9}, {0x16af0, 0x16af4}, {0x16b30, 0x16b36}, {0x16b50, 0x16b59}, + {0x16f4f, 0x16f4f}, {0x16f51, 0x16f87}, {0x16f8f, 0x16f92}, {0x16fe4, 0x16fe4}, + {0x16ff0, 0x16ff1}, {0x1bc9d, 0x1bc9e}, {0x1cf00, 0x1cf2d}, {0x1cf30, 0x1cf46}, + {0x1d165, 0x1d169}, {0x1d16d, 0x1d172}, {0x1d17b, 0x1d182}, {0x1d185, 0x1d18b}, + {0x1d1aa, 0x1d1ad}, {0x1d242, 0x1d244}, {0x1d7ce, 0x1d7ff}, {0x1da00, 0x1da36}, + {0x1da3b, 0x1da6c}, {0x1da75, 0x1da75}, {0x1da84, 0x1da84}, {0x1da9b, 0x1da9f}, + {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006}, {0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, + {0x1e023, 0x1e024}, {0x1e026, 0x1e02a}, {0x1e130, 0x1e136}, {0x1e140, 0x1e149}, + {0x1e2ae, 0x1e2ae}, {0x1e2ec, 0x1e2f9}, {0x1e8d0, 0x1e8d6}, {0x1e944, 0x1e94a}, + {0x1e950, 0x1e959}, {0x1fbf0, 0x1fbf9}, {0xe0100, 0xe01ef}, +}; + +} // namespace + +bool CodePoint::IsXIDStart() const { + // Short circuit ASCII. The binary search will find these last, but most + // of our current source is ASCII, so handle them quicker. + if ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z')) { + return true; + } + // With [a-zA-Z] handled, nothing less then the next sequence start can be + // XIDStart, so filter them all out. This catches most of the common symbols + // that are used in ASCII. + if (value < 0x000aa) { + return false; + } + return std::binary_search(std::begin(kXIDStartRanges), std::end(kXIDStartRanges), *this); +} + +bool CodePoint::IsXIDContinue() const { + // Short circuit ASCII. The binary search will find these last, but most + // of our current source is ASCII, so handle them quicker. + if ((value >= '0' && value <= '9') || value == '_') { + return true; + } + return IsXIDStart() || + std::binary_search(std::begin(kXIDContinueRanges), std::end(kXIDContinueRanges), *this); +} + +namespace utf8 { + +uint8_t SequenceLength(uint8_t first_code_point) { + // Lookup table for the first byte of a UTF-8 sequence. + // 0 indicates an invalid length. + // Note that bit encodings that can fit in a smaller number of bytes are + // invalid (e.g. 0xc0). Code points that exceed the unicode maximum of + // 0x10FFFF are also invalid (0xf5+). + // See: https://en.wikipedia.org/wiki/UTF-8#Encoding and + // https://datatracker.ietf.org/doc/html/rfc3629#section-3 + static constexpr std::array kSequenceLength = { + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xc0 */ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /* 0xd0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /* 0xe0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* 0xf0 */ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + return kSequenceLength[first_code_point]; +} + +// This is a C-style API that will always trigger -Wunsafe-buffer-usage +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +std::pair Decode(const uint8_t* ptr, size_t len) { + if (len < 1) { + return {}; + } + // Fast-path ASCII characters as they're always valid + if (ptr[0] <= 0x7f) { + return {CodePoint{ptr[0]}, 1}; + } + + uint8_t n = SequenceLength(ptr[0]); + if (n > len) { + return {}; + } + + CodePoint c; + + uint8_t top_bits = 0b11000000; + switch (n) { + // Note: n=0 (invalid) is correctly handled without a case. + case 1: + c = CodePoint{ptr[0]}; + break; + case 2: + top_bits &= ptr[1] ^ 0b01000000; + c = CodePoint{(static_cast(ptr[0] & 0b00011111) << 6) | + (static_cast(ptr[1] & 0b00111111))}; + break; + case 3: + top_bits &= (ptr[1] ^ 0b01000000) & (ptr[2] ^ 0b01000000); + c = CodePoint{(static_cast(ptr[0] & 0b00001111) << 12) | + (static_cast(ptr[1] & 0b00111111) << 6) | + (static_cast(ptr[2] & 0b00111111))}; + break; + case 4: + top_bits &= (ptr[1] ^ 0b01000000) & (ptr[2] ^ 0b01000000) & (ptr[3] ^ 0b01000000); + c = CodePoint{(static_cast(ptr[0] & 0b00000111) << 18) | + (static_cast(ptr[1] & 0b00111111) << 12) | + (static_cast(ptr[2] & 0b00111111) << 6) | + (static_cast(ptr[3] & 0b00111111))}; + break; + } + if (top_bits != 0b11000000) { + // Check that the two most significant bits of all the code units after the first code point + // are all [1, 0]. + n = 0; + c = 0; + } + + // Validate code point range. After decoding, each byte count utf8 character must fall within + // the available range of code points. + uint32_t v = c; + if ((n == 1 && (v > 0x0000'007f)) || // + (n == 2 && (v < 0x0000'0080 || v > 0x0000'07ff)) || // + (n == 3 && (v < 0x0000'0800 || v > 0x0000'ffff)) || // + (n == 4 && (v < 0x0001'0000 || v > 0x0010'ffff))) { + return {}; + } + + return {c, n}; +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +std::pair Decode(std::string_view utf8_string) { + return Decode(reinterpret_cast(utf8_string.data()), utf8_string.size()); +} + +// This is a C-style API that will always trigger -Wunsafe-buffer-usage +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +size_t Encode(CodePoint code_point, uint8_t* ptr) { + if (code_point <= 0x7f) { + if (ptr) { + ptr[0] = static_cast(code_point); + } + return 1; + } + if (code_point <= 0x7ff) { + if (ptr) { + ptr[0] = static_cast(code_point >> 6) | 0b11000000; + ptr[1] = static_cast(code_point & 0b00111111) | 0b10000000; + } + return 2; + } + if (code_point <= 0xffff) { + if (ptr) { + ptr[0] = static_cast(code_point >> 12) | 0b11100000; + ptr[1] = static_cast((code_point >> 6) & 0b00111111) | 0b10000000; + ptr[2] = static_cast(code_point & 0b00111111) | 0b10000000; + } + return 3; + } + if (code_point <= 0x10ffff) { + if (ptr) { + ptr[0] = static_cast(code_point >> 18) | 0b11110000; + ptr[1] = static_cast((code_point >> 12) & 0b00111111) | 0b10000000; + ptr[2] = static_cast((code_point >> 6) & 0b00111111) | 0b10000000; + ptr[3] = static_cast(code_point & 0b00111111) | 0b10000000; + } + return 4; + } + return 0; // invalid code point +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +bool IsASCII(std::string_view str) { + for (auto c : str) { + if (c & 0x80) { + return false; + } + } + return true; +} + +} // namespace utf8 + +namespace utf16 { + +// This is a C-style API that will always trigger -Wunsafe-buffer-usage +TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); +std::pair Decode(const uint16_t* ptr, size_t len) { + if (len < 1) { + return {}; + } + uint16_t a = ptr[0]; + if (a <= 0xd7ff || a >= 0xe000) { + return {CodePoint{static_cast(a)}, 1}; + } + if (len < 2) { + return {}; + } + uint32_t b = ptr[1]; + if (b <= 0xd7ff || b >= 0xe000) { + return {}; + } + uint32_t high = a - 0xd800; + uint32_t low = b - 0xdc00; + return {CodePoint{0x10000 + ((high << 10) | low)}, 2}; +} + +std::pair Decode(std::string_view utf16_string) { + return Decode(reinterpret_cast(utf16_string.data()), utf16_string.size() / 2); +} + +size_t Encode(CodePoint code_point, uint16_t* ptr) { + if (code_point <= 0xd7ff || (code_point >= 0xe000 && code_point <= 0xffff)) { + if (ptr) { + ptr[0] = static_cast(code_point); + } + return 1; + } + if (code_point >= 0x10000 && code_point <= 0x10ffff) { + if (ptr) { + auto biased = code_point - 0x10000; + ptr[0] = static_cast((biased >> 10) + 0xd800); + ptr[1] = static_cast((biased & 0b1111111111) + 0xdc00); + } + return 2; + } + return 0; // invalid code point +} +TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + +} // namespace utf16 +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text/unicode.h b/3rdparty/dawn/src/tint/utils/text/unicode.h new file mode 100644 index 000000000..50d5150bd --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text/unicode.h @@ -0,0 +1,131 @@ +// Copyright 2022 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_UNICODE_H_ +#define SRC_TINT_UTILS_TEXT_UNICODE_H_ + +#include +#include +#include +#include + +namespace tint { + +/// CodePoint is a unicode code point. +struct CodePoint { + /// Constructor + inline CodePoint() = default; + + /// Constructor + /// @param v the code point value + inline explicit CodePoint(uint32_t v) : value(v) {} + + /// @returns the code point value + inline operator uint32_t() const { return value; } + + /// Assignment operator + /// @param v the new value for the code point + /// @returns this CodePoint + inline CodePoint& operator=(uint32_t v) { + value = v; + return *this; + } + + /// @returns true if this CodePoint is in the XID_Start set. + /// @see https://unicode.org/reports/tr31/ + bool IsXIDStart() const; + + /// @returns true if this CodePoint is in the XID_Continue set. + /// @see https://unicode.org/reports/tr31/ + bool IsXIDContinue() const; + + /// The code point value + uint32_t value = 0; +}; + +namespace utf8 { + +/// Returns the length of the utf8 sequence that starts with @p first_code_point. +/// @param first_code_point the first byte of the utf8 sequence +/// @returns the length of the utf8 sequence, or 0 if the sequence is invalid. +uint8_t SequenceLength(uint8_t first_code_point); + +/// Decodes the first code point in the utf8 string. +/// @param ptr the pointer to the first byte of the utf8 sequence +/// @param len the maximum number of uint8_t to read +/// @returns a pair of CodePoint and width in code units (uint8_t). +/// If the next code point cannot be decoded then returns [0,0]. +std::pair Decode(const uint8_t* ptr, size_t len); + +/// Decodes the first code point in the utf8 string. +/// @param utf8_string the string view that contains the utf8 sequence +/// @returns a pair of CodePoint and width in code units (uint8_t). +/// If the next code point cannot be decoded, then returns [0,0]. +std::pair Decode(std::string_view utf8_string); + +/// Encodes a code point to the utf8 string buffer or queries the number of code units used to +/// encode the code point. +/// @param code_point the code point to encode. +/// @param ptr the pointer to the utf8 string buffer, or nullptr to query the number of code units +/// that would be written if @p ptr is not nullptr. +/// @returns the number of code units written / would be written (at most 4). +size_t Encode(CodePoint code_point, uint8_t* ptr); + +/// @returns true if all the utf-8 code points in the string are ASCII +/// (code-points 0x00..0x7f). +bool IsASCII(std::string_view); + +} // namespace utf8 + +namespace utf16 { + +/// Decodes the first code point in the utf16 string. +/// @param ptr the pointer to the first byte of the utf16 sequence +/// @param len the maximum number of code units to read +/// @returns a pair of CodePoint and width in code units (16-bit integers). +/// If the next code point cannot be decoded then returns [0,0]. +std::pair Decode(const uint16_t* ptr, size_t len); + +/// Decodes the first code point in the utf16 string. +/// @param utf16_string the string view that contains the utf16 sequence +/// @returns a pair of CodePoint and width in code units (16-bit integers). +/// If the next code point cannot be decoded then returns [0,0]. +std::pair Decode(std::string_view utf16_string); + +/// Encodes a code point to the utf16 string buffer or queries the number of code units used to +/// encode the code point. +/// @param code_point the code point to encode. +/// @param ptr the pointer to the utf16 string buffer, or nullptr to query the number of code units +/// that would be written if @p ptr is not nullptr. +/// @returns the number of code units written / would be written (at most 2). +size_t Encode(CodePoint code_point, uint16_t* ptr); + +} // namespace utf16 + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_UNICODE_H_ diff --git a/3rdparty/dawn/src/tint/utils/text_generator/text_generator.cc b/3rdparty/dawn/src/tint/utils/text_generator/text_generator.cc new file mode 100644 index 000000000..a2a616305 --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text_generator/text_generator.cc @@ -0,0 +1,183 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "src/tint/utils/text_generator/text_generator.h" + +#include +#include + +#include "src/tint/utils/ice/ice.h" + +namespace tint { + +TextGenerator::TextGenerator() = default; + +TextGenerator::~TextGenerator() = default; + +TextGenerator::LineWriter::LineWriter(TextBuffer* buf) : buffer(buf) {} + +TextGenerator::LineWriter::LineWriter(LineWriter&& other) { + buffer = other.buffer; + other.buffer = nullptr; +} + +TextGenerator::LineWriter::~LineWriter() { + if (buffer) { + buffer->Append(os.str()); + } +} + +TextGenerator::TextBuffer::TextBuffer() = default; + +TextGenerator::TextBuffer::~TextBuffer() = default; + +void TextGenerator::TextBuffer::IncrementIndent() { + current_indent += 2; +} + +void TextGenerator::TextBuffer::DecrementIndent() { + current_indent = std::max(2u, current_indent) - 2u; +} + +void TextGenerator::TextBuffer::Append(const std::string& line) { + lines.emplace_back(LineInfo{current_indent, line}); +} + +void TextGenerator::TextBuffer::Insert(const std::string& line, size_t before, uint32_t indent) { + TINT_ASSERT(before <= lines.size()) + << "TextBuffer::Insert() called with before > lines.size()\n" + << " before:" << before << "\n" + << " lines.size(): " << lines.size(); + + using DT = decltype(lines)::difference_type; + lines.insert(lines.begin() + static_cast
(before), LineInfo{indent, line}); +} + +void TextGenerator::TextBuffer::Append(const TextBuffer& tb) { + for (auto& line : tb.lines) { + // TODO(crbug.com/tint/2222): inefficient, consider optimizing + lines.emplace_back(LineInfo{current_indent + line.indent, line.content}); + } +} + +void TextGenerator::TextBuffer::Insert(const TextBuffer& tb, size_t before, uint32_t indent) { + TINT_ASSERT(before <= lines.size()) + << "TextBuffer::Insert() called with before > lines.size()\n" + << " before:" << before << "\n" + << " lines.size(): " << lines.size(); + + size_t idx = 0; + for (auto& line : tb.lines) { + // TODO(crbug.com/tint/2222): inefficient, consider optimizing + using DT = decltype(lines)::difference_type; + lines.insert(lines.begin() + static_cast
(before + idx), + LineInfo{indent + line.indent, line.content}); + idx++; + } +} + +std::string TextGenerator::TextBuffer::String(uint32_t indent /* = 0 */) const { + StringStream ss; + for (auto& line : lines) { + if (!line.content.empty()) { + for (uint32_t i = 0; i < indent + line.indent; i++) { + ss << " "; + } + ss << line.content; + } + ss << "\n"; + } + return ss.str(); +} + +std::string TextGenerator::TextBuffer::MinifiedString() const { + /// Returns `true` if @p c is the start of an identifier codepoint. + auto is_ident_char = [](char c) { return std::isalnum(c) || c == '_' || !isascii(c); }; + + bool previous_is_ident = false; + bool in_whitespace = false; + std::string result; + for (const auto& line : lines) { + for (uint32_t i = 0; i < line.content.length();) { + auto c = line.content.at(i); + if (std::isspace(c)) { + // Track that we are in whitespace but do not emit anything. + // We will emit a whitespace character if the next non-whitespace character would + // combine with the previous whitespace character to form an incorrect token. + in_whitespace = true; + i++; + continue; + } + if (in_whitespace) { + // If we are coming from whitespace that separates two identifiers, then we need to + // emit a space between them. Use a newline in these cases to reduce the maximum + // line length of generated shaders. + if (previous_is_ident && is_ident_char(c)) { + result += "\n"; + } + } + + in_whitespace = false; + previous_is_ident = is_ident_char(c); + + // Emit the next codepoint. + auto codepoint_length = utf8::SequenceLength(static_cast(c)); + for (uint32_t j = 0; j < codepoint_length; j++) { + TINT_ASSERT(i < line.content.length()); + result += line.content.at(i); + i++; + } + } + in_whitespace = true; + } + + return result; +} + +std::string TextGenerator::Result() const { + return main_buffer_.String(); +} + +TextGenerator::ScopedParen::ScopedParen(StringStream& stream) : s(stream) { + s << "("; +} + +TextGenerator::ScopedParen::~ScopedParen() { + s << ")"; +} + +TextGenerator::ScopedIndent::ScopedIndent(TextGenerator* generator) + : ScopedIndent(generator->current_buffer_) {} + +TextGenerator::ScopedIndent::ScopedIndent(TextBuffer* buffer) : buffer_(buffer) { + buffer_->IncrementIndent(); +} +TextGenerator::ScopedIndent::~ScopedIndent() { + buffer_->DecrementIndent(); +} + +} // namespace tint diff --git a/3rdparty/dawn/src/tint/utils/text_generator/text_generator.h b/3rdparty/dawn/src/tint/utils/text_generator/text_generator.h new file mode 100644 index 000000000..3223bb1eb --- /dev/null +++ b/3rdparty/dawn/src/tint/utils/text_generator/text_generator.h @@ -0,0 +1,206 @@ +// Copyright 2020 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_TINT_UTILS_TEXT_GENERATOR_TEXT_GENERATOR_H_ +#define SRC_TINT_UTILS_TEXT_GENERATOR_TEXT_GENERATOR_H_ + +#include +#include +#include + +#include "src/tint/utils/diagnostic/diagnostic.h" +#include "src/tint/utils/text/string_stream.h" + +namespace tint { + +/// Helper methods for generators which are creating text output +class TextGenerator { + public: + /// LineInfo holds a single line of text + struct LineInfo { + /// The indentation of the line in blankspace + uint32_t indent = 0; + /// The content of the line, without a trailing newline character + std::string content; + }; + + /// TextBuffer holds a list of lines of text. + struct TextBuffer { + // Constructor + TextBuffer(); + + // Destructor + ~TextBuffer(); + + /// IncrementIndent increases the indentation of lines that will be written + /// to the TextBuffer + void IncrementIndent(); + + /// DecrementIndent decreases the indentation of lines that will be written + /// to the TextBuffer + void DecrementIndent(); + + /// Appends the line to the end of the TextBuffer + /// @param line the line to append to the TextBuffer + void Append(const std::string& line); + + /// Inserts the line to the TextBuffer before the line with index `before` + /// @param line the line to append to the TextBuffer + /// @param before the zero-based index of the line to insert the text before + /// @param indent the indentation to apply to the inserted lines + void Insert(const std::string& line, size_t before, uint32_t indent); + + /// Appends the lines of `tb` to the end of this TextBuffer + /// @param tb the TextBuffer to append to the end of this TextBuffer + void Append(const TextBuffer& tb); + + /// Inserts the lines of `tb` to the TextBuffer before the line with index + /// `before` + /// @param tb the TextBuffer to insert into this TextBuffer + /// @param before the zero-based index of the line to insert the text before + /// @param indent the indentation to apply to the inserted lines + void Insert(const TextBuffer& tb, size_t before, uint32_t indent); + + /// @returns the buffer's content as a single string + /// @param indent additional indentation to apply to each line + std::string String(uint32_t indent = 0) const; + + /// @returns the buffer's content as a single string with all + /// unneeded whitespace removed. + std::string MinifiedString() const; + + /// The current indentation of the TextBuffer. Lines appended to the + /// TextBuffer will use this indentation. + uint32_t current_indent = 0; + + /// The lines + std::vector lines; + }; + /// LineWriter is a helper that acts as a string buffer, who's content is + /// emitted to the TextBuffer as a single line on destruction. + struct LineWriter { + public: + /// Constructor + /// @param buffer the TextBuffer that the LineWriter will append its + /// content to on destruction, at the end of the buffer. + explicit LineWriter(TextBuffer* buffer); + + /// Move constructor + /// @param rhs the LineWriter to move + LineWriter(LineWriter&& rhs); + /// Destructor + ~LineWriter(); + + /// @returns the StringStream + operator StringStream&() { return os; } + + /// @param rhs the value to write to the line + /// @returns the StringStream so calls can be chained + template + StringStream& operator<<(T&& rhs) { + return os << std::forward(rhs); + } + + private: + LineWriter(const LineWriter&) = delete; + LineWriter& operator=(const LineWriter&) = delete; + + StringStream os; + TextBuffer* buffer; + }; + + /// Increment the emitter indent level + void IncrementIndent() { current_buffer_->IncrementIndent(); } + /// Decrement the emitter indent level + void DecrementIndent() { current_buffer_->DecrementIndent(); } + + /// @returns a new LineWriter, used for buffering and writing a line to + /// the end of #current_buffer_. + LineWriter Line() { return LineWriter(current_buffer_); } + /// @param buffer the TextBuffer to write the line to + /// @returns a new LineWriter, used for buffering and writing a line to + /// the end of `buffer`. + static LineWriter Line(TextBuffer* buffer) { return LineWriter(buffer); } + + /// @returns the result data + virtual std::string Result() const; + + /// @returns the list of diagnostics raised by the generator. + const diag::List& Diagnostics() const { return diagnostics_; } + + protected: + /// Helper for writing a '(' on construction and a ')' destruction. + struct ScopedParen { + /// Constructor + /// @param stream the StringStream that will be written to + explicit ScopedParen(StringStream& stream); + /// Destructor + ~ScopedParen(); + + private: + ScopedParen(ScopedParen&& rhs) = delete; + ScopedParen(const ScopedParen&) = delete; + ScopedParen& operator=(const ScopedParen&) = delete; + StringStream& s; + }; + + /// Helper for incrementing indentation on construction and decrementing + /// indentation on destruction. + struct ScopedIndent { + /// Constructor + /// @param buffer the TextBuffer that the ScopedIndent will indent + explicit ScopedIndent(TextBuffer* buffer); + /// Constructor + /// @param generator ScopedIndent will indent the generator's + /// `current_buffer_` + explicit ScopedIndent(TextGenerator* generator); + /// Destructor + ~ScopedIndent(); + + private: + ScopedIndent(ScopedIndent&& rhs) = delete; + ScopedIndent(const ScopedIndent&) = delete; + ScopedIndent& operator=(const ScopedIndent&) = delete; + TextBuffer* buffer_; + }; + + /// Constructor + TextGenerator(); + virtual ~TextGenerator(); + + /// Diagnostics generated by the generator + diag::List diagnostics_; + /// The buffer the TextGenerator is currently appending lines to + TextBuffer* current_buffer_ = &main_buffer_; + + /// The primary text buffer that the generator will emit + TextBuffer main_buffer_; +}; + +} // namespace tint + +#endif // SRC_TINT_UTILS_TEXT_GENERATOR_TEXT_GENERATOR_H_ diff --git a/3rdparty/dawn/src/utils/compiler.h b/3rdparty/dawn/src/utils/compiler.h new file mode 100644 index 000000000..bf11ec021 --- /dev/null +++ b/3rdparty/dawn/src/utils/compiler.h @@ -0,0 +1,127 @@ +// Copyright 2024 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_UTILS_COMPILER_H_ +#define SRC_UTILS_COMPILER_H_ + +// DAWN_COMPILER_IS(CLANG|GCC|MSVC): Compiler detection +// +// Note: clang masquerades as GCC on POSIX and as MSVC on Windows. It must be checked first. +#if defined(__clang__) +#define DAWN_COMPILER_IS_CLANG 1 +#define DAWN_COMPILER_IS_GCC 0 +#define DAWN_COMPILER_IS_MSVC 0 +#elif defined(__GNUC__) +#define DAWN_COMPILER_IS_CLANG 0 +#define DAWN_COMPILER_IS_GCC 1 +#define DAWN_COMPILER_IS_MSVC 0 +#elif defined(_MSC_VER) +#define DAWN_COMPILER_IS_CLANG 0 +#define DAWN_COMPILER_IS_GCC 0 +#define DAWN_COMPILER_IS_MSVC 1 +#else +#error "Unsupported compiler" +#endif + +// Use #if DAWN_COMPILER_IS(XXX) for compiler specific code. +// Do not use #ifdef or the naked macro DAWN_COMPILER_IS_XXX. +// This can help avoid common mistakes like not including "compiler.h" and falling into unwanted +// code block as usage of undefined macro "function" will be blocked by the compiler. +#define DAWN_COMPILER_IS(X) (1 == DAWN_COMPILER_IS_##X) + +// DAWN_HAS_ATTRIBUTE +// +// A wrapper around `__has_attribute`. This test whether its operand is recognized by the compiler. +#if defined(__has_attribute) +#define DAWN_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +#define DAWN_HAS_ATTRIBUTE(x) 0 +#endif + +// DAWN_HAS_CPP_ATTRIBUTE +// +// A wrapper around `__has_cpp_attribute`. This test whether its operand is recognized by the +// compiler. +#if defined(__has_cpp_attribute) +#define DAWN_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define DAWN_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +// DAWN_BUILTIN_UNREACHABLE() +// +// Hints the compiler that a code path is unreachable. +#if DAWN_COMPILER_IS(MSVC) +#define DAWN_BUILTIN_UNREACHABLE() __assume(false) +#else +#define DAWN_BUILTIN_UNREACHABLE() __builtin_unreachable() +#endif + +// DAWN_LIKELY(EXPR) +// +// Where available, hints the compiler that the expression will be true to help it generate code +// that leads to better branch prediction. +#if DAWN_COMPILER_IS(GCC) || DAWN_COMPILER_IS(CLANG) +#define DAWN_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define DAWN_LIKELY(x) (x) +#endif + +// DAWN_UNLIKELY(EXPR) +// +// Where available, hints the compiler that the expression will be false to help it generate code +// that leads to better branch prediction. +#if DAWN_COMPILER_IS(GCC) || DAWN_COMPILER_IS(CLANG) +#define DAWN_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define DAWN_UNLIKELY(x) (x) +#endif + +// DAWN_ASAN_ENABLED() +// +// Checks whether ASan is enabled. +#if DAWN_COMPILER_IS(CLANG) +#define DAWN_ASAN_ENABLED() __has_feature(address_sanitizer) +#elif DAWN_COMPILER_IS(GCC) || DAWN_COMPILER_IS(MSVC) +#if defined(__SANITIZE_ADDRESS__) +#define DAWN_ASAN_ENABLED() 1 +#else +#define DAWN_ASAN_ENABLED() 0 +#endif +#endif + +// DAWN_NO_SANITIZE(instrumentation) +// +// Annotate a function or a global variable declaration to specify that a particular instrumentation +// or set of instrumentations should not be applied. +#if DAWN_HAS_ATTRIBUTE(no_sanitize) +#define DAWN_NO_SANITIZE(instrumentation) __attribute__((no_sanitize(instrumentation))) +#else +#define DAWN_NO_SANITIZE(instrumentation) +#endif + +#endif // SRC_UTILS_COMPILER_H_ diff --git a/3rdparty/dawn/src/utils/numeric.h b/3rdparty/dawn/src/utils/numeric.h new file mode 100644 index 000000000..a0015fa6b --- /dev/null +++ b/3rdparty/dawn/src/utils/numeric.h @@ -0,0 +1,56 @@ +// Copyright 2025 The Dawn & Tint Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SRC_UTILS_NUMERIC_H_ +#define SRC_UTILS_NUMERIC_H_ + +#include +#include + +namespace dawn { +template +bool inline IsDoubleValueRepresentable(double value) { + if constexpr (std::is_same_v || std::is_integral_v) { + // Following WebIDL 3.3.6.[EnforceRange] for integral + // Following WebIDL 3.2.5.float for float + // TODO(crbug.com/1396194): now follows what blink does but may need revisit. + constexpr double kLowest = static_cast(std::numeric_limits::lowest()); + constexpr double kMax = static_cast(std::numeric_limits::max()); + return kLowest <= value && value <= kMax; + } else { + static_assert(std::is_same_v || std::is_integral_v, "Unsupported type"); + } +} + +inline bool IsDoubleValueRepresentableAsF16(double value) { + constexpr double kLowestF16 = -65504.0; + constexpr double kMaxF16 = 65504.0; + return kLowestF16 <= value && value <= kMaxF16; +} +} // namespace dawn + +#endif // SRC_UTILS_NUMERIC_H_ diff --git a/3rdparty/dawn/third_party/abseil-cpp/LICENSE b/3rdparty/dawn/third_party/abseil-cpp/LICENSE new file mode 100644 index 000000000..ccd61dcfe --- /dev/null +++ b/3rdparty/dawn/third_party/abseil-cpp/LICENSE @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + https://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. + diff --git a/3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/algorithm.h b/3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/algorithm.h new file mode 100644 index 000000000..48f59504d --- /dev/null +++ b/3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/algorithm.h @@ -0,0 +1,64 @@ +// Copyright 2017 The Abseil 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 +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: algorithm.h +// ----------------------------------------------------------------------------- +// +// This header file contains Google extensions to the standard C++ +// header. + +#ifndef ABSL_ALGORITHM_ALGORITHM_H_ +#define ABSL_ALGORITHM_ALGORITHM_H_ + +#include +#include +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// equal() +// rotate() +// +// Historical note: Abseil once provided implementations of these algorithms +// prior to their adoption in C++14. New code should prefer to use the std +// variants. +// +// See the documentation for the STL header for more information: +// https://en.cppreference.com/w/cpp/header/algorithm +using std::equal; +using std::rotate; + +// linear_search() +// +// Performs a linear search for `value` using the iterator `first` up to +// but not including `last`, returning true if [`first`, `last`) contains an +// element equal to `value`. +// +// A linear search is of O(n) complexity which is guaranteed to make at most +// n = (`last` - `first`) comparisons. A linear search over short containers +// may be faster than a binary search, even when the container is sorted. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search( + InputIterator first, InputIterator last, const EqualityComparable& value) { + return std::find(first, last, value) != last; +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_ALGORITHM_ALGORITHM_H_ diff --git a/3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/container.h b/3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/container.h new file mode 100644 index 000000000..c0b8a10ae --- /dev/null +++ b/3rdparty/dawn/third_party/abseil-cpp/absl/algorithm/container.h @@ -0,0 +1,1864 @@ +// Copyright 2017 The Abseil 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 +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: container.h +// ----------------------------------------------------------------------------- +// +// This header file provides Container-based versions of algorithmic functions +// within the C++ standard library. The following standard library sets of +// functions are covered within this file: +// +// * Algorithmic functions +// * Algorithmic functions +// * functions +// +// The standard library functions operate on iterator ranges; the functions +// within this API operate on containers, though many return iterator ranges. +// +// All functions within this API are named with a `c_` prefix. Calls such as +// `absl::c_xx(container, ...) are equivalent to std:: functions such as +// `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on +// iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`) +// have no equivalent here. +// +// For template parameter and variable naming, `C` indicates the container type +// to which the function is applied, `Pred` indicates the predicate object type +// to be used by the function and `T` indicates the applicable element type. + +#ifndef ABSL_ALGORITHM_CONTAINER_H_ +#define ABSL_ALGORITHM_CONTAINER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/algorithm/algorithm.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/meta/type_traits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace container_algorithm_internal { + +// NOTE: it is important to defer to ADL lookup for building with C++ modules, +// especially for headers like which are not visible from this file +// but specialize std::begin and std::end. +using std::begin; +using std::end; + +// The type of the iterator given by begin(c) (possibly std::begin(c)). +// ContainerIter> gives vector::const_iterator, +// while ContainerIter> gives vector::iterator. +template +using ContainerIter = decltype(begin(std::declval())); + +// An MSVC bug involving template parameter substitution requires us to use +// decltype() here instead of just std::pair. +template +using ContainerIterPairType = decltype(std::make_pair( + std::declval>(), std::declval>())); + +template +using ContainerDifferenceType = decltype(std::distance( + std::declval>(), std::declval>())); + +template +using ContainerPointerType = + typename std::iterator_traits>::pointer; + +// container_algorithm_internal::c_begin and +// container_algorithm_internal::c_end are abbreviations for proper ADL +// lookup of std::begin and std::end, i.e. +// using std::begin; +// using std::end; +// std::foo(begin(c), end(c)); +// becomes +// std::foo(container_algorithm_internal::c_begin(c), +// container_algorithm_internal::c_end(c)); +// These are meant for internal use only. + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { + return begin(c); +} + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { + return end(c); +} + +template +struct IsUnorderedContainer : std::false_type {}; + +template +struct IsUnorderedContainer< + std::unordered_map> : std::true_type {}; + +template +struct IsUnorderedContainer> + : std::true_type {}; + +} // namespace container_algorithm_internal + +// PUBLIC API + +//------------------------------------------------------------------------------ +// Abseil algorithm.h functions +//------------------------------------------------------------------------------ + +// c_linear_search() +// +// Container-based version of absl::linear_search() for performing a linear +// search within a container. +// +// For a generalization that uses a predicate, see absl::c_any_of(). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search( + const C& c, EqualityComparable&& value) { + return absl::linear_search(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +//------------------------------------------------------------------------------ +// algorithms +//------------------------------------------------------------------------------ + +// c_distance() +// +// Container-based version of the `std::distance()` function to +// return the number of elements within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerDifferenceType + c_distance(const C& c) { + return std::distance(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +//------------------------------------------------------------------------------ +// Non-modifying sequence operations +//------------------------------------------------------------------------------ + +// c_all_of() +// +// Container-based version of the `std::all_of()` function to +// test if all elements within a container satisfy a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) { + return std::all_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_any_of() +// +// Container-based version of the `std::any_of()` function to +// test if any element in a container fulfills a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) { + return std::any_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_none_of() +// +// Container-based version of the `std::none_of()` function to +// test if no elements in a container fulfill a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) { + return std::none_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_for_each() +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_for_each(C&& c, + Function&& f) { + return std::for_each(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(f)); +} + +// c_find() +// +// Container-based version of the `std::find()` function to find +// the first element containing the passed value within a container value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find(C& c, T&& value) { + return std::find(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +// c_contains() +// +// Container-based version of the `std::ranges::contains()` C++23 +// function to search a container for a value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence, + T&& value) { + return absl::c_find(sequence, std::forward(value)) != + container_algorithm_internal::c_end(sequence); +} + +// c_find_if() +// +// Container-based version of the `std::find_if()` function to find +// the first element in a container matching the given condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if(C& c, Pred&& pred) { + return std::find_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_find_if_not() +// +// Container-based version of the `std::find_if_not()` function to +// find the first element in a container not matching the given condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if_not(C& c, Pred&& pred) { + return std::find_if_not(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_find_end() +// +// Container-based version of the `std::find_end()` function to +// find the last subsequence within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence) { + return std::find_end(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence)); +} + +// Overload of c_find_end() for using a predicate evaluation other than `==` as +// the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return std::find_end(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence), + std::forward(pred)); +} + +// c_find_first_of() +// +// Container-based version of the `std::find_first_of()` function to +// find the first element within the container that is also within the options +// container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, const C2& options) { + return std::find_first_of(container_algorithm_internal::c_begin(container), + container_algorithm_internal::c_end(container), + container_algorithm_internal::c_begin(options), + container_algorithm_internal::c_end(options)); +} + +// Overload of c_find_first_of() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) { + return std::find_first_of(container_algorithm_internal::c_begin(container), + container_algorithm_internal::c_end(container), + container_algorithm_internal::c_begin(options), + container_algorithm_internal::c_end(options), + std::forward(pred)); +} + +// c_adjacent_find() +// +// Container-based version of the `std::adjacent_find()` function to +// find equal adjacent elements within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence) { + return std::adjacent_find(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_adjacent_find() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) { + return std::adjacent_find(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(pred)); +} + +// c_count() +// +// Container-based version of the `std::count()` function to count +// values that match within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count(const C& c, T&& value) { + return std::count(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +// c_count_if() +// +// Container-based version of the `std::count_if()` function to +// count values matching a condition within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count_if(const C& c, Pred&& pred) { + return std::count_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_mismatch() +// +// Container-based version of the `std::mismatch()` function to +// return the first element where two ordered containers differ. Applies `==` to +// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2) { + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_mismatch() for using a predicate evaluation other than `==` as +// the function's test condition. Applies `pred`to the first N elements of `c1` +// and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) { + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), pred); +} + +// c_equal() +// +// Container-based version of the `std::equal()` function to +// test whether two containers are equal. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) { + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_equal() for using a predicate evaluation other than `==` as +// the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2, + BinaryPredicate&& pred) { + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(pred)); +} + +// c_is_permutation() +// +// Container-based version of the `std::is_permutation()` function +// to test whether a container is a permutation of another. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1, + const C2& c2) { + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_is_permutation() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation( + const C1& c1, const C2& c2, BinaryPredicate&& pred) { + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(pred)); +} + +// c_search() +// +// Container-based version of the `std::search()` function to search +// a container for a subsequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence) { + return std::search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence)); +} + +// Overload of c_search() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return std::search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence), + std::forward(pred)); +} + +// c_contains_subrange() +// +// Container-based version of the `std::ranges::contains_subrange()` +// C++23 function to search a container for a subsequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence) { + return absl::c_search(sequence, subsequence) != + container_algorithm_internal::c_end(sequence); +} + +// Overload of c_contains_subrange() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { + return absl::c_search(sequence, subsequence, + std::forward(pred)) != + container_algorithm_internal::c_end(sequence); +} + +// c_search_n() +// +// Container-based version of the `std::search_n()` function to +// search a container for the first sequence of N elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value) { + return std::search_n(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), count, + std::forward(value)); +} + +// Overload of c_search_n() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value, + BinaryPredicate&& pred) { + return std::search_n(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), count, + std::forward(value), + std::forward(pred)); +} + +//------------------------------------------------------------------------------ +// Modifying sequence operations +//------------------------------------------------------------------------------ + +// c_copy() +// +// Container-based version of the `std::copy()` function to copy a +// container's elements into an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_copy(const InputSequence& input, OutputIterator output) { + return std::copy(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output); +} + +// c_copy_n() +// +// Container-based version of the `std::copy_n()` function to copy a +// container's first N elements into an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_copy_n(const C& input, Size n, OutputIterator output) { + return std::copy_n(container_algorithm_internal::c_begin(input), n, output); +} + +// c_copy_if() +// +// Container-based version of the `std::copy_if()` function to copy +// a container's elements satisfying some condition into an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_copy_if(const InputSequence& input, OutputIterator output, Pred&& pred) { + return std::copy_if(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output, + std::forward(pred)); +} + +// c_copy_backward() +// +// Container-based version of the `std::copy_backward()` function to +// copy a container's elements in reverse order into an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 BidirectionalIterator +c_copy_backward(const C& src, BidirectionalIterator dest) { + return std::copy_backward(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_move() +// +// Container-based version of the `std::move()` function to move +// a container's elements into an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_move(C&& src, + OutputIterator dest) { + return std::move(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_move_backward() +// +// Container-based version of the `std::move_backward()` function to +// move a container's elements into an iterator in reverse order. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 BidirectionalIterator +c_move_backward(C&& src, BidirectionalIterator dest) { + return std::move_backward(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_swap_ranges() +// +// Container-based version of the `std::swap_ranges()` function to +// swap a container's elements with another container's elements. Swaps the +// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_swap_ranges(C1& c1, C2& c2) { + auto first1 = container_algorithm_internal::c_begin(c1); + auto last1 = container_algorithm_internal::c_end(c1); + auto first2 = container_algorithm_internal::c_begin(c2); + auto last2 = container_algorithm_internal::c_end(c2); + + using std::swap; + for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { + swap(*first1, *first2); + } + return first2; +} + +// c_transform() +// +// Container-based version of the `std::transform()` function to +// transform a container's elements using the unary operation, storing the +// result in an iterator pointing to the last transformed element in the output +// range. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_transform( + const InputSequence& input, OutputIterator output, UnaryOp&& unary_op) { + return std::transform(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output, + std::forward(unary_op)); +} + +// Overload of c_transform() for performing a transformation using a binary +// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`, +// where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_transform(const InputSequence1& input1, const InputSequence2& input2, + OutputIterator output, BinaryOp&& binary_op) { + auto first1 = container_algorithm_internal::c_begin(input1); + auto last1 = container_algorithm_internal::c_end(input1); + auto first2 = container_algorithm_internal::c_begin(input2); + auto last2 = container_algorithm_internal::c_end(input2); + for (; first1 != last1 && first2 != last2; + ++first1, (void)++first2, ++output) { + *output = binary_op(*first1, *first2); + } + + return output; +} + +// c_replace() +// +// Container-based version of the `std::replace()` function to +// replace a container's elements of some value with a new value. The container +// is modified in place. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_replace(Sequence& sequence, + const T& old_value, + const T& new_value) { + std::replace(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), old_value, + new_value); +} + +// c_replace_if() +// +// Container-based version of the `std::replace_if()` function to +// replace a container's elements of some value with a new value based on some +// condition. The container is modified in place. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_replace_if(C& c, Pred&& pred, + T&& new_value) { + std::replace_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred), std::forward(new_value)); +} + +// c_replace_copy() +// +// Container-based version of the `std::replace_copy()` function to +// replace a container's elements of some value with a new value and return the +// results within an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_replace_copy( + const C& c, OutputIterator result, T&& old_value, T&& new_value) { + return std::replace_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(old_value), + std::forward(new_value)); +} + +// c_replace_copy_if() +// +// Container-based version of the `std::replace_copy_if()` function +// to replace a container's elements of some value with a new value based on +// some condition, and return the results within an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_replace_copy_if( + const C& c, OutputIterator result, Pred&& pred, const T& new_value) { + return std::replace_copy_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred), new_value); +} + +// c_fill() +// +// Container-based version of the `std::fill()` function to fill a +// container with some value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_fill(C& c, const T& value) { + std::fill(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), value); +} + +// c_fill_n() +// +// Container-based version of the `std::fill_n()` function to fill +// the first N elements in a container with some value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_fill_n(C& c, Size n, + const T& value) { + std::fill_n(container_algorithm_internal::c_begin(c), n, value); +} + +// c_generate() +// +// Container-based version of the `std::generate()` function to +// assign a container's elements to the values provided by the given generator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_generate(C& c, Generator&& gen) { + std::generate(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(gen)); +} + +// c_generate_n() +// +// Container-based version of the `std::generate_n()` function to +// assign a container's first N elements to the values provided by the given +// generator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_generate_n(C& c, Size n, Generator&& gen) { + return std::generate_n(container_algorithm_internal::c_begin(c), n, + std::forward(gen)); +} + +// Note: `c_xx()` container versions for `remove()`, `remove_if()`, +// and `unique()` are omitted, because it's not clear whether or not such +// functions should call erase on their supplied sequences afterwards. Either +// behavior would be surprising for a different set of users. + +// c_remove_copy() +// +// Container-based version of the `std::remove_copy()` function to +// copy a container's elements while removing any elements matching the given +// `value`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_remove_copy(const C& c, OutputIterator result, const T& value) { + return std::remove_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + value); +} + +// c_remove_copy_if() +// +// Container-based version of the `std::remove_copy_if()` function +// to copy a container's elements while removing any elements matching the given +// condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_remove_copy_if(const C& c, OutputIterator result, Pred&& pred) { + return std::remove_copy_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred)); +} + +// c_unique_copy() +// +// Container-based version of the `std::unique_copy()` function to +// copy a container's elements while removing any elements containing duplicate +// values. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_unique_copy(const C& c, OutputIterator result) { + return std::unique_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result); +} + +// Overload of c_unique_copy() for using a predicate evaluation other than +// `==` for comparing uniqueness of the element values. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_unique_copy(const C& c, OutputIterator result, BinaryPredicate&& pred) { + return std::unique_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred)); +} + +// c_reverse() +// +// Container-based version of the `std::reverse()` function to +// reverse a container's elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_reverse(Sequence& sequence) { + std::reverse(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// c_reverse_copy() +// +// Container-based version of the `std::reverse()` function to +// reverse a container's elements and write them to an iterator range. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_reverse_copy(const C& sequence, OutputIterator result) { + return std::reverse_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + result); +} + +// c_rotate() +// +// Container-based version of the `std::rotate()` function to +// shift a container's elements leftward such that the `middle` element becomes +// the first element in the container. +template > +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 Iterator c_rotate(C& sequence, + Iterator middle) { + return absl::rotate(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence)); +} + +// c_rotate_copy() +// +// Container-based version of the `std::rotate_copy()` function to +// shift a container's elements leftward such that the `middle` element becomes +// the first element in a new iterator range. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_rotate_copy(const C& sequence, + container_algorithm_internal::ContainerIter middle, + OutputIterator result) { + return std::rotate_copy(container_algorithm_internal::c_begin(sequence), + middle, container_algorithm_internal::c_end(sequence), + result); +} + +// c_shuffle() +// +// Container-based version of the `std::shuffle()` function to +// randomly shuffle elements within the container using a `gen()` uniform random +// number generator. +template +void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { + std::shuffle(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(gen)); +} + +// c_sample() +// +// Container-based version of the `std::sample()` function to +// randomly sample elements from the container without replacement using a +// `gen()` uniform random number generator and write them to an iterator range. +template +OutputIterator c_sample(const C& c, OutputIterator result, Distance n, + UniformRandomBitGenerator&& gen) { + return std::sample(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, n, + std::forward(gen)); +} + +//------------------------------------------------------------------------------ +// Partition functions +//------------------------------------------------------------------------------ + +// c_is_partitioned() +// +// Container-based version of the `std::is_partitioned()` function +// to test whether all elements in the container for which `pred` returns `true` +// precede those for which `pred` is `false`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_partitioned(const C& c, + Pred&& pred) { + return std::is_partitioned(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_partition() +// +// Container-based version of the `std::partition()` function +// to rearrange all elements in a container in such a way that all elements for +// which `pred` returns `true` precede all those for which it returns `false`, +// returning an iterator to the first element of the second group. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_partition(C& c, Pred&& pred) { + return std::partition(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_stable_partition() +// +// Container-based version of the `std::stable_partition()` function +// to rearrange all elements in a container in such a way that all elements for +// which `pred` returns `true` precede all those for which it returns `false`, +// preserving the relative ordering between the two groups. The function returns +// an iterator to the first element of the second group. +template +container_algorithm_internal::ContainerIter c_stable_partition(C& c, + Pred&& pred) { + return std::stable_partition(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_partition_copy() +// +// Container-based version of the `std::partition_copy()` function +// to partition a container's elements and return them into two iterators: one +// for which `pred` returns `true`, and one for which `pred` returns `false.` + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::pair +c_partition_copy(const C& c, OutputIterator1 out_true, + OutputIterator2 out_false, Pred&& pred) { + return std::partition_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), out_true, + out_false, std::forward(pred)); +} + +// c_partition_point() +// +// Container-based version of the `std::partition_point()` function +// to return the first element of an already partitioned container for which +// the given `pred` is not `true`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_partition_point(C& c, Pred&& pred) { + return std::partition_point(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +//------------------------------------------------------------------------------ +// Sorting functions +//------------------------------------------------------------------------------ + +// c_sort() +// +// Container-based version of the `std::sort()` function +// to sort elements in ascending order of their values. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort(C& c) { + std::sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_sort() for performing a `comp` comparison other than the +// default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort(C& c, LessThan&& comp) { + std::sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_stable_sort() +// +// Container-based version of the `std::stable_sort()` function +// to sort elements in ascending order of their values, preserving the order +// of equivalents. +template +void c_stable_sort(C& c) { + std::stable_sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_stable_sort() for performing a `comp` comparison other than the +// default `operator<`. +template +void c_stable_sort(C& c, LessThan&& comp) { + std::stable_sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_is_sorted() +// +// Container-based version of the `std::is_sorted()` function +// to evaluate whether the given container is sorted in ascending order. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_sorted(const C& c) { + return std::is_sorted(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// c_is_sorted() overload for performing a `comp` comparison other than the +// default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_sorted(const C& c, + LessThan&& comp) { + return std::is_sorted(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_partial_sort() +// +// Container-based version of the `std::partial_sort()` function +// to rearrange elements within a container such that elements before `middle` +// are sorted in ascending order. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_partial_sort( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter middle) { + std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_partial_sort() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_partial_sort( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter middle, + LessThan&& comp) { + std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_partial_sort_copy() +// +// Container-based version of the `std::partial_sort_copy()` +// function to sort the elements in the given range `result` within the larger +// `sequence` in ascending order (and using `result` as the output parameter). +// At most min(result.last - result.first, sequence.last - sequence.first) +// elements from the sequence will be stored in the result. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) { + return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(result), + container_algorithm_internal::c_end(result)); +} + +// Overload of c_partial_sort_copy() for performing a `comp` comparison other +// than the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_partial_sort_copy(const C& sequence, RandomAccessContainer& result, + LessThan&& comp) { + return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(result), + container_algorithm_internal::c_end(result), + std::forward(comp)); +} + +// c_is_sorted_until() +// +// Container-based version of the `std::is_sorted_until()` function +// to return the first element within a container that is not sorted in +// ascending order as an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_is_sorted_until(C& c) { + return std::is_sorted_until(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_is_sorted_until() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_is_sorted_until(C& c, LessThan&& comp) { + return std::is_sorted_until(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_nth_element() +// +// Container-based version of the `std::nth_element()` function +// to rearrange the elements within a container such that the `nth` element +// would be in that position in an ordered sequence; other elements may be in +// any order, except that all preceding `nth` will be less than that element, +// and all following `nth` will be greater than that element. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_nth_element( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter nth) { + std::nth_element(container_algorithm_internal::c_begin(sequence), nth, + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_nth_element() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_nth_element( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter nth, + LessThan&& comp) { + std::nth_element(container_algorithm_internal::c_begin(sequence), nth, + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Binary Search +//------------------------------------------------------------------------------ + +// c_lower_bound() +// +// Container-based version of the `std::lower_bound()` function +// to return an iterator pointing to the first element in a sorted container +// which does not compare less than `value`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_lower_bound(Sequence& sequence, const T& value) { + return std::lower_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_lower_bound() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_lower_bound(Sequence& sequence, const T& value, LessThan&& comp) { + return std::lower_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_upper_bound() +// +// Container-based version of the `std::upper_bound()` function +// to return an iterator pointing to the first element in a sorted container +// which is greater than `value`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_upper_bound(Sequence& sequence, const T& value) { + return std::upper_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_upper_bound() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_upper_bound(Sequence& sequence, const T& value, LessThan&& comp) { + return std::upper_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_equal_range() +// +// Container-based version of the `std::equal_range()` function +// to return an iterator pair pointing to the first and last elements in a +// sorted container which compare equal to `value`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_equal_range(Sequence& sequence, const T& value) { + return std::equal_range(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_equal_range() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) { + return std::equal_range(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_binary_search() +// +// Container-based version of the `std::binary_search()` function +// to test if any element in the sorted container contains a value equivalent to +// 'value'. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_binary_search( + const Sequence& sequence, const T& value) { + return std::binary_search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + value); +} + +// Overload of c_binary_search() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_binary_search( + const Sequence& sequence, const T& value, LessThan&& comp) { + return std::binary_search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + value, std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Merge functions +//------------------------------------------------------------------------------ + +// c_merge() +// +// Container-based version of the `std::merge()` function +// to merge two sorted containers into a single sorted iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_merge(const C1& c1, const C2& c2, OutputIterator result) { + return std::merge(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), result); +} + +// Overload of c_merge() for performing a `comp` comparison other than +// the default `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_merge(const C1& c1, const C2& c2, OutputIterator result, LessThan&& comp) { + return std::merge(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), result, + std::forward(comp)); +} + +// c_inplace_merge() +// +// Container-based version of the `std::inplace_merge()` function +// to merge a supplied iterator `middle` into a container. +template +void c_inplace_merge(C& c, + container_algorithm_internal::ContainerIter middle) { + std::inplace_merge(container_algorithm_internal::c_begin(c), middle, + container_algorithm_internal::c_end(c)); +} + +// Overload of c_inplace_merge() for performing a merge using a `comp` other +// than `operator<`. +template +void c_inplace_merge(C& c, + container_algorithm_internal::ContainerIter middle, + LessThan&& comp) { + std::inplace_merge(container_algorithm_internal::c_begin(c), middle, + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_includes() +// +// Container-based version of the `std::includes()` function +// to test whether a sorted container `c1` entirely contains another sorted +// container `c2`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_includes(const C1& c1, + const C2& c2) { + return std::includes(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_includes() for performing a merge using a `comp` other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_includes(const C1& c1, const C2& c2, + LessThan&& comp) { + return std::includes(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(comp)); +} + +// c_set_union() +// +// Container-based version of the `std::set_union()` function +// to return an iterator containing the union of two containers; duplicate +// values are not copied into the output. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_set_union(const C1& c1, const C2& c2, OutputIterator output) { + return std::set_union(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_union() for performing a merge using a `comp` other than +// `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_union( + const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { + return std::set_union(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_intersection() +// +// Container-based version of the `std::set_intersection()` function +// to return an iterator containing the intersection of two sorted containers. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_set_intersection(const C1& c1, const C2& c2, OutputIterator output) { + // In debug builds, ensure that both containers are sorted with respect to the + // default comparator. std::set_intersection requires the containers be sorted + // using operator<. + ABSL_ASSERT(absl::c_is_sorted(c1)); + ABSL_ASSERT(absl::c_is_sorted(c2)); + return std::set_intersection(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_intersection() for performing a merge using a `comp` other +// than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_intersection( + const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { + // In debug builds, ensure that both containers are sorted with respect to the + // default comparator. std::set_intersection requires the containers be sorted + // using the same comparator. + ABSL_ASSERT(absl::c_is_sorted(c1, comp)); + ABSL_ASSERT(absl::c_is_sorted(c2, comp)); + return std::set_intersection(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_difference() +// +// Container-based version of the `std::set_difference()` function +// to return an iterator containing elements present in the first container but +// not in the second. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_set_difference(const C1& c1, const C2& c2, OutputIterator output) { + return std::set_difference(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_difference() for performing a merge using a `comp` other +// than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_difference( + const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { + return std::set_difference(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_symmetric_difference() +// +// Container-based version of the `std::set_symmetric_difference()` +// function to return an iterator containing elements present in either one +// container or the other, but not both. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator +c_set_symmetric_difference(const C1& c1, const C2& c2, OutputIterator output) { + return std::set_symmetric_difference( + container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_symmetric_difference() for performing a merge using a +// `comp` other than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIterator c_set_symmetric_difference( + const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { + return std::set_symmetric_difference( + container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Heap functions +//------------------------------------------------------------------------------ + +// c_push_heap() +// +// Container-based version of the `std::push_heap()` function +// to push a value onto a container heap. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_push_heap( + RandomAccessContainer& sequence) { + std::push_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_push_heap() for performing a push operation on a heap using a +// `comp` other than `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_push_heap( + RandomAccessContainer& sequence, LessThan&& comp) { + std::push_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_pop_heap() +// +// Container-based version of the `std::pop_heap()` function +// to pop a value from a heap container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_pop_heap( + RandomAccessContainer& sequence) { + std::pop_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_pop_heap() for performing a pop operation on a heap using a +// `comp` other than `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_pop_heap( + RandomAccessContainer& sequence, LessThan&& comp) { + std::pop_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_make_heap() +// +// Container-based version of the `std::make_heap()` function +// to make a container a heap. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_make_heap( + RandomAccessContainer& sequence) { + std::make_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_make_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_make_heap( + RandomAccessContainer& sequence, LessThan&& comp) { + std::make_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_sort_heap() +// +// Container-based version of the `std::sort_heap()` function +// to sort a heap into ascending order (after which it is no longer a heap). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort_heap( + RandomAccessContainer& sequence) { + std::sort_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_sort_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_sort_heap( + RandomAccessContainer& sequence, LessThan&& comp) { + std::sort_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_is_heap() +// +// Container-based version of the `std::is_heap()` function +// to check whether the given container is a heap. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_heap( + const RandomAccessContainer& sequence) { + return std::is_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_is_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_heap( + const RandomAccessContainer& sequence, LessThan&& comp) { + return std::is_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_is_heap_until() +// +// Container-based version of the `std::is_heap_until()` function +// to find the first element in a given container which is not in heap order. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_is_heap_until(RandomAccessContainer& sequence) { + return std::is_heap_until(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_is_heap_until() for performing heap comparisons using a +// `comp` other than `operator<` +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) { + return std::is_heap_until(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Min/max +//------------------------------------------------------------------------------ + +// c_min_element() +// +// Container-based version of the `std::min_element()` function +// to return an iterator pointing to the element with the smallest value, using +// `operator<` to make the comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence) { + return std::min_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_min_element() for performing a `comp` comparison other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence, LessThan&& comp) { + return std::min_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_max_element() +// +// Container-based version of the `std::max_element()` function +// to return an iterator pointing to the element with the largest value, using +// `operator<` to make the comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence) { + return std::max_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_max_element() for performing a `comp` comparison other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence, LessThan&& comp) { + return std::max_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_minmax_element() +// +// Container-based version of the `std::minmax_element()` function +// to return a pair of iterators pointing to the elements containing the +// smallest and largest values, respectively, using `operator<` to make the +// comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c) { + return std::minmax_element(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_minmax_element() for performing `comp` comparisons other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c, LessThan&& comp) { + return std::minmax_element(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Lexicographical Comparisons +//------------------------------------------------------------------------------ + +// c_lexicographical_compare() +// +// Container-based version of the `std::lexicographical_compare()` +// function to lexicographically compare (e.g. sort words alphabetically) two +// container sequences. The comparison is performed using `operator<`. Note +// that capital letters ("A-Z") have ASCII values less than lowercase letters +// ("a-z"). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_lexicographical_compare( + const Sequence1& sequence1, const Sequence2& sequence2) { + return std::lexicographical_compare( + container_algorithm_internal::c_begin(sequence1), + container_algorithm_internal::c_end(sequence1), + container_algorithm_internal::c_begin(sequence2), + container_algorithm_internal::c_end(sequence2)); +} + +// Overload of c_lexicographical_compare() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_lexicographical_compare( + const Sequence1& sequence1, const Sequence2& sequence2, LessThan&& comp) { + return std::lexicographical_compare( + container_algorithm_internal::c_begin(sequence1), + container_algorithm_internal::c_end(sequence1), + container_algorithm_internal::c_begin(sequence2), + container_algorithm_internal::c_end(sequence2), + std::forward(comp)); +} + +// c_next_permutation() +// +// Container-based version of the `std::next_permutation()` function +// to rearrange a container's elements into the next lexicographically greater +// permutation. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_next_permutation(C& c) { + return std::next_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_next_permutation() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_next_permutation(C& c, + LessThan&& comp) { + return std::next_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_prev_permutation() +// +// Container-based version of the `std::prev_permutation()` function +// to rearrange a container's elements into the next lexicographically lesser +// permutation. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_prev_permutation(C& c) { + return std::prev_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_prev_permutation() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_prev_permutation(C& c, + LessThan&& comp) { + return std::prev_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// algorithms +//------------------------------------------------------------------------------ + +// c_iota() +// +// Container-based version of the `std::iota()` function +// to compute successive values of `value`, as if incremented with `++value` +// after each element is written, and write them to the container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 void c_iota(Sequence& sequence, + const T& value) { + std::iota(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// c_accumulate() +// +// Container-based version of the `std::accumulate()` function +// to accumulate the element values of a container to `init` and return that +// accumulation by value. +// +// Note: Due to a language technicality this function has return type +// absl::decay_t. As a user of this function you can casually read +// this as "returns T by value" and assume it does the right thing. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_accumulate( + const Sequence& sequence, T&& init) { + return std::accumulate(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(init)); +} + +// Overload of c_accumulate() for using a binary operations other than +// addition for computing the accumulation. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_accumulate( + const Sequence& sequence, T&& init, BinaryOp&& binary_op) { + return std::accumulate(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(init), + std::forward(binary_op)); +} + +// c_inner_product() +// +// Container-based version of the `std::inner_product()` function +// to compute the cumulative inner product of container element pairs. +// +// Note: Due to a language technicality this function has return type +// absl::decay_t. As a user of this function you can casually read +// this as "returns T by value" and assume it does the right thing. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_inner_product( + const Sequence1& factors1, const Sequence2& factors2, T&& sum) { + return std::inner_product(container_algorithm_internal::c_begin(factors1), + container_algorithm_internal::c_end(factors1), + container_algorithm_internal::c_begin(factors2), + std::forward(sum)); +} + +// Overload of c_inner_product() for using binary operations other than +// `operator+` (for computing the accumulation) and `operator*` (for computing +// the product between the two container's element pair). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_inner_product( + const Sequence1& factors1, const Sequence2& factors2, T&& sum, + BinaryOp1&& op1, BinaryOp2&& op2) { + return std::inner_product(container_algorithm_internal::c_begin(factors1), + container_algorithm_internal::c_end(factors1), + container_algorithm_internal::c_begin(factors2), + std::forward(sum), std::forward(op1), + std::forward(op2)); +} + +// c_adjacent_difference() +// +// Container-based version of the `std::adjacent_difference()` +// function to compute the difference between each element and the one preceding +// it and write it to an iterator. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt +c_adjacent_difference(const InputSequence& input, OutputIt output_first) { + return std::adjacent_difference(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first); +} + +// Overload of c_adjacent_difference() for using a binary operation other than +// subtraction to compute the adjacent difference. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt c_adjacent_difference( + const InputSequence& input, OutputIt output_first, BinaryOp&& op) { + return std::adjacent_difference(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first, std::forward(op)); +} + +// c_partial_sum() +// +// Container-based version of the `std::partial_sum()` function +// to compute the partial sum of the elements in a sequence and write them +// to an iterator. The partial sum is the sum of all element values so far in +// the sequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt +c_partial_sum(const InputSequence& input, OutputIt output_first) { + return std::partial_sum(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first); +} + +// Overload of c_partial_sum() for using a binary operation other than addition +// to compute the "partial sum". +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 OutputIt c_partial_sum( + const InputSequence& input, OutputIt output_first, BinaryOp&& op) { + return std::partial_sum(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first, std::forward(op)); +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_ALGORITHM_CONTAINER_H_ diff --git a/3rdparty/dawn/third_party/abseil-cpp/absl/base/attributes.h b/3rdparty/dawn/third_party/abseil-cpp/absl/base/attributes.h new file mode 100644 index 000000000..33b2c2849 --- /dev/null +++ b/3rdparty/dawn/third_party/abseil-cpp/absl/base/attributes.h @@ -0,0 +1,1077 @@ +// Copyright 2017 The Abseil 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 +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This header file defines macros for declaring attributes for functions, +// types, and variables. +// +// These macros are used within Abseil and allow the compiler to optimize, where +// applicable, certain function calls. +// +// Most macros here are exposing GCC or Clang features, and are stubbed out for +// other compilers. +// +// GCC attributes documentation: +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html +// +// Most attributes in this file are already supported by GCC 4.7. However, some +// of them are not supported in older version of Clang. Thus, we check +// `__has_attribute()` first. If the check fails, we check if we are on GCC and +// assume the attribute exists on GCC (which is verified on GCC 4.7). + +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + +#ifndef ABSL_BASE_ATTRIBUTES_H_ +#define ABSL_BASE_ATTRIBUTES_H_ + +#include "absl/base/config.h" + +// ABSL_HAVE_ATTRIBUTE +// +// A function-like feature checking macro that is a wrapper around +// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a +// nonzero constant integer if the attribute is supported or 0 if not. +// +// It evaluates to zero if `__has_attribute` is not defined by the compiler. +// +// GCC: https://gcc.gnu.org/gcc-5/changes.html +// Clang: https://clang.llvm.org/docs/LanguageExtensions.html +#ifdef __has_attribute +#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) +#else +#define ABSL_HAVE_ATTRIBUTE(x) 0 +#endif + +// ABSL_HAVE_CPP_ATTRIBUTE +// +// A function-like feature checking macro that accepts C++11 style attributes. +// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 +// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't +// find `__has_cpp_attribute`, will evaluate to 0. +#if defined(__cplusplus) && defined(__has_cpp_attribute) +// NOTE: requiring __cplusplus above should not be necessary, but +// works around https://bugs.llvm.org/show_bug.cgi?id=23435. +#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 +#endif + +// ----------------------------------------------------------------------------- +// Function Attributes +// ----------------------------------------------------------------------------- +// +// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +// Clang: https://clang.llvm.org/docs/AttributeReference.html + +// ABSL_PRINTF_ATTRIBUTE +// ABSL_SCANF_ATTRIBUTE +// +// Tells the compiler to perform `printf` format string checking if the +// compiler supports it; see the 'format' attribute in +// . +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__scanf__, string_index, first_to_check))) +#else +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) +#endif + +// ABSL_ATTRIBUTE_ALWAYS_INLINE +// ABSL_ATTRIBUTE_NOINLINE +// +// Forces functions to either inline or not inline. Introduced in gcc 3.1. +#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 +#else +#define ABSL_ATTRIBUTE_ALWAYS_INLINE +#endif + +#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 +#else +#define ABSL_ATTRIBUTE_NOINLINE +#endif + +// ABSL_ATTRIBUTE_NO_TAIL_CALL +// +// Prevents the compiler from optimizing away stack frames for functions which +// end in a call to another function. +#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) +#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ + __attribute__((optimize("no-optimize-sibling-calls"))) +#else +#define ABSL_ATTRIBUTE_NO_TAIL_CALL +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 +#endif + +// ABSL_ATTRIBUTE_WEAK +// +// Tags a function as weak for the purposes of compilation and linking. +// Weak attributes did not work properly in LLVM's Windows backend before +// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 +// for further information. Weak attributes do not work across DLL boundary. +// The MinGW compiler doesn't complain about the weak attribute until the link +// step, presumably because Windows doesn't use ELF binaries. +#if (ABSL_HAVE_ATTRIBUTE(weak) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + (!defined(_WIN32) || \ + (defined(__clang__) && __clang_major__ >= 9 && \ + !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \ + !defined(__MINGW32__) +#undef ABSL_ATTRIBUTE_WEAK +#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) +#define ABSL_HAVE_ATTRIBUTE_WEAK 1 +#else +#define ABSL_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_WEAK 0 +#endif + +// ABSL_ATTRIBUTE_NONNULL +// +// Tells the compiler either (a) that a particular function parameter +// should be a non-null pointer, or (b) that all pointer arguments should +// be non-null. +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +// +// Args are indexed starting at 1. +// +// For non-static class member functions, the implicit `this` argument +// is arg 1, and the first explicit argument is arg 2. For static class member +// functions, there is no implicit `this`, and the first explicit argument is +// arg 1. +// +// Example: +// +// /* arg_a cannot be null, but arg_b can */ +// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); +// +// class C { +// /* arg_a cannot be null, but arg_b can */ +// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); +// +// /* arg_a cannot be null, but arg_b can */ +// static void StaticMethod(void* arg_a, void* arg_b) +// ABSL_ATTRIBUTE_NONNULL(1); +// }; +// +// If no arguments are provided, then all pointer arguments should be non-null. +// +// /* No pointer arguments may be null. */ +// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); +// +// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but +// ABSL_ATTRIBUTE_NONNULL does not. +#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) +#else +#define ABSL_ATTRIBUTE_NONNULL(...) +#endif + +// ABSL_ATTRIBUTE_NORETURN +// +// Tells the compiler that a given function never returns. +// +// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over +// this macro. +#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define ABSL_ATTRIBUTE_NORETURN +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +// +// Tells the AddressSanitizer (or other memory testing tools) to ignore a given +// function. Useful for cases when a function reads random locations on stack, +// calls _exit from a cloned subprocess, deliberately accesses buffer +// out of bounds or does other scary things with memory. +// NOTE: GCC supports AddressSanitizer(asan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ + ABSL_HAVE_ATTRIBUTE(no_sanitize_address) +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \ + _MSC_VER >= 1928 +// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) +#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize) +// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU +// features to detect similar bugs with less CPU and memory overhead. +// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11. +// https://gcc.gnu.org/gcc-11/changes.html +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \ + __attribute__((no_sanitize("hwaddress"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +// +// Tells the MemorySanitizer to relax the handling of a given function. All "Use +// of uninitialized value" warnings from such functions will be suppressed, and +// all values loaded from memory will be considered fully initialized. This +// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute +// above, but deals with initialized-ness rather than addressability issues. +// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +// +// Tells the ThreadSanitizer to not instrument a given function. +// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +// +// Tells the UndefinedSanitizer to ignore a given function. Useful for cases +// where certain behavior (eg. division by zero) is being used intentionally. +// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. +// https://gcc.gnu.org/gcc-4.9/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_CFI +// +// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. +// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__) +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +// +// Tells the SafeStack to not instrument a given function. +// See https://clang.llvm.org/docs/SafeStack.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ + __attribute__((no_sanitize("safe-stack"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +#endif + +// ABSL_ATTRIBUTE_RETURNS_NONNULL +// +// Tells the compiler that a particular function never returns a null pointer. +#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) +#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define ABSL_ATTRIBUTE_RETURNS_NONNULL +#endif + +// ABSL_HAVE_ATTRIBUTE_SECTION +// +// Indicates whether labeled sections are supported. Weak symbol support is +// a prerequisite. Labeled sections are not supported on Darwin/iOS. +#ifdef ABSL_HAVE_ATTRIBUTE_SECTION +#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set +#elif (ABSL_HAVE_ATTRIBUTE(section) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_SECTION 1 + +// ABSL_ATTRIBUTE_SECTION +// +// Tells the compiler/linker to put a given function into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. Any function annotated with +// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into +// whatever section its caller is placed into. +// +#ifndef ABSL_ATTRIBUTE_SECTION +#define ABSL_ATTRIBUTE_SECTION(name) \ + __attribute__((section(#name))) __attribute__((noinline)) +#endif + +// ABSL_ATTRIBUTE_SECTION_VARIABLE +// +// Tells the compiler/linker to put a given variable into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. +#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE +#ifdef _AIX +// __attribute__((section(#name))) on AIX is achieved by using the `.csect` +// pseudo op which includes an additional integer as part of its syntax +// indicating alignment. If data fall under different alignments then you might +// get a compilation error indicating a `Section type conflict`. +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#else +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) +#endif +#endif + +// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +// +// A weak section declaration to be used as a global declaration +// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link +// even without functions with ABSL_ATTRIBUTE_SECTION(name). +// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's +// a no-op on ELF but not on Mach-O. +// +#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ + extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ + extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK +#endif +#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#endif + +// ABSL_ATTRIBUTE_SECTION_START +// +// Returns `void*` pointers to start/end of a section of code with +// functions having ABSL_ATTRIBUTE_SECTION(name). +// Returns 0 if no such functions exist. +// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and +// link. +// +#define ABSL_ATTRIBUTE_SECTION_START(name) \ + (reinterpret_cast(__start_##name)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ + (reinterpret_cast(__stop_##name)) + +#else // !ABSL_HAVE_ATTRIBUTE_SECTION + +#define ABSL_HAVE_ATTRIBUTE_SECTION 0 + +// provide dummy definitions +#define ABSL_ATTRIBUTE_SECTION(name) +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) + +#endif // ABSL_ATTRIBUTE_SECTION + +// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +// +// Support for aligning the stack on 32-bit x86. +#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ + (defined(__GNUC__) && !defined(__clang__)) +#if defined(__i386__) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ + __attribute__((force_align_arg_pointer)) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#elif defined(__x86_64__) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#else // !__i386__ && !__x86_64 +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#endif // __i386__ +#else +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#endif + +// ABSL_MUST_USE_RESULT +// +// Tells the compiler to warn about unused results. +// +// For code or headers that are assured to only build with C++17 and up, prefer +// just using the standard `[[nodiscard]]` directly over this macro. +// +// When annotating a function, it must appear as the first part of the +// declaration or definition. The compiler will warn if the return value from +// such a function is unused: +// +// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); +// AllocateSprocket(); // Triggers a warning. +// +// When annotating a class, it is equivalent to annotating every function which +// returns an instance. +// +// class ABSL_MUST_USE_RESULT Sprocket {}; +// Sprocket(); // Triggers a warning. +// +// Sprocket MakeSprocket(); +// MakeSprocket(); // Triggers a warning. +// +// Note that references and pointers are not instances: +// +// Sprocket* SprocketPointer(); +// SprocketPointer(); // Does *not* trigger a warning. +// +// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result +// warning. For that, warn_unused_result is used only for clang but not for gcc. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 +// +// Note: past advice was to place the macro after the argument list. +// +// TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is +// compliant with the stricter [[nodiscard]]. +#if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) +#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD +// +// Tells GCC that a function is hot or cold. GCC can use this information to +// improve static analysis, i.e. a conditional branch to a cold function +// is likely to be not-taken. +// This annotation is used for function declarations. +// +// Example: +// +// int foo() ABSL_ATTRIBUTE_HOT; +#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) +#else +#define ABSL_ATTRIBUTE_HOT +#endif + +#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) +#else +#define ABSL_ATTRIBUTE_COLD +#endif + +// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS +// +// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT +// macro used as an attribute to mark functions that must always or never be +// instrumented by XRay. Currently, this is only supported in Clang/LLVM. +// +// For reference on the LLVM XRay instrumentation, see +// http://llvm.org/docs/XRay.html. +// +// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration +// will always get the XRay instrumentation sleds. These sleds may introduce +// some binary size and runtime overhead and must be used sparingly. +// +// These attributes only take effect when the following conditions are met: +// +// * The file/target is built in at least C++11 mode, with a Clang compiler +// that supports XRay attributes. +// * The file/target is built with the -fxray-instrument flag set for the +// Clang/LLVM compiler. +// * The function is defined in the translation unit (the compiler honors the +// attribute in either the definition or the declaration, and must match). +// +// There are cases when, even when building with XRay instrumentation, users +// might want to control specifically which functions are instrumented for a +// particular build using special-case lists provided to the compiler. These +// special case lists are provided to Clang via the +// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The +// attributes in source take precedence over these special-case lists. +// +// To disable the XRay attributes at build-time, users may define +// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific +// packages/targets, as this may lead to conflicting definitions of functions at +// link-time. +// +// XRay isn't currently supported on Android: +// https://github.com/android/ndk/issues/368 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ + !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) +#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] +#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) +#define ABSL_XRAY_LOG_ARGS(N) \ + [[clang::xray_always_instrument, clang::xray_log_args(N)]] +#else +#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] +#endif +#else +#define ABSL_XRAY_ALWAYS_INSTRUMENT +#define ABSL_XRAY_NEVER_INSTRUMENT +#define ABSL_XRAY_LOG_ARGS(N) +#endif + +// ABSL_ATTRIBUTE_REINITIALIZES +// +// Indicates that a member function reinitializes the entire object to a known +// state, independent of the previous state of the object. +// +// The clang-tidy check bugprone-use-after-move allows member functions marked +// with this attribute to be called on objects that have been moved from; +// without the attribute, this would result in a use-after-move warning. +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) +#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#else +#define ABSL_ATTRIBUTE_REINITIALIZES +#endif + +// ----------------------------------------------------------------------------- +// Variable Attributes +// ----------------------------------------------------------------------------- + +// ABSL_ATTRIBUTE_UNUSED +// +// Prevents the compiler from complaining about variables that appear unused. +// +// Deprecated: Use the standard C++17 `[[maybe_unused]]` instead. +// +// Due to differences in positioning requirements between the old, compiler +// specific __attribute__ syntax and the now standard `[[maybe_unused]]`, this +// macro does not attempt to take advantage of `[[maybe_unused]]`. +#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) +#undef ABSL_ATTRIBUTE_UNUSED +#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ABSL_ATTRIBUTE_UNUSED +#endif + +// ABSL_ATTRIBUTE_INITIAL_EXEC +// +// Tells the compiler to use "initial-exec" mode for a thread-local variable. +// See http://people.redhat.com/drepper/tls.pdf for the gory details. +#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) +#else +#define ABSL_ATTRIBUTE_INITIAL_EXEC +#endif + +// ABSL_ATTRIBUTE_PACKED +// +// Instructs the compiler not to use natural alignment for a tagged data +// structure, but instead to reduce its alignment to 1. +// +// Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing +// so can cause atomic variables to be mis-aligned and silently violate +// atomicity on x86. +// +// This attribute can either be applied to members of a structure or to a +// structure in its entirety. Applying this attribute (judiciously) to a +// structure in its entirety to optimize the memory footprint of very +// commonly-used structs is fine. Do not apply this attribute to a structure in +// its entirety if the purpose is to control the offsets of the members in the +// structure. Instead, apply this attribute only to structure members that need +// it. +// +// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the +// natural alignment of structure members not annotated is preserved. Aligned +// member accesses are faster than non-aligned member accesses even if the +// targeted microprocessor supports non-aligned accesses. +#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) +#else +#define ABSL_ATTRIBUTE_PACKED +#endif + +// ABSL_ATTRIBUTE_FUNC_ALIGN +// +// Tells the compiler to align the function start at least to certain +// alignment boundary +#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) +#endif + +// ABSL_FALLTHROUGH_INTENDED +// +// Annotates implicit fall-through between switch labels, allowing a case to +// indicate intentional fallthrough and turn off warnings about any lack of a +// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by +// a semicolon and can be used in most places where `break` can, provided that +// no statements exist between it and the next switch label. +// +// Example: +// +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations +// // in comments +// } else { +// return x; +// } +// case 42: +// ... +// +// Notes: When supported, GCC and Clang can issue a warning on switch labels +// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See +// clang documentation on language extensions for details: +// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough +// +// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has +// no effect on diagnostics. In any case this macro has no effect on runtime +// behavior and performance of code. + +#ifdef ABSL_FALLTHROUGH_INTENDED +#error "ABSL_FALLTHROUGH_INTENDED should not be defined." +#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#else +#define ABSL_FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +// ABSL_DEPRECATED() +// +// Marks a deprecated class, struct, enum, function, method and variable +// declarations. The macro argument is used as a custom diagnostic message (e.g. +// suggestion of a better alternative). +// +// For code or headers that are assured to only build with C++14 and up, prefer +// just using the standard `[[deprecated("message")]]` directly over this macro. +// +// Examples: +// +// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; +// +// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} +// +// template +// ABSL_DEPRECATED("Use DoThat() instead") +// void DoThis(); +// +// enum FooEnum { +// kBar ABSL_DEPRECATED("Use kBaz instead"), +// }; +// +// Every usage of a deprecated entity will trigger a warning when compiled with +// GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain +// turns this warning off by default, instead relying on clang-tidy to report +// new uses of deprecated code. +#if ABSL_HAVE_ATTRIBUTE(deprecated) +#define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) +#else +#define ABSL_DEPRECATED(message) +#endif + +// When deprecating Abseil code, it is sometimes necessary to turn off the +// warning within Abseil, until the deprecated code is actually removed. The +// deprecated code can be surrounded with these directives to achieve that +// result. +// +// class ABSL_DEPRECATED("Use Bar instead") Foo; +// +// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +// Baz ComputeBazFromFoo(Foo f); +// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#if defined(__GNUC__) || defined(__clang__) +// Clang also supports these GCC pragmas. +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("warning(push)") _Pragma("warning(disable: 4996)") +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("warning(pop)") +#else +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#endif // defined(__GNUC__) || defined(__clang__) + +// ABSL_CONST_INIT +// +// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will +// not compile (on supported platforms) unless the variable has a constant +// initializer. This is useful for variables with static and thread storage +// duration, because it guarantees that they will not suffer from the so-called +// "static init order fiasco". +// +// This attribute must be placed on the initializing declaration of the +// variable. Some compilers will give a -Wmissing-constinit warning when this +// attribute is placed on some other declaration but missing from the +// initializing declaration. +// +// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can +// also be used in a non-initializing declaration to tell the compiler that a +// variable is already initialized, reducing overhead that would otherwise be +// incurred by a hidden guard variable. Thus annotating all declarations with +// this attribute is recommended to potentially enhance optimization. +// +// Example: +// +// class MyClass { +// public: +// ABSL_CONST_INIT static MyType my_var; +// }; +// +// ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...); +// +// For code or headers that are assured to only build with C++20 and up, prefer +// just using the standard `constinit` keyword directly over this macro. +// +// Note that this attribute is redundant if the variable is declared constexpr. +#if defined(__cpp_constinit) && __cpp_constinit >= 201907L +#define ABSL_CONST_INIT constinit +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) +#define ABSL_CONST_INIT [[clang::require_constant_initialization]] +#else +#define ABSL_CONST_INIT +#endif + +// ABSL_REQUIRE_EXPLICIT_INIT +// +// ABSL_REQUIRE_EXPLICIT_INIT is placed *after* the data members of an aggregate +// type to indicate that the annotated member must be explicitly initialized by +// the user whenever the aggregate is constructed. For example: +// +// struct Coord { +// int x ABSL_REQUIRE_EXPLICIT_INIT; +// int y ABSL_REQUIRE_EXPLICIT_INIT; +// }; +// Coord coord = {1}; // warning: field 'y' is not explicitly initialized +// +// Note that usage on C arrays is not supported in C++. +// Use a struct (such as std::array) to wrap the array member instead. +// +// Avoid applying this attribute to the members of non-aggregate types. +// The behavior within non-aggregates is unspecified and subject to change. +// +// Do NOT attempt to suppress or demote the error generated by this attribute. +// Just like with a missing function argument, it is a hard error by design. +// +// See the upstream documentation for more details: +// https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization +#ifdef __cplusplus +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_explicit_initialization) +// clang-format off +#define ABSL_REQUIRE_EXPLICIT_INIT \ + [[clang::require_explicit_initialization]] = \ + AbslInternal_YouForgotToExplicitlyInitializeAField::v +#else +#define ABSL_REQUIRE_EXPLICIT_INIT \ + = AbslInternal_YouForgotToExplicitlyInitializeAField::v +#endif +// clang-format on +#else +// clang-format off +#if ABSL_HAVE_ATTRIBUTE(require_explicit_initialization) +#define ABSL_REQUIRE_EXPLICIT_INIT \ + __attribute__((require_explicit_initialization)) +#else +#define ABSL_REQUIRE_EXPLICIT_INIT \ + /* No portable fallback for C is available */ +#endif +// clang-format on +#endif + +#ifdef __cplusplus +struct AbslInternal_YouForgotToExplicitlyInitializeAField { + // A portable version of [[clang::require_explicit_initialization]] that + // never builds, as a last resort for all toolchains. + // The error messages are poor, so we don't rely on this unless we have to. + template +#if !defined(SWIG) + constexpr +#endif + operator T() const /* NOLINT */ { + const void *volatile deliberately_volatile_ptr = nullptr; + // Infinite loop to prevent constexpr compilation + for (;;) { + // This assignment ensures the 'this' pointer is not optimized away, so + // that linking always fails. + deliberately_volatile_ptr = this; // Deliberately not constexpr + (void)deliberately_volatile_ptr; + } + } + // This is deliberately left undefined to prevent linking + static AbslInternal_YouForgotToExplicitlyInitializeAField v; +}; +#endif + +// ABSL_ATTRIBUTE_PURE_FUNCTION +// +// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" +// functions. A function is pure if its return value is only a function of its +// arguments. The pure attribute prohibits a function from modifying the state +// of the program that is observable by means other than inspecting the +// function's return value. Declaring such functions with the pure attribute +// allows the compiler to avoid emitting some calls in repeated invocations of +// the function with the same argument values. +// +// Example: +// +// ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t); +#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] +#elif ABSL_HAVE_ATTRIBUTE(pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) +#else +// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since +// pure functions are useless if its return is ignored. +#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_CONST_FUNCTION +// +// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const" +// functions. A const function is similar to a pure function, with one +// exception: Pure functions may return value that depend on a non-volatile +// object that isn't provided as a function argument, while the const function +// is guaranteed to return the same result given the same arguments. +// +// Example: +// +// ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d); +#if defined(_MSC_VER) && !defined(__clang__) +// Put the MSVC case first since MSVC seems to parse const as a C++ keyword. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]] +#elif ABSL_HAVE_ATTRIBUTE(const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const)) +#else +// Since const functions are more restrictive pure function, we'll fallback to a +// pure function if the const attribute is not handled. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#endif + +// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function +// parameter or implicit object parameter is retained by the return value of the +// annotated function (or, for a parameter of a constructor, in the value of the +// constructed object). This attribute causes warnings to be produced if a +// temporary object does not live long enough. +// +// When applied to a reference parameter, the referenced object is assumed to be +// retained by the return value of the function. When applied to a non-reference +// parameter (for example, a pointer or a class type), all temporaries +// referenced by the parameter are assumed to be retained by the return value of +// the function. +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound +// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]] +#elif ABSL_HAVE_ATTRIBUTE(lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) +#else +#define ABSL_ATTRIBUTE_LIFETIME_BOUND +#endif + +// Internal attribute; name and documentation TBD. +// +// See the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by) +#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \ + [[clang::lifetime_capture_by(Owner)]] +#else +#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) +#endif + +// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it +// points to, similarly to a span, string_view, or other non-owning reference +// type. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template +// StringView(const R&); +// }; +// +// StringView f(std::string s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional sv) { return *sv; } +// +// See the following links for details: +// https://reviews.llvm.org/D64448 +// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]] +#else +#define ABSL_ATTRIBUTE_VIEW +#endif + +// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or +// similar class that owns all the data that it points to. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template +// StringView(const R&); +// }; +// +// struct ABSL_ATTRIBUTE_OWNER String {}; +// +// StringView f(String s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional sv) { return *sv; } +// +// See the following links for details: +// https://reviews.llvm.org/D64448 +// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]] +#else +#define ABSL_ATTRIBUTE_OWNER +#endif + +// ABSL_ATTRIBUTE_TRIVIAL_ABI +// Indicates that a type is "trivially relocatable" -- meaning it can be +// relocated without invoking the constructor/destructor, using a form of move +// elision. +// +// From a memory safety point of view, putting aside destructor ordering, it's +// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location +// can change over the course of its lifetime: if a constructor can be run one +// place, and then the object magically teleports to another place where some +// methods are run, and then the object teleports to yet another place where it +// is destroyed. This is notably not true for self-referential types, where the +// move-constructor must keep the self-reference up to date. If the type changed +// location without invoking the move constructor, it would have a dangling +// self-reference. +// +// The use of this teleporting machinery means that the number of paired +// move/destroy operations can change, and so it is a bad idea to apply this to +// a type meant to count the number of moves. +// +// Warning: applying this can, rarely, break callers. Objects passed by value +// will be destroyed at the end of the call, instead of the end of the +// full-expression containing the call. In addition, it changes the ABI +// of functions accepting this type by value (e.g. to pass in registers). +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi +// +// b/321691395 - This is currently disabled in open-source builds since +// compiler support differs. If system libraries compiled with GCC are mixed +// with libraries compiled with Clang, types will have different ideas about +// their ABI, leading to hard to debug crashes. +#define ABSL_ATTRIBUTE_TRIVIAL_ABI + +// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS +// +// Indicates a data member can be optimized to occupy no space (if it is empty) +// and/or its tail padding can be used for other members. +// +// For code that is assured to only build with C++20 or later, prefer using +// the standard attribute `[[no_unique_address]]` directly instead of this +// macro. +// +// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address +// Current versions of MSVC have disabled `[[no_unique_address]]` since it +// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for +// situations when it can be assured that it is desired. Since Abseil does not +// claim ABI compatibility in mixed builds, we can offer it unconditionally. +#if defined(_MSC_VER) && _MSC_VER >= 1929 +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address) +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_UNINITIALIZED +// +// GCC and Clang support a flag `-ftrivial-auto-var-init=